Add checkstyle, format existing code accordingly.

This commit is contained in:
Player 2019-10-27 03:39:47 +01:00
parent d1753d4af9
commit dfdb52d6e5
301 changed files with 3209 additions and 2520 deletions

1
.gitignore vendored
View file

@ -2,6 +2,7 @@
.gradle
# Eclipse
.checkstyle
.classpath
.metadata
.settings

View file

@ -43,6 +43,7 @@ def getBranch(){
}
allprojects {
apply plugin: 'checkstyle'
apply plugin: 'maven-publish'
apply plugin: 'fabric-loom'
apply plugin: 'net.minecrell.licenser'
@ -52,8 +53,6 @@ allprojects {
group = "net.fabricmc.fabric-api"
dependencies {
minecraft "com.mojang:minecraft:$Globals.mcVersion"
mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}"
@ -105,9 +104,14 @@ allprojects {
classifier = 'sources'
from sourceSets.main.allSource
}
checkstyle {
configFile = rootProject.file("checkstyle.xml")
toolVersion = '8.25'
}
}
javadoc{
javadoc {
options.memberLevel = "PACKAGE"
allprojects.each{
source( it.sourceSets.main.allJava.srcDirs)

162
checkstyle.xml Normal file
View file

@ -0,0 +1,162 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="fileExtensions" value="java"/>
<module name="NewlineAtEndOfFile"/>
<!-- disallow trailing whitespace -->
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="message" value="trailing whitespace"/>
</module>
<!-- note: RegexpMultiline shows nicer messages than Regexp, but has to be outside TreeWalker -->
<!-- disallow multiple consecutive blank lines -->
<module name="RegexpMultiline">
<property name="format" value="\n[\r\t ]*\n[\r\t ]*\n"/>
<property name="message" value="adjacent blank lines"/>
</module>
<!-- disallow blank after { -->
<module name="RegexpMultiline">
<property name="format" value="\{[\r\t ]*\n[\r\t ]*\n"/>
<property name="message" value="blank line after '{'"/>
</module>
<!-- disallow blank before } -->
<module name="RegexpMultiline">
<property name="format" value="\n[\r\t ]*\n[\r\t ]*\}"/>
<property name="message" value="blank line before '}'"/>
</module>
<!-- require blank before { in the same indentation level -->
<module name="RegexpMultiline">
<!-- the regex works as follows:
It matches (=fails) for \n<indentation><something>\n<same indentation><control statement>[...]{\n
while <something> is a single line comment, it'll look for a blank line one line earlier
if <something> is a space, indicating a formatting error or ' */', it'll ignore the instance
if <something> is a tab, indicating a continued line, it'll ignore the instance
<control statement> is 'if', 'do', 'while', 'for', 'try' or nothing (instance initializer block)
- first \n: with positive lookbehind (?<=\n) to move the error marker to a more reasonable place
- capture tabs for <indentation>, later referenced via \1
- remaining preceding line as a non-comment (doesn't start with '/', '//', ' ' or '\t') or multiple lines where all but the first are a single line comment with the same indentation
- new line
- <indentation> as captured earlier
- <control statement> as specified above
- { before the next new line -->
<property name="format" value="(?&lt;=\n)([\t]+)(?:[^/\n \t][^\n]*|/[^/\n][^\n]*|[^/\n][^\n]*(\n\1//[^\n]*)+)\n\1(|(if|do|while|for|try)[^\n]+)\{[\r\t ]*\n"/>
<property name="message" value="missing blank line before block at same indentation level"/>
</module>
<!-- require blank after } in the same indentation level -->
<module name="RegexpMultiline">
<!-- \n<indentation>}\n<same indentation><whatever unless newline, '}' or starting with cas(e) or def(ault)> -->
<property name="format" value="(?&lt;=\n)([\t]+)\}\n\1(?:[^\r\n\}cd]|c[^\r\na]|ca[^\r\ns]|d[^\r\ne]|de[^\r\nf])"/>
<property name="message" value="missing blank line after block at same indentation level"/>
</module>
<module name="TreeWalker">
<!-- Ensure all imports are ship shape -->
<module name="AvoidStarImport"/>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports"/>
<module name="ImportOrder">
<property name="groups" value="java,javax,*,net.minecraft,net.fabricmc"/>
<property name="ordered" value="false"/><!-- the plugin orders alphabetically without considering separators.. -->
<property name="separated" value="true"/>
<property name="option" value="top"/>
<property name="sortStaticImportsAlphabetically" value="true"/>
</module>
<!-- Ensures braces are at the end of a line -->
<module name="LeftCurly"/>
<module name="RightCurly"/>
<!-- single line statements on one line, -->
<module name="NeedBraces">
<property name="tokens" value="LITERAL_IF,LITERAL_FOR,LITERAL_WHILE"/>
<property name="allowSingleLineStatement" value="true"/>
</module>
<module name="NeedBraces">
<property name="tokens" value="LITERAL_ELSE,LITERAL_DO"/>
<property name="allowSingleLineStatement" value="false"/>
</module>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
<property name="allowMultipleEmptyLines" value="false"/>
<!-- exclude METHOD_DEF and VARIABLE_DEF -->
<property name="tokens" value="PACKAGE_DEF,IMPORT,STATIC_IMPORT,CLASS_DEF,INTERFACE_DEF,ENUM_DEF,STATIC_INIT,INSTANCE_INIT,CTOR_DEF"/>
</module>
<module name="OperatorWrap"/>
<module name="SeparatorWrap">
<property name="tokens" value="DOT,ELLIPSIS,AT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="COMMA,SEMI"/>
<property name="option" value="eol"/>
</module>
<module name="Indentation">
<property name="basicOffset" value="8"/>
<property name="caseIndent" value="0"/>
<property name="throwsIndent" value="8"/>
<property name="arrayInitIndent" value="8"/>
<property name="lineWrappingIndentation" value="16"/>
</module>
<module name="ParenPad"/>
<module name="NoWhitespaceBefore"/>
<module name="NoWhitespaceAfter">
<!-- allow ARRAY_INIT -->
<property name="tokens" value="AT,INC,DEC,UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP"/>
</module>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround">
<!-- Allow PLUS, MINUS, MUL, DIV as they may be more readable without spaces in some cases -->
<property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV_ASSIGN,DO_WHILE,EQUAL,GE,GT,LAMBDA,LAND,LCURLY,LE,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS_ASSIGN,QUESTION,RCURLY,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
</module>
<module name="SingleSpaceSeparator"/>
<module name="GenericWhitespace"/>
<module name="CommentsIndentation"/>
<module name="ArrayTypeStyle"/>
<module name="DefaultComesLast">
<property name="skipIfLastAndSharedWithCase" value="true"/>
</module>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StringLiteralEquality"/>
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<module name="AnnotationLocation"/>
<module name="MissingOverride"/>
<!-- By default this allows catch blocks with only comments -->
<module name="EmptyCatchBlock"/>
<!-- Enforce tabs -->
<module name="RegexpSinglelineJava">
<property name="format" value="^\t* ([^*]|\*[^ /])"/>
<property name="message" value="non-tab indentation"/>
</module>
<module name="OuterTypeFilename"/>
<!--<module name="InvalidJavadocPosition"/>-->
<module name="JavadocParagraph"/>
<module name="JavadocStyle"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param,@return,@throws,@deprecated"/>
</module>
</module>
</module>

View file

@ -32,8 +32,8 @@ public abstract class Event<T> {
/**
* Returns the invoker instance.
* <p>
* An "invoker" is an object which hides multiple registered
*
* <p>An "invoker" is an object which hides multiple registered
* listeners of type T under one instance of type T, executing
* them and leaving early as necessary.
*

View file

@ -16,19 +16,17 @@
package net.fabricmc.fabric.api.event;
import net.fabricmc.fabric.impl.event.EventFactoryImpl;
import java.util.function.Function;
import net.fabricmc.fabric.impl.event.EventFactoryImpl;
/**
* Helper for creating {@link Event} classes.
*/
public final class EventFactory {
private static boolean profilingEnabled = true;
private EventFactory() {
}
private EventFactory() { }
/**
* @return True if events are supposed to be profiled.
@ -61,8 +59,8 @@ public final class EventFactory {
/**
* Create an "array-backed" Event instance with a custom empty invoker.
* <p>
* Having a custom empty invoker (of type (...) -&gt; {}) increases performance
*
* <p>Having a custom empty invoker (of type (...) -&gt; {}) increases performance
* relative to iterating over an empty array; however, it only really matters
* if the event is executed thousands of times a second.
*

View file

@ -22,10 +22,10 @@ import net.minecraft.nbt.Tag;
/**
* NBT type ID constants. Useful for filtering by value type in a few cases.
*
* <p>For the current list of types, check with {@link Tag#TYPES}.
*
* @see CompoundTag#containsKey(String, int)
* @see Tag#idToString(int)
* <p>
* For the current list of types, check with {@link Tag#TYPES}.
*/
public final class NbtType {
public static final int END = 0;
@ -49,7 +49,5 @@ public final class NbtType {
*/
public static final int NUMBER = 99;
private NbtType() {
}
private NbtType() { }
}

View file

@ -16,12 +16,12 @@
package net.fabricmc.fabric.impl.event;
import net.fabricmc.fabric.api.event.Event;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.function.Function;
import net.fabricmc.fabric.api.event.Event;
class ArrayBackedEvent<T> extends Event<T> {
private final Class<? super T> type;
private final Function<T[], T> invokerFactory;

View file

@ -16,8 +16,6 @@
package net.fabricmc.fabric.impl.event;
import net.fabricmc.fabric.api.event.Event;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@ -29,12 +27,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import net.fabricmc.fabric.api.event.Event;
public final class EventFactoryImpl {
private static final List<ArrayBackedEvent<?>> ARRAY_BACKED_EVENTS = new ArrayList<>();
private EventFactoryImpl() {
}
private EventFactoryImpl() { }
public static void invalidate() {
ARRAY_BACKED_EVENTS.forEach(ArrayBackedEvent::update);

View file

@ -16,24 +16,22 @@
package net.fabricmc.fabric.api.biomes.v1;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.minecraft.world.biome.Biome;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
/**
* General API that applies to all biome sources
* General API that applies to all biome sources.
*/
public final class FabricBiomes {
private FabricBiomes() {
}
private FabricBiomes() { }
/**
* Allows players to naturally spawn in this biome
* Allows players to naturally spawn in this biome.
*
* @param biome a biome the player should be able to spawn in
*/
public static void addSpawnBiome(Biome biome) {
InternalBiomeData.addSpawnBiome(biome);
}
}

View file

@ -16,16 +16,15 @@
package net.fabricmc.fabric.api.biomes.v1;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.minecraft.world.biome.Biome;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
/**
* API that exposes some internals of the minecraft default biome source for the overworld
* API that exposes some internals of the minecraft default biome source for the overworld.
*/
public final class OverworldBiomes {
private OverworldBiomes() {
}
private OverworldBiomes() { }
/**
* Adds the biome to the specified climate group, with the specified weight. This is only for the biomes that make up the initial continents in generation.
@ -41,7 +40,7 @@ public final class OverworldBiomes {
}
/**
* Adds the biome as a hills variant of the parent biome, with the specified weight
* Adds the biome as a hills variant of the parent biome, with the specified weight.
*
* @param parent the biome to where the hills variant is added
* @param hills the biome to be set as a hills variant
@ -54,7 +53,7 @@ public final class OverworldBiomes {
}
/**
* Adds the biome as a shore/beach biome for the parent biome, with the specified weight
* Adds the biome as a shore/beach biome for the parent biome, with the specified weight.
*
* @param parent the base biome to where the shore biome is added
* @param shore the biome to be added as a shore biome
@ -67,7 +66,7 @@ public final class OverworldBiomes {
}
/**
* Adds the biome as an an edge biome (excluding as a beach) of the parent biome, with the specified weight
* Adds the biome as an an edge biome (excluding as a beach) of the parent biome, with the specified weight.
*
* @param parent the base biome to where the edge biome is added
* @param edge the biome to be added as an edge biome
@ -81,7 +80,8 @@ public final class OverworldBiomes {
/**
* Adds a 'variant' biome which replaces another biome on occasion.
* For example, addBiomeVariant(Biomes.JUNGLE, Biomes.DESERT, 0.2) will replace 20% of jungles with deserts.
*
* <p>For example, addBiomeVariant(Biomes.JUNGLE, Biomes.DESERT, 0.2) will replace 20% of jungles with deserts.
* This method is rather useful for replacing biomes not generated through standard methods, such as oceans,
* deep oceans, jungles, mushroom islands, etc. When replacing ocean and deep ocean biomes, one must specify
* the biome without temperature (Biomes.OCEAN / Biomes.DEEP_OCEAN) only, as ocean temperatures have not been
@ -107,5 +107,4 @@ public final class OverworldBiomes {
public static void setRiverBiome(Biome parent, Biome river) {
InternalBiomeData.setOverworldRiverBiome(parent, river);
}
}

View file

@ -17,27 +17,26 @@
package net.fabricmc.fabric.api.biomes.v1;
/**
* Represents the climates of biomes on the overworld continents
* Represents the climates of biomes on the overworld continents.
*/
public enum OverworldClimate {
/**
* Includes Snowy Tundra (with a weight of 3) and Snowy Taiga (with a weight of 1)
* Includes Snowy Tundra (with a weight of 3) and Snowy Taiga (with a weight of 1).
*/
SNOWY,
/**
* Includes Forest, Taiga, Mountains, and Plains (all with weights of 1)
* Includes Forest, Taiga, Mountains, and Plains (all with weights of 1).
*/
COOL,
/**
* Includes Forest, Dark Forest, Mountains, Plains, Birch Forest, and Swamp (all with weights of 1)
* Includes Forest, Dark Forest, Mountains, Plains, Birch Forest, and Swamp (all with weights of 1).
*/
TEMPERATE,
/**
* Includes Desert (with a weight of 3), Savanna (with a weight of 2), and Plains (with a weight of 1)
* Includes Desert (with a weight of 3), Savanna (with a weight of 2), and Plains (with a weight of 1).
*/
DRY
}

View file

@ -19,10 +19,9 @@ package net.fabricmc.fabric.impl.biomes;
import net.minecraft.world.biome.Biome;
/**
* Represents a biome variant and its corresponding chance
* Represents a biome variant and its corresponding chance.
*/
final class BiomeVariant {
private final Biome variant;
private final double chance;
@ -48,5 +47,4 @@ final class BiomeVariant {
double getChance() {
return chance;
}
}

View file

@ -19,7 +19,7 @@ package net.fabricmc.fabric.impl.biomes;
import net.minecraft.world.biome.Biome;
/**
* Represents a biome and its corresponding weight
* Represents a biome and its corresponding weight.
*/
final class ContinentalBiomeEntry {
private final Biome biome;

View file

@ -16,26 +16,30 @@
package net.fabricmc.fabric.impl.biomes;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import net.fabricmc.fabric.api.biomes.v1.OverworldClimate;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import net.minecraft.world.biome.layer.BiomeLayers;
import net.minecraft.world.biome.source.VanillaLayeredBiomeSource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import net.fabricmc.fabric.api.biomes.v1.OverworldClimate;
/**
* Lists and maps for internal use only! Stores data that is used by the various mixins into the world generation
*/
public final class InternalBiomeData {
private InternalBiomeData() {
}
private InternalBiomeData() { }
private static final EnumMap<OverworldClimate, WeightedBiomePicker> OVERWORLD_MODDED_CONTINENTAL_BIOME_PICKERS = new EnumMap<>(OverworldClimate.class);
private static final Map<Biome, WeightedBiomePicker> OVERWORLD_HILLS_MAP = new HashMap<>();
@ -95,6 +99,7 @@ public final class InternalBiomeData {
public static void setOverworldRiverBiome(Biome primary, Biome river) {
Preconditions.checkArgument(primary != null, "Primary biome is null");
OVERWORLD_RIVER_MAP.put(primary, river);
if (river != null) {
injectOverworldBiome(river);
}
@ -113,7 +118,7 @@ public final class InternalBiomeData {
}
injectBiomeMethod.invoke(null, biome);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | InvocationTargetException e){
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}

View file

@ -16,23 +16,22 @@
package net.fabricmc.fabric.impl.biomes;
import net.fabricmc.fabric.api.biomes.v1.OverworldClimate;
import java.util.List;
import java.util.Map;
import java.util.function.IntConsumer;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import java.util.List;
import java.util.Map;
import java.util.function.IntConsumer;
import net.fabricmc.fabric.api.biomes.v1.OverworldClimate;
/**
* Internal utilities used for biome sampling
* Internal utilities used for biome sampling.
*/
public final class InternalBiomeUtils {
private InternalBiomeUtils() {
}
private InternalBiomeUtils() { }
/**
* @param north raw id of the biome to the north
@ -85,14 +84,17 @@ public final class InternalBiomeUtils {
reqWeightSum -= vanillaArrayWeight;
int low = 0;
int high = moddedBiomes.size() - 1;
while (low < high) {
int mid = (high + low) >>> 1;
if (reqWeightSum < moddedBiomes.get(mid).getUpperWeightBound()) {
high = mid;
} else {
low = mid + 1;
}
}
return low;
}
@ -127,7 +129,7 @@ public final class InternalBiomeUtils {
}
int vanillaArrayWeight = vanillaArray.length;
double reqWeightSum = (double) random.nextInt(Integer.MAX_VALUE) * (vanillaArray.length + picker.getCurrentWeightTotal()) / Integer.MAX_VALUE;
double reqWeightSum = random.nextInt(Integer.MAX_VALUE) * (vanillaArray.length + picker.getCurrentWeightTotal()) / Integer.MAX_VALUE;
if (reqWeightSum < vanillaArray.length) {
// Vanilla biome; look it up from the vanilla array and transform accordingly.

View file

@ -16,17 +16,18 @@
package net.fabricmc.fabric.impl.biomes;
import net.fabricmc.fabric.api.biomes.v1.OverworldClimate;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import net.fabricmc.fabric.api.biomes.v1.OverworldClimate;
/**
* Deals with picking variants for you
* Deals with picking variants for you.
*/
final class VariantTransformer {
private final SubTransformer defaultTransformer = new SubTransformer();
@ -49,7 +50,7 @@ final class VariantTransformer {
}
/**
* Transforms a biome into a variant randomly depending on its chance
* Transforms a biome into a variant randomly depending on its chance.
*
* @param replaced biome to transform
* @param random the {@link LayerRandomnessSource} from the layer
@ -81,7 +82,7 @@ final class VariantTransformer {
}
/**
* Transforms a biome into a variant randomly depending on its chance
* Transforms a biome into a variant randomly depending on its chance.
*
* @param replaced biome to transform
* @param random the {@link LayerRandomnessSource} from the layer
@ -93,6 +94,7 @@ final class VariantTransformer {
return variant.getVariant();
}
}
return replaced;
}
}

View file

@ -16,13 +16,14 @@
package net.fabricmc.fabric.impl.biomes;
import com.google.common.base.Preconditions;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Preconditions;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
/**
* Picks biomes with arbitrary double weights using a binary search.
*/
@ -46,13 +47,13 @@ public final class WeightedBiomePicker {
}
public Biome pickRandom(LayerRandomnessSource random) {
double target = (double) random.nextInt(Integer.MAX_VALUE) * getCurrentWeightTotal() / Integer.MAX_VALUE;
double target = random.nextInt(Integer.MAX_VALUE) * getCurrentWeightTotal() / Integer.MAX_VALUE;
return search(target).getBiome();
}
/**
* Searches with the specified target value
* Searches with the specified target value.
*
* @param target The target value, must satisfy the constraint 0 <= target <= currentTotal
* @return The result of the search
@ -67,6 +68,7 @@ public final class WeightedBiomePicker {
while (low < high) {
int mid = (high + low) >>> 1;
if (target < entries.get(mid).getUpperWeightBound()) {
high = mid;
} else {

View file

@ -16,32 +16,33 @@
package net.fabricmc.fabric.mixin.biomes;
import net.fabricmc.fabric.api.biomes.v1.OverworldBiomes;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.fabricmc.fabric.impl.biomes.InternalBiomeUtils;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.AddEdgeBiomesLayer;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.AddEdgeBiomesLayer;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import net.fabricmc.fabric.api.biomes.v1.OverworldBiomes;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.fabricmc.fabric.impl.biomes.InternalBiomeUtils;
/**
* Adds edges and shores specified in {@link OverworldBiomes#addEdgeBiome(Biome, Biome, double)} and {@link OverworldBiomes#addShoreBiome(Biome, Biome, double)} to the edges layer
* Adds edges and shores specified in {@link OverworldBiomes#addEdgeBiome(Biome, Biome, double)} and {@link OverworldBiomes#addShoreBiome(Biome, Biome, double)} to the edges layer.
*/
@Mixin(AddEdgeBiomesLayer.class)
public class MixinAddEdgeBiomesLayer {
@Inject(at = @At("HEAD"), method = "sample", cancellable = true)
private void sample(LayerRandomnessSource rand, int north, int east, int south, int west, int center, CallbackInfoReturnable<Integer> info) {
Biome centerBiome = Registry.BIOME.get(center);
if (InternalBiomeData.getOverworldShores().containsKey(centerBiome) && InternalBiomeUtils.neighborsOcean(north, east, south, west)) {
info.setReturnValue(Registry.BIOME.getRawId(InternalBiomeData.getOverworldShores().get(centerBiome).pickRandom(rand)));
} else if (InternalBiomeData.getOverworldEdges().containsKey(centerBiome) && InternalBiomeUtils.isEdge(north, east, south, west, center)) {
info.setReturnValue(Registry.BIOME.getRawId(InternalBiomeData.getOverworldEdges().get(centerBiome).pickRandom(rand)));
}
}
}

View file

@ -16,26 +16,27 @@
package net.fabricmc.fabric.mixin.biomes;
import net.fabricmc.fabric.api.biomes.v1.OverworldBiomes;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.fabricmc.fabric.impl.biomes.WeightedBiomePicker;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.AddHillsLayer;
import net.minecraft.world.biome.layer.BiomeLayers;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import net.minecraft.world.biome.layer.LayerSampler;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.fabricmc.fabric.api.biomes.v1.OverworldBiomes;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.fabricmc.fabric.impl.biomes.WeightedBiomePicker;
/**
* Injects hills biomes specified from {@link OverworldBiomes#addHillsBiome(Biome, Biome, double)}into the default hills layer
* Injects hills biomes specified from {@link OverworldBiomes#addHillsBiome(Biome, Biome, double)}into the default hills layer.
*/
@Mixin(AddHillsLayer.class)
public class MixinAddHillsLayer {
@Inject(at = @At("HEAD"), method = "sample", cancellable = true)
private void sample(LayerRandomnessSource rand, LayerSampler biomeSampler, LayerSampler noiseSampler, int chunkX, int chunkZ, CallbackInfoReturnable<Integer> info) {
if (InternalBiomeData.getOverworldHills().isEmpty()) {
@ -67,18 +68,23 @@ public class MixinAddHillsLayer {
if (biomeReturn != biomeId) {
int similarity = 0;
if (BiomeLayers.areSimilar(biomeSampler.sample(chunkX, chunkZ - 1), biomeId)) {
++similarity;
}
if (BiomeLayers.areSimilar(biomeSampler.sample(chunkX + 1, chunkZ), biomeId)) {
++similarity;
}
if (BiomeLayers.areSimilar(biomeSampler.sample(chunkX - 1, chunkZ), biomeId)) {
++similarity;
}
if (BiomeLayers.areSimilar(biomeSampler.sample(chunkX, chunkZ + 1), biomeId)) {
++similarity;
}
if (similarity >= 3) {
info.setReturnValue(biomeReturn);
return;
@ -89,5 +95,4 @@ public class MixinAddHillsLayer {
// Cancel vanilla logic.
info.setReturnValue(biomeId);
}
}

View file

@ -16,13 +16,8 @@
package net.fabricmc.fabric.mixin.biomes;
import net.fabricmc.fabric.api.biomes.v1.OverworldBiomes;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.AddRiversLayer;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import net.minecraft.world.biome.layer.LayerSampler;
import java.util.Map;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -30,14 +25,20 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.AddRiversLayer;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import net.minecraft.world.biome.layer.LayerSampler;
import net.fabricmc.fabric.api.biomes.v1.OverworldBiomes;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
/**
* Sets river biomes specified with {@link OverworldBiomes#setRiverBiome(Biome, Biome)}
* Sets river biomes specified with {@link OverworldBiomes#setRiverBiome(Biome, Biome)}.
*/
@Mixin(AddRiversLayer.class)
public class MixinAddRiversLayer {
@Shadow
@Final
private static int RIVER_ID;
@ -49,10 +50,10 @@ public class MixinAddRiversLayer {
int riverBiomeId = riverSampler.sample(x, z);
Map<Biome, Biome> overworldRivers = InternalBiomeData.getOverworldRivers();
if (overworldRivers.containsKey(landBiome) && riverBiomeId == RIVER_ID) {
Biome riverBiome = overworldRivers.get(landBiome);
info.setReturnValue(riverBiome == null ? landBiomeId : Registry.BIOME.getRawId(riverBiome));
}
}
}

View file

@ -16,9 +16,11 @@
package net.fabricmc.fabric.mixin.biomes;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.BiomeSource;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -26,17 +28,16 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.BiomeSource;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
/**
* Adds spawn biomes to the base {@link BiomeSource} class.
*/
@Mixin(BiomeSource.class)
public class MixinBiomeSource {
@Shadow
@Final
private static List<Biome> SPAWN_BIOMES;
@ -44,9 +45,9 @@ public class MixinBiomeSource {
@Inject(at = @At("RETURN"), cancellable = true, method = "getSpawnBiomes")
private void getSpawnBiomes(CallbackInfoReturnable<List<Biome>> info) {
Set<Biome> biomes = new LinkedHashSet<>(info.getReturnValue());
if (biomes.addAll(InternalBiomeData.getSpawnBiomes())) {
info.setReturnValue(new ArrayList<>(biomes));
}
}
}

View file

@ -16,12 +16,6 @@
package net.fabricmc.fabric.mixin.biomes;
import net.fabricmc.fabric.api.biomes.v1.OverworldClimate;
import net.fabricmc.fabric.impl.biomes.InternalBiomeUtils;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import net.minecraft.world.biome.layer.SetBaseBiomesLayer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
@ -30,12 +24,19 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.LayerRandomnessSource;
import net.minecraft.world.biome.layer.SetBaseBiomesLayer;
import net.fabricmc.fabric.api.biomes.v1.OverworldClimate;
import net.fabricmc.fabric.impl.biomes.InternalBiomeUtils;
/**
* Injects biomes into the arrays of biomes in the {@link SetBaseBiomesLayer}
* Injects biomes into the arrays of biomes in the {@link SetBaseBiomesLayer}.
*/
@Mixin(SetBaseBiomesLayer.class)
public class MixinSetBaseBiomesLayer {
@Shadow
@Final
@Mutable
@ -112,5 +113,4 @@ public class MixinSetBaseBiomesLayer {
info.setReturnValue(InternalBiomeUtils.transformBiome(random, biome, climate));
}
}

View file

@ -16,9 +16,9 @@
package net.fabricmc.fabric.mixin.biomes;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.VanillaLayeredBiomeSource;
import net.minecraft.world.gen.feature.StructureFeature;
import java.util.HashSet;
import java.util.Set;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
@ -27,8 +27,9 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.VanillaLayeredBiomeSource;
import net.minecraft.world.gen.feature.StructureFeature;
/**
* Adds the biomes in world gen to the array for the vanilla layered biome source.
@ -36,14 +37,13 @@ import java.util.Set;
*/
@Mixin(VanillaLayeredBiomeSource.class)
public class MixinVanillaLayeredBiomeSource {
@Shadow
@Final
@Mutable
private static Set<Biome> BIOMES;
@Inject(method = "<clinit>", at = @At("RETURN"))
private static void cinit(CallbackInfo info){
private static void cinit(CallbackInfo info) {
BIOMES = new HashSet<>(BIOMES);
}
@ -51,5 +51,4 @@ public class MixinVanillaLayeredBiomeSource {
private static void fabric_injectBiome(Biome biome) {
BIOMES.add(biome);
}
}

View file

@ -16,31 +16,32 @@
package net.fabricmc.fabric.api.blockrenderlayer.v1;
import net.fabricmc.fabric.impl.blockrenderlayer.BlockRenderLayerMapImpl;
import net.minecraft.block.Block;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item;
import net.fabricmc.fabric.impl.blockrenderlayer.BlockRenderLayerMapImpl;
/**
* Use to associate blocks or fluids with block render layer other than default.
* Replaces the {@code renderLayer} property previously on {@code Block}.<p>
*
* {@code BlockRenderLayer} controls how sprite pixels for fluids and blocks are blended
* with the scene. Consult the vanilla {@code BlockRenderLayer} implementation for examples.<p>
*
* The Fabric Renderer API can be used to control this at a per-quad level at the code
* via {@code BlendMode}.<p>
*
* Client-side only.
* Use to associate blocks or fluids with block render layer other than default.
* Replaces the {@code renderLayer} property previously on {@code Block}.
*
* <p>{@code BlockRenderLayer} controls how sprite pixels for fluids and blocks are blended
* with the scene. Consult the vanilla {@code BlockRenderLayer} implementation for examples.
*
* <p>The Fabric Renderer API can be used to control this at a per-quad level at the code
* via {@code BlendMode}.
*
* <p>Client-side only.
*/
public interface BlockRenderLayerMap {
BlockRenderLayerMap INSTANCE = BlockRenderLayerMapImpl.INSTANCE;
/**
* Map (or re-map) a block state with a render layer. Re-mapping is not recommended but if done, last one in wins.
* Must be called from client thread prior to world load/rendering. Best practice will be to call from mod's client initializer.
*
*
* @param block Identifies block to be mapped.
* @param renderLayer Render layer. Should be one of the layers used for terrain rendering.
*/
@ -58,7 +59,7 @@ public interface BlockRenderLayerMap {
/**
* Map (or re-map) a fluid state with a render layer. Re-mapping is not recommended but if done, last one in wins.
* Must be called from client thread prior to world load/rendering. Best practice will be to call from mod's client initializer.
*
*
* @param fluid Identifies fluid to be mapped.
* @param renderLayer Render layer. Should be one of the layers used for terrain rendering.
*/

View file

@ -20,16 +20,16 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import net.minecraft.block.Block;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.minecraft.block.Block;
import net.minecraft.fluid.Fluid;
public class BlockRenderLayerMapImpl implements BlockRenderLayerMap {
private BlockRenderLayerMapImpl() {}
private BlockRenderLayerMapImpl() { }
@Override
public void putBlock(Block block, RenderLayer renderLayer) {
if (block == null) throw new IllegalArgumentException("Request to map null block to BlockRenderLayer");
@ -53,7 +53,7 @@ public class BlockRenderLayerMapImpl implements BlockRenderLayerMap {
fluidHandler.accept(fluid, renderLayer);
}
public static final BlockRenderLayerMap INSTANCE = new BlockRenderLayerMapImpl();
private static Map<Block, RenderLayer> blockRenderLayerMap = new HashMap<>();

View file

@ -18,25 +18,26 @@ package net.fabricmc.fabric.mixin.blockrenderlayer;
import java.util.Map;
import net.minecraft.class_4696;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.item.Item;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.fabricmc.fabric.impl.blockrenderlayer.BlockRenderLayerMapImpl;
import net.minecraft.class_4696;
import net.minecraft.block.Block;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item;
import net.fabricmc.fabric.impl.blockrenderlayer.BlockRenderLayerMapImpl;
@Mixin(class_4696.class)
public class MixinBlockRenderLayer {
@Shadow private static Map<Block, RenderLayer> field_21469;
@Shadow private static Map<Item, RenderLayer> field_21470;
@Shadow private static Map<Fluid, RenderLayer> field_21471;
@Inject(method = "<clinit>*", at = @At("RETURN"))
private static void onInitialize(CallbackInfo info) {
BlockRenderLayerMapImpl.initialize(field_21469::put, field_21470::put, field_21471::put);

View file

@ -16,11 +16,13 @@
package net.fabricmc.fabric.api.registry;
import java.util.function.Consumer;
import com.mojang.brigadier.CommandDispatcher;
import net.fabricmc.fabric.impl.registry.CommandRegistryImpl;
import net.minecraft.server.command.ServerCommandSource;
import java.util.function.Consumer;
import net.fabricmc.fabric.impl.registry.CommandRegistryImpl;
/**
* Registry for server-side command providers.

View file

@ -16,14 +16,15 @@
package net.fabricmc.fabric.impl.registry;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.server.command.ServerCommandSource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.server.command.ServerCommandSource;
public class CommandRegistryImpl {
public static final CommandRegistryImpl INSTANCE = new CommandRegistryImpl();

View file

@ -17,15 +17,17 @@
package net.fabricmc.fabric.mixin.registrycommands;
import com.mojang.brigadier.CommandDispatcher;
import net.fabricmc.fabric.impl.registry.CommandRegistryImpl;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.fabricmc.fabric.impl.registry.CommandRegistryImpl;
@Mixin(CommandManager.class)
public class MixinCommandManagerIntegrated {
@Shadow

View file

@ -16,27 +16,28 @@
package net.fabricmc.fabric.mixin.registrycommands;
import java.io.File;
import java.net.Proxy;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.datafixers.DataFixer;
import net.fabricmc.fabric.impl.registry.CommandRegistryImpl;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldGenerationProgressListenerFactory;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.dedicated.MinecraftDedicatedServer;
import net.minecraft.util.UserCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.File;
import java.net.Proxy;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldGenerationProgressListenerFactory;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.dedicated.MinecraftDedicatedServer;
import net.minecraft.util.UserCache;
import net.fabricmc.fabric.impl.registry.CommandRegistryImpl;
@Mixin(MinecraftDedicatedServer.class)
public abstract class MixinMinecraftDedicatedServer extends MinecraftServer {
public MixinMinecraftDedicatedServer(File file_1, Proxy proxy_1, DataFixer dataFixer_1, CommandManager serverCommandManager_1, YggdrasilAuthenticationService yggdrasilAuthenticationService_1, MinecraftSessionService minecraftSessionService_1, GameProfileRepository gameProfileRepository_1, UserCache userCache_1, WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory_1, String string_1) {
super(file_1, proxy_1, dataFixer_1, serverCommandManager_1, yggdrasilAuthenticationService_1, minecraftSessionService_1, gameProfileRepository_1, userCache_1, worldGenerationProgressListenerFactory_1, string_1);
}

View file

@ -21,7 +21,5 @@ import net.minecraft.container.Container;
@FunctionalInterface
public interface ContainerScreenFactory<C extends Container> {
AbstractContainerScreen create(C container);
}

View file

@ -16,15 +16,15 @@
package net.fabricmc.fabric.api.client.screen;
import net.fabricmc.fabric.api.container.ContainerFactory;
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
import net.fabricmc.fabric.impl.client.gui.ScreenProviderRegistryImpl;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.container.Container;
import net.minecraft.util.Identifier;
public interface ScreenProviderRegistry {
import net.fabricmc.fabric.api.container.ContainerFactory;
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
import net.fabricmc.fabric.impl.client.gui.ScreenProviderRegistryImpl;
public interface ScreenProviderRegistry {
ScreenProviderRegistry INSTANCE = ScreenProviderRegistryImpl.INSTANCE;
/**
@ -43,5 +43,4 @@ public interface ScreenProviderRegistry {
* @param factory the gui factory, this should return a new {@link AbstractContainerScreen}
*/
void registerFactory(Identifier identifier, ContainerFactory<AbstractContainerScreen> factory);
}

View file

@ -22,7 +22,6 @@ import net.minecraft.util.PacketByteBuf;
@FunctionalInterface
public interface ContainerFactory<T> {
/**
* Creates the new object.
*
@ -33,5 +32,4 @@ public interface ContainerFactory<T> {
* @return the new gui or container
*/
T create(int syncId, Identifier identifier, PlayerEntity player, PacketByteBuf buf);
}

View file

@ -16,18 +16,18 @@
package net.fabricmc.fabric.api.container;
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry;
import net.fabricmc.fabric.impl.container.ContainerProviderImpl;
import java.util.function.Consumer;
import net.minecraft.container.Container;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import java.util.function.Consumer;
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry;
import net.fabricmc.fabric.impl.container.ContainerProviderImpl;
public interface ContainerProviderRegistry {
ContainerProviderRegistry INSTANCE = ContainerProviderImpl.INSTANCE;
/**

View file

@ -16,26 +16,27 @@
package net.fabricmc.fabric.impl.client.gui;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.container.Container;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.client.screen.ContainerScreenFactory;
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry;
import net.fabricmc.fabric.api.container.ContainerFactory;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.fabricmc.fabric.impl.container.ContainerProviderImpl;
import net.fabricmc.fabric.impl.network.PacketTypes;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.container.Container;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.HashMap;
import java.util.Map;
public class ScreenProviderRegistryImpl implements ScreenProviderRegistry {
/**
* Use the instance provided by ScreenProviderRegistry
* Use the instance provided by ScreenProviderRegistry.
*/
public static final ScreenProviderRegistry INSTANCE = new ScreenProviderRegistryImpl();
@ -43,10 +44,12 @@ public class ScreenProviderRegistryImpl implements ScreenProviderRegistry {
private static final Map<Identifier, ContainerFactory<AbstractContainerScreen>> FACTORIES = new HashMap<>();
@Override
public void registerFactory(Identifier identifier, ContainerFactory<AbstractContainerScreen> factory) {
if (FACTORIES.containsKey(identifier)) {
throw new RuntimeException("A factory has already been registered as " + identifier + "!");
}
FACTORIES.put(identifier, factory);
}
@ -54,10 +57,12 @@ public class ScreenProviderRegistryImpl implements ScreenProviderRegistry {
public <C extends Container> void registerFactory(Identifier identifier, ContainerScreenFactory<C> containerScreenFactory) {
registerFactory(identifier, (syncId, identifier1, player, buf) -> {
C container = ContainerProviderImpl.INSTANCE.createContainer(syncId, identifier1, player, buf);
if (container == null) {
LOGGER.error("Could not open container for {} - a null object was created!", identifier1.toString());
return null;
}
return containerScreenFactory.create(container);
});
}
@ -71,10 +76,12 @@ public class ScreenProviderRegistryImpl implements ScreenProviderRegistry {
MinecraftClient.getInstance().execute(() -> {
try {
ContainerFactory<AbstractContainerScreen> factory = FACTORIES.get(identifier);
if (factory == null) {
LOGGER.error("No GUI factory found for {}!", identifier.toString());
return;
}
AbstractContainerScreen gui = factory.create(syncId, identifier, packetContext.getPlayer(), packetByteBuf);
packetContext.getPlayer().container = gui.getContainer();
MinecraftClient.getInstance().openScreen(gui);

View file

@ -16,28 +16,29 @@
package net.fabricmc.fabric.impl.container;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import io.netty.buffer.Unpooled;
import net.fabricmc.fabric.api.container.ContainerFactory;
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
import net.fabricmc.fabric.impl.network.PacketTypes;
import net.fabricmc.fabric.mixin.container.ServerPlayerEntityAccessor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.client.network.packet.CustomPayloadS2CPacket;
import net.minecraft.container.Container;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import net.fabricmc.fabric.api.container.ContainerFactory;
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
import net.fabricmc.fabric.impl.network.PacketTypes;
import net.fabricmc.fabric.mixin.container.ServerPlayerEntityAccessor;
public class ContainerProviderImpl implements ContainerProviderRegistry {
/**
* Use the instance provided by ContainerProviderRegistry
* Use the instance provided by ContainerProviderRegistry.
*/
public static final ContainerProviderImpl INSTANCE = new ContainerProviderImpl();
@ -50,6 +51,7 @@ public class ContainerProviderImpl implements ContainerProviderRegistry {
if (FACTORIES.containsKey(identifier)) {
throw new RuntimeException("A factory has already been registered as " + identifier.toString());
}
FACTORIES.put(identifier, factory);
}
@ -96,19 +98,23 @@ public class ContainerProviderImpl implements ContainerProviderRegistry {
clonedBuf.readUnsignedByte();
Container container = createContainer(syncId, identifier, player, clonedBuf);
if (container == null) {
return;
}
player.container = container;
player.container.addListener(player);
}
public <C extends Container> C createContainer(int syncId, Identifier identifier, PlayerEntity player, PacketByteBuf buf) {
ContainerFactory<Container> factory = FACTORIES.get(identifier);
if (factory == null) {
LOGGER.error("No container factory found for {}!", identifier.toString());
return null;
}
//noinspection unchecked
return (C) factory.create(syncId, identifier, player, buf);
}

View file

@ -20,12 +20,10 @@ package net.fabricmc.fabric.impl.container;
* This is a interface that is present on a ServerPlayerEntity, it allows access to the sync id.
*/
public interface ServerPlayerEntitySyncHook {
/**
* gets and sets the new player sync id, and returns the new value
* Gets and sets the new player sync id, and returns the new value.
*
* @return the new sync id of the player
*/
int fabric_incrementSyncId();
}

View file

@ -16,11 +16,13 @@
package net.fabricmc.fabric.mixin.container;
import net.fabricmc.fabric.impl.container.ServerPlayerEntitySyncHook;
import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.server.network.ServerPlayerEntity;
import net.fabricmc.fabric.impl.container.ServerPlayerEntitySyncHook;
@Mixin(ServerPlayerEntity.class)
public abstract class MixinServerPlayerEntity implements ServerPlayerEntitySyncHook {
@Shadow

View file

@ -16,10 +16,11 @@
package net.fabricmc.fabric.mixin.container;
import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.server.network.ServerPlayerEntity;
@Mixin(ServerPlayerEntity.class)
public interface ServerPlayerEntityAccessor {
@Accessor

View file

@ -21,8 +21,8 @@ import net.fabricmc.fabric.impl.registry.CompostingChanceRegistryImpl;
/**
* Registry of items to 0.0-1.0 values, defining the chance of a given item
* increasing the Composter block's level
* increasing the Composter block's level.
*/
public interface CompostingChanceRegistry extends Item2ObjectMap<Float> {
final CompostingChanceRegistry INSTANCE = new CompostingChanceRegistryImpl();
CompostingChanceRegistry INSTANCE = new CompostingChanceRegistryImpl();
}

View file

@ -16,12 +16,13 @@
package net.fabricmc.fabric.api.registry;
import net.fabricmc.fabric.api.util.Block2ObjectMap;
import net.fabricmc.fabric.impl.registry.FlammableBlockRegistryImpl;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.tag.Tag;
import net.fabricmc.fabric.api.util.Block2ObjectMap;
import net.fabricmc.fabric.impl.registry.FlammableBlockRegistryImpl;
public interface FlammableBlockRegistry extends Block2ObjectMap<FlammableBlockRegistry.Entry> {
static FlammableBlockRegistry getDefaultInstance() {
return getInstance(Blocks.FIRE);
@ -39,7 +40,7 @@ public interface FlammableBlockRegistry extends Block2ObjectMap<FlammableBlockRe
this.add(tag, new Entry(burn, spread));
}
public static final class Entry {
final class Entry {
private final int burn, spread;
public Entry(int burn, int spread) {

View file

@ -23,5 +23,5 @@ import net.fabricmc.fabric.impl.registry.FuelRegistryImpl;
* Registry of items to 0-32767 fuel burn time values, in in-game ticks.
*/
public interface FuelRegistry extends Item2ObjectMap<Integer> {
final FuelRegistry INSTANCE = FuelRegistryImpl.INSTANCE;
FuelRegistry INSTANCE = FuelRegistryImpl.INSTANCE;
}

View file

@ -16,16 +16,17 @@
package net.fabricmc.fabric.api.registry;
import net.minecraft.world.loot.entry.LootEntry;
import net.fabricmc.fabric.impl.registry.LootEntryTypeRegistryImpl;
import net.minecraft.world.loot.entry.LootEntry;
/**
* @deprecated Use {@link net.fabricmc.fabric.api.loot.v1.LootEntryTypeRegistry}
*/
@Deprecated
public interface LootEntryTypeRegistry {
@Deprecated
final LootEntryTypeRegistry INSTANCE = LootEntryTypeRegistryImpl.INSTANCE;
LootEntryTypeRegistry INSTANCE = LootEntryTypeRegistryImpl.INSTANCE;
@Deprecated
void register(LootEntry.Serializer<?> serializer);

View file

@ -16,12 +16,13 @@
package net.fabricmc.fabric.impl.registry;
import net.fabricmc.fabric.api.registry.CompostingChanceRegistry;
import net.minecraft.block.ComposterBlock;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.tag.Tag;
import net.fabricmc.fabric.api.registry.CompostingChanceRegistry;
public class CompostingChanceRegistryImpl implements CompostingChanceRegistry {
@Override
public Float get(ItemConvertible item) {

View file

@ -16,9 +16,10 @@
package net.fabricmc.fabric.impl.registry;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.block.BlockState;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
public interface FireBlockHooks {
FlammableBlockRegistry.Entry fabric_getVanillaEntry(BlockState block);
}

View file

@ -16,20 +16,21 @@
package net.fabricmc.fabric.impl.registry;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourceType;
import net.minecraft.tag.Tag;
import net.minecraft.util.Identifier;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
public class FlammableBlockRegistryImpl implements FlammableBlockRegistry, SimpleSynchronousResourceReloadListener {
private static final FlammableBlockRegistry.Entry REMOVED = new FlammableBlockRegistry.Entry(0, 0);
@ -59,13 +60,16 @@ public class FlammableBlockRegistryImpl implements FlammableBlockRegistry, Simpl
private void reload() {
computedEntries.clear();
// tags take precedence before blocks
for (Tag<Block> tag : registeredEntriesTag.keySet()) {
FlammableBlockRegistry.Entry entry = registeredEntriesTag.get(tag);
for (Block block : tag.values()) {
computedEntries.put(block, entry);
}
}
computedEntries.putAll(registeredEntriesBlock);
/* computedBurnChances.clear();
@ -82,6 +86,7 @@ public class FlammableBlockRegistryImpl implements FlammableBlockRegistry, Simpl
@Override
public Entry get(Block block) {
Entry entry = computedEntries.get(block);
if (entry != null) {
return entry;
} else {

View file

@ -16,17 +16,19 @@
package net.fabricmc.fabric.impl.registry;
import java.util.Map;
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.fabricmc.fabric.api.registry.FuelRegistry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.tag.Tag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Map;
import net.fabricmc.fabric.api.registry.FuelRegistry;
// TODO: Clamp values to 32767 (+ add hook for mods which extend the limit to disable the check?)
public class FuelRegistryImpl implements FuelRegistry {
@ -35,9 +37,7 @@ public class FuelRegistryImpl implements FuelRegistry {
private final Object2IntMap<ItemConvertible> itemCookTimes = new Object2IntLinkedOpenHashMap<>();
private final Object2IntMap<Tag<Item>> tagCookTimes = new Object2IntLinkedOpenHashMap<>();
public FuelRegistryImpl() {
}
public FuelRegistryImpl() { }
@Override
public Integer get(ItemConvertible item) {
@ -49,6 +49,7 @@ public class FuelRegistryImpl implements FuelRegistry {
if (cookTime > 32767) {
LOGGER.warn("Tried to register an overly high cookTime: " + cookTime + " > 32767! (" + item + ")");
}
itemCookTimes.put(item, cookTime.intValue());
}
@ -57,6 +58,7 @@ public class FuelRegistryImpl implements FuelRegistry {
if (cookTime > 32767) {
LOGGER.warn("Tried to register an overly high cookTime: " + cookTime + " > 32767! (" + tag.getId() + ")");
}
tagCookTimes.put(tag, cookTime.intValue());
}
@ -84,6 +86,7 @@ public class FuelRegistryImpl implements FuelRegistry {
// tags take precedence before blocks
for (Tag<Item> tag : tagCookTimes.keySet()) {
int time = tagCookTimes.getInt(tag);
if (time <= 0) {
for (Item i : tag.values()) {
map.remove(i);
@ -97,6 +100,7 @@ public class FuelRegistryImpl implements FuelRegistry {
for (ItemConvertible item : itemCookTimes.keySet()) {
int time = itemCookTimes.getInt(item);
if (time <= 0) {
map.remove(item.asItem());
} else {

View file

@ -16,11 +16,12 @@
package net.fabricmc.fabric.impl.registry;
import net.fabricmc.fabric.api.registry.LootEntryTypeRegistry;
import java.lang.reflect.Method;
import net.minecraft.world.loot.entry.LootEntries;
import net.minecraft.world.loot.entry.LootEntry;
import java.lang.reflect.Method;
import net.fabricmc.fabric.api.registry.LootEntryTypeRegistry;
@Deprecated
public final class LootEntryTypeRegistryImpl implements LootEntryTypeRegistry {
@ -29,6 +30,7 @@ public final class LootEntryTypeRegistryImpl implements LootEntryTypeRegistry {
static {
Method target = null;
for (Method m : LootEntries.class.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0] == LootEntry.Serializer.class) {
if (target != null) {
@ -47,8 +49,7 @@ public final class LootEntryTypeRegistryImpl implements LootEntryTypeRegistry {
}
}
private LootEntryTypeRegistryImpl() {
}
private LootEntryTypeRegistryImpl() { }
@Override
public void register(LootEntry.Serializer<?> serializer) {

View file

@ -16,15 +16,17 @@
package net.fabricmc.fabric.mixin.registryextras;
import net.fabricmc.fabric.impl.registry.FuelRegistryImpl;
import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.item.Item;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.item.Item;
import net.fabricmc.fabric.impl.registry.FuelRegistryImpl;
@Mixin(AbstractFurnaceBlockEntity.class)
public class MixinAbstractFurnaceBlockEntity {
@ -32,4 +34,4 @@ public class MixinAbstractFurnaceBlockEntity {
private static void fuelTimeMapHook(CallbackInfoReturnable<Map<Item, Integer>> info) {
FuelRegistryImpl.INSTANCE.apply(info.getReturnValue());
}
}
}

View file

@ -16,13 +16,6 @@
package net.fabricmc.fabric.mixin.registryextras;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.fabricmc.fabric.impl.registry.FireBlockHooks;
import net.fabricmc.fabric.impl.registry.FlammableBlockRegistryImpl;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.FireBlock;
import net.minecraft.state.property.Properties;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -30,6 +23,15 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.FireBlock;
import net.minecraft.state.property.Properties;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.fabricmc.fabric.impl.registry.FireBlockHooks;
import net.fabricmc.fabric.impl.registry.FlammableBlockRegistryImpl;
@Mixin(FireBlock.class)
public class MixinFireBlock implements FireBlockHooks {
private FlammableBlockRegistryImpl fabric_registry;
@ -52,6 +54,7 @@ public class MixinFireBlock implements FireBlockHooks {
@Inject(at = @At("HEAD"), method = "getBurnChance", cancellable = true)
private void getFabricBurnChance(BlockState block, CallbackInfoReturnable info) {
FlammableBlockRegistry.Entry entry = fabric_registry.getFabric(block.getBlock());
if (entry != null) {
// TODO: use a (BlockState -> int) with this as the default impl
if (block.contains(Properties.WATERLOGGED) && block.get(Properties.WATERLOGGED)) {
@ -65,6 +68,7 @@ public class MixinFireBlock implements FireBlockHooks {
@Inject(at = @At("HEAD"), method = "getSpreadChance", cancellable = true)
private void getFabricSpreadChance(BlockState block, CallbackInfoReturnable info) {
FlammableBlockRegistry.Entry entry = fabric_registry.getFabric(block.getBlock());
if (entry != null) {
// TODO: use a (BlockState -> int) with this as the default impl
if (block.contains(Properties.WATERLOGGED) && block.get(Properties.WATERLOGGED)) {

View file

@ -16,18 +16,20 @@
package net.fabricmc.fabric.mixin.crash;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.crash.CrashReportSection;
import java.util.Map;
import java.util.TreeMap;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
import java.util.TreeMap;
import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.crash.CrashReportSection;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
@Mixin(CrashReport.class)
public abstract class MixinCrashReport {
@ -38,6 +40,7 @@ public abstract class MixinCrashReport {
private void fillSystemDetails(CallbackInfo info) {
getSystemDetailsSection().add("Fabric Mods", () -> {
Map<String, String> mods = new TreeMap<>();
for (ModContainer container : FabricLoader.getInstance().getAllMods()) {
mods.put(container.getMetadata().getId(), container.getMetadata().getName() + " " + container.getMetadata().getVersion().getFriendlyString());
}

View file

@ -20,7 +20,6 @@ import net.minecraft.block.pattern.BlockPattern;
import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.Direction;
import net.minecraft.world.dimension.DimensionType;
/**
* Responsible for placing an Entity once they have entered a dimension.
@ -35,7 +34,7 @@ public interface EntityPlacer {
* Handles the placement of an entity going to a dimension.
* Utilized by {@link FabricDimensions#teleport(Entity, DimensionType, EntityPlacer)} to specify placement logic when needed.
*
* <p> This method may have side effects such as the creation of a portal in the target dimension,
* <p>This method may have side effects such as the creation of a portal in the target dimension,
* or the creation of a chunk loading ticket.
*
* @param portalDir the direction the portal is facing, meaningless if no portal was used

View file

@ -16,6 +16,8 @@
package net.fabricmc.fabric.api.dimension.v1;
import java.util.function.BiFunction;
import com.google.common.base.Preconditions;
import net.minecraft.entity.Entity;
@ -29,8 +31,6 @@ import net.minecraft.world.biome.VoronoiBiomeAccessType;
import net.minecraft.world.dimension.Dimension;
import net.minecraft.world.dimension.DimensionType;
import java.util.function.BiFunction;
/**
* An extended version of {@link DimensionType} with automatic raw id management and default placement settings.
* {@code FabricDimensionType} instances are constructed and registered through a {@link Builder}.
@ -42,7 +42,7 @@ import java.util.function.BiFunction;
public final class FabricDimensionType extends DimensionType {
private final EntityPlacer defaultPlacement;
private int desiredRawId;
/** The fixed raw id for this dimension type, set through reflection */
/** The fixed raw id for this dimension type, set through reflection. */
private int fixedRawId;
/**
@ -77,7 +77,7 @@ public final class FabricDimensionType extends DimensionType {
/**
* Return the current raw id for this dimension type.
*
* <p> The returned id is guaranteed to be unique and persistent in a save,
* <p>The returned id is guaranteed to be unique and persistent in a save,
* as well as synchronized between a server and its connected clients.
* It may change when connecting to a different server or opening a new save.
*
@ -131,7 +131,7 @@ public final class FabricDimensionType extends DimensionType {
* Set the default placer used when teleporting entities to dimensions of the built type.
* The default placer must be set before building a dimension type.
*
* <p> A dimension type's default placer must never return {@code null} when its
* <p>A dimension type's default placer must never return {@code null} when its
* {@link EntityPlacer#placeEntity(Entity, ServerWorld, Direction, double, double) placeEntity} method
* is called.
*
@ -194,7 +194,7 @@ public final class FabricDimensionType extends DimensionType {
* If this method is not called, the value defaults to the raw registry id
* of the dimension type.
*
* <p> A Fabric Dimension's desired raw id is used as its actual raw id
* <p>A Fabric Dimension's desired raw id is used as its actual raw id
* when it does not conflict with any existing id, and the world
* save does not map the dimension to a different raw id.
*
@ -212,7 +212,7 @@ public final class FabricDimensionType extends DimensionType {
/**
* Build and register a {@code FabricDimensionType}.
*
* <p> The {@code dimensionId} is used as a registry ID, and as
* <p>The {@code dimensionId} is used as a registry ID, and as
* a unique name both for the dimension suffix and the save directory.
*
* @param dimensionId the id used to name and register the dimension
@ -225,7 +225,7 @@ public final class FabricDimensionType extends DimensionType {
Preconditions.checkArgument(Registry.DIMENSION.get(dimensionId) == null);
Preconditions.checkState(this.defaultPlacer != null, "No defaultPlacer has been specified!");
Preconditions.checkState(this.factory != null, "No dimension factory has been specified!");
String suffix = dimensionId.getNamespace() + "_" + dimensionId.getPath();
String saveDir = "DIM_" + dimensionId.getNamespace() + "_" + dimensionId.getPath();
FabricDimensionType built = new FabricDimensionType(suffix, saveDir, this);

View file

@ -17,10 +17,12 @@
package net.fabricmc.fabric.api.dimension.v1;
import com.google.common.base.Preconditions;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
import net.minecraft.entity.Entity;
import net.minecraft.world.dimension.DimensionType;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
/**
* This class consists exclusively of static methods that operate on world dimensions.
*/
@ -32,10 +34,10 @@ public final class FabricDimensions {
/**
* Teleports an entity to a different dimension, using custom placement logic.
*
* <p> This method behaves as if:
* <p>This method behaves as if:
* <pre>{@code teleported.changeDimension(destination)}</pre>
*
* <p> If {@code destination} is a {@link FabricDimensionType}, the placement logic used
* <p>If {@code destination} is a {@link FabricDimensionType}, the placement logic used
* is {@link FabricDimensionType#getDefaultPlacement()}. If {@code destination} is
* the nether or the overworld, the default logic is the vanilla path.
* For any other dimension, the default placement behaviour is undefined.
@ -43,7 +45,7 @@ public final class FabricDimensions {
* {@code lastPortalDirectionVector}, and {@code lastPortalDirection} fields should be updated
* before calling this method.
*
* <p> After calling this method, {@code teleported} may be invalidated. Callers should use
* <p>After calling this method, {@code teleported} may be invalidated. Callers should use
* the returned entity for any further manipulation.
*
* @param teleported the entity to teleport
@ -58,12 +60,12 @@ public final class FabricDimensions {
/**
* Teleports an entity to a different dimension, using custom placement logic.
*
* <p> If {@code customPlacement} is {@code null}, this method behaves as if:
* <p>If {@code customPlacement} is {@code null}, this method behaves as if:
* <pre>{@code teleported.changeDimension(destination)}</pre>
* The {@code customPlacement} may itself return {@code null}, in which case
* the default placement logic for that dimension will be run.
*
* <p> If {@code destination} is a {@link FabricDimensionType}, the default placement logic
* <p>If {@code destination} is a {@link FabricDimensionType}, the default placement logic
* is {@link FabricDimensionType#getDefaultPlacement()}. If {@code destination} is the nether
* or the overworld, the default logic is the vanilla path.
* For any other dimension, the default placement behaviour is undefined.
@ -71,7 +73,7 @@ public final class FabricDimensions {
* {@code lastPortalDirectionVector}, and {@code lastPortalDirection} fields should be updated
* before calling this method.
*
* <p> After calling this method, {@code teleported} may be invalidated. Callers should use
* <p>After calling this method, {@code teleported} may be invalidated. Callers should use
* the returned entity for any further manipulation.
*
* @param teleported the entity to teleport

View file

@ -16,12 +16,15 @@
package net.fabricmc.fabric.impl.dimension;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensionType;
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
import net.fabricmc.fabric.impl.registry.RemapException;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.Packet;
import net.minecraft.util.Identifier;
@ -30,10 +33,9 @@ import net.minecraft.util.registry.Registry;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.level.LevelProperties;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensionType;
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
import net.fabricmc.fabric.impl.registry.RemapException;
/**
* Handles fixing raw dimension ids between saves and servers,
@ -72,6 +74,7 @@ public class DimensionIdsFixer {
setFixedRawId(fabricDimension, fabricDimension.getDesiredRawId());
} else {
Identifier existing = fixedIds.put(dimensionType.getRawId(), id);
if (existing != null) {
throw new RemapException("Two non-fabric dimensions have the same raw dim id (" + dimensionType.getRawId() + ") : " + existing + " and " + id);
}
@ -89,6 +92,7 @@ public class DimensionIdsFixer {
}
DimensionType dim = DimensionType.byId(dimId);
if (dim instanceof FabricDimensionType) {
setFixedRawId((FabricDimensionType) dim, savedRawId);
} else {
@ -100,6 +104,7 @@ public class DimensionIdsFixer {
// step 3: de-duplicate raw ids for dimensions which ids are not fixed yet
int nextFreeId = 0;
for (FabricDimensionType fabricDimension : fabricDimensions) {
int rawDimId = fabricDimension.getRawId();
Identifier dimId = Objects.requireNonNull(DimensionType.getId(fabricDimension));

View file

@ -19,7 +19,7 @@ package net.fabricmc.fabric.impl.dimension;
import net.minecraft.nbt.CompoundTag;
/**
* An object holding a raw id -> full id map for fabric dimensions
* An object holding a raw id -> full id map for fabric dimensions.
*/
public interface DimensionIdsHolder {
CompoundTag fabric_getDimensionIds();

View file

@ -16,18 +16,20 @@
package net.fabricmc.fabric.impl.dimension;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.fabricmc.fabric.api.network.PacketContext;
import net.fabricmc.fabric.impl.registry.RemapException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.text.LiteralText;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.fabricmc.fabric.api.network.PacketContext;
import net.fabricmc.fabric.impl.registry.RemapException;
/**
* Client entry point for fabric-dimensions
* Client entry point for fabric-dimensions.
*/
public final class FabricDimensionClientInit {
private static final Logger LOGGER = LogManager.getLogger();
@ -55,8 +57,7 @@ public final class FabricDimensionClientInit {
LOGGER.error("Dimension id remapping failed!", e);
MinecraftClient.getInstance().execute(() -> ((ClientPlayerEntity) ctx.getPlayer()).networkHandler.getConnection().disconnect(
new LiteralText("Dimension id remapping failed: " + e)
new LiteralText("Dimension id remapping failed: " + e)
));
}
}

View file

@ -17,17 +17,19 @@
package net.fabricmc.fabric.impl.dimension;
import com.google.common.base.Preconditions;
import net.fabricmc.fabric.api.dimension.v1.EntityPlacer;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensionType;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensions;
import net.fabricmc.fabric.mixin.EntityHooks;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.block.pattern.BlockPattern;
import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.Direction;
import net.minecraft.world.dimension.DimensionType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.fabricmc.fabric.api.dimension.v1.EntityPlacer;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensionType;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensions;
import net.fabricmc.fabric.mixin.EntityHooks;
public final class FabricDimensionInternals {
private FabricDimensionInternals() {
@ -38,11 +40,11 @@ public final class FabricDimensionInternals {
public static final Logger LOGGER = LogManager.getLogger();
/**
* The entity currently being transported to another dimension
* The entity currently being transported to another dimension.
*/
private static final ThreadLocal<Entity> PORTAL_ENTITY = new ThreadLocal<>();
/**
* The custom placement logic passed from {@link FabricDimensions#teleport(Entity, DimensionType, EntityPlacer)}
* The custom placement logic passed from {@link FabricDimensions#teleport(Entity, DimensionType, EntityPlacer)}.
*/
private static EntityPlacer customPlacement;
@ -65,9 +67,11 @@ public final class FabricDimensionInternals {
// Set values used by `PortalForcer#changeDimension` to prevent a NPE crash.
EntityHooks access = ((EntityHooks) entity);
if (entity.getLastPortalDirectionVector() == null) {
access.setLastPortalDirectionVector(entity.getRotationVector());
}
if (entity.getLastPortalDirection() == null) {
access.setLastPortalDirection(entity.getHorizontalFacing());
}
@ -86,6 +90,7 @@ public final class FabricDimensionInternals {
// Custom placement logic, falls back to default dimension placement if no placement or target found
EntityPlacer customPlacement = FabricDimensionInternals.customPlacement;
if (customPlacement != null) {
BlockPattern.TeleportTarget customTarget = customPlacement.placeEntity(teleported, destination, portalDir, portalX, portalY);
@ -96,12 +101,14 @@ public final class FabricDimensionInternals {
// Default placement logic, falls back to vanilla if not a fabric dimension
DimensionType dimType = destination.getDimension().getType();
if (dimType instanceof FabricDimensionType) {
BlockPattern.TeleportTarget defaultTarget = ((FabricDimensionType) dimType).getDefaultPlacement().placeEntity(teleported, destination, portalDir, portalX, portalY);
if (defaultTarget == null) {
throw new IllegalStateException("Mod dimension " + DimensionType.getId(dimType) + " returned an invalid teleport target");
}
return defaultTarget;
}
@ -121,5 +128,4 @@ public final class FabricDimensionInternals {
customPlacement = null;
}
}
}

View file

@ -16,11 +16,12 @@
package net.fabricmc.fabric.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(Entity.class)
public interface EntityHooks {
@ -29,5 +30,4 @@ public interface EntityHooks {
@Accessor
void setLastPortalDirection(Direction dir);
}

View file

@ -16,17 +16,18 @@
package net.fabricmc.fabric.mixin;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
import net.minecraft.entity.Entity;
import net.minecraft.world.dimension.DimensionType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.entity.Entity;
import net.minecraft.world.dimension.DimensionType;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
@Mixin(Entity.class)
public abstract class MixinEntity {
// Inject right before the direction vector is retrieved by the game
@Inject(method = "changeDimension", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getLastPortalDirectionVector()Lnet/minecraft/util/math/Vec3d;"))
private void onGetPortal(DimensionType dimension, CallbackInfoReturnable<Entity> cir) {

View file

@ -16,7 +16,13 @@
package net.fabricmc.fabric.mixin;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.block.pattern.BlockPattern;
import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld;
@ -24,12 +30,8 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.PortalForcer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
@Mixin(PortalForcer.class)
public abstract class MixinPortalForcer {

View file

@ -16,13 +16,14 @@
package net.fabricmc.fabric.mixin.idremap;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.dimension.DimensionType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.dimension.DimensionType;
// NOTE: This probably goes into dimension-fixes
@Mixin(DimensionType.class)
public abstract class MixinDimensionRawIndexFix {

View file

@ -17,18 +17,20 @@
package net.fabricmc.fabric.mixin.idremap;
import com.mojang.datafixers.DataFixer;
import net.fabricmc.fabric.impl.dimension.DimensionIdsFixer;
import net.fabricmc.fabric.impl.dimension.DimensionIdsHolder;
import net.fabricmc.fabric.impl.dimension.DimensionRemapException;
import net.fabricmc.fabric.impl.registry.RemapException;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.LevelProperties;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.LevelProperties;
import net.fabricmc.fabric.impl.dimension.DimensionIdsFixer;
import net.fabricmc.fabric.impl.dimension.DimensionIdsHolder;
import net.fabricmc.fabric.impl.dimension.DimensionRemapException;
import net.fabricmc.fabric.impl.registry.RemapException;
@Mixin(LevelProperties.class)
public abstract class MixinLevelProperties implements DimensionIdsHolder {
@Unique
@ -42,6 +44,7 @@ public abstract class MixinLevelProperties implements DimensionIdsHolder {
@Inject(method = "<init>(Lnet/minecraft/nbt/CompoundTag;Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/CompoundTag;)V", at = @At("RETURN"))
private void readDimensionIds(CompoundTag data, DataFixer fixer, int version, CompoundTag player, CallbackInfo ci) {
CompoundTag savedIds = data.getCompound("fabric_DimensionIds");
try {
this.fabricDimensionIds = DimensionIdsFixer.apply(savedIds);
} catch (RemapException e) {

View file

@ -16,12 +16,14 @@
package net.fabricmc.fabric.mixin.idremap;
import net.fabricmc.fabric.impl.dimension.DimensionRemapException;
import net.minecraft.world.level.storage.LevelStorage;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import net.minecraft.world.level.storage.LevelStorage;
import net.fabricmc.fabric.impl.dimension.DimensionRemapException;
@Mixin(LevelStorage.class)
public abstract class MixinLevelStorage {
@ModifyArg(method = "readLevelProperties", at = @At(value = "INVOKE", target = "Lorg/apache/logging/log4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false), index = 2)

View file

@ -16,20 +16,22 @@
package net.fabricmc.fabric.mixin.idremap;
import net.fabricmc.fabric.impl.dimension.DimensionIdsFixer;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
import net.minecraft.network.ClientConnection;
import net.minecraft.server.PlayerManager;
import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.network.ClientConnection;
import net.minecraft.server.PlayerManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.fabricmc.fabric.impl.dimension.DimensionIdsFixer;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
@Mixin(PlayerManager.class)
public abstract class MixinPlayerManager {
/**
* Synchronizes raw dimension ids to connecting players
* Synchronizes raw dimension ids to connecting players.
*/
@Inject(method = "onPlayerConnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/packet/DifficultyS2CPacket;<init>(Lnet/minecraft/world/Difficulty;Z)V"))
private void onPlayerConnect(ClientConnection conn, ServerPlayerEntity player, CallbackInfo info) {

View file

@ -16,14 +16,16 @@
package net.fabricmc.fabric.mixin.idremap;
import net.fabricmc.fabric.impl.dimension.DimensionIdsHolder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.LevelProperties;
import net.minecraft.world.level.UnmodifiableLevelProperties;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.LevelProperties;
import net.minecraft.world.level.UnmodifiableLevelProperties;
import net.fabricmc.fabric.impl.dimension.DimensionIdsHolder;
@Mixin(UnmodifiableLevelProperties.class)
public abstract class MixinUnmodifiableLevelProperties implements DimensionIdsHolder {
@Shadow
@ -31,7 +33,7 @@ public abstract class MixinUnmodifiableLevelProperties implements DimensionIdsHo
private LevelProperties properties;
/**
* Delegates to the main level properties
* Delegates to the main level properties.
*/
@Override
public CompoundTag fabric_getDimensionIds() {

View file

@ -16,31 +16,33 @@
package net.fabricmc.fabric.api.event.client.player;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.hit.HitResult;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* This event is emitted during the block-picking process. It can be used to
* modify the returned ItemStack, as well as nullify it - returning an empty
* ItemStack will cause the event to leave, and no block to be picked.
*/
public interface ClientPickBlockApplyCallback {
public static final Event<ClientPickBlockApplyCallback> EVENT = EventFactory.createArrayBacked(ClientPickBlockApplyCallback.class,
(listeners) -> (player, result, _stack) -> {
ItemStack stack = _stack;
Event<ClientPickBlockApplyCallback> EVENT = EventFactory.createArrayBacked(ClientPickBlockApplyCallback.class,
(listeners) -> (player, result, _stack) -> {
ItemStack stack = _stack;
for (ClientPickBlockApplyCallback event : listeners) {
stack = event.pick(player, result, stack);
if (stack.isEmpty()) {
return ItemStack.EMPTY;
for (ClientPickBlockApplyCallback event : listeners) {
stack = event.pick(player, result, stack);
if (stack.isEmpty()) {
return ItemStack.EMPTY;
}
}
}
return stack;
}
return stack;
}
);
ItemStack pick(PlayerEntity player, HitResult result, ItemStack stack);

View file

@ -16,12 +16,13 @@
package net.fabricmc.fabric.api.event.client.player;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.hit.HitResult;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* This event handler has been deprecated due to not hooking nicely
* into the game. Please use the alternatives.
@ -32,7 +33,7 @@ import net.minecraft.util.hit.HitResult;
@Deprecated
public interface ClientPickBlockCallback {
@Deprecated
public static final class Container {
final class Container {
private ItemStack stack;
public Container(ItemStack stack) {
@ -48,8 +49,7 @@ public interface ClientPickBlockCallback {
}
}
@Deprecated
public static final Event<ClientPickBlockCallback> EVENT = EventFactory.createArrayBacked(ClientPickBlockCallback.class,
@Deprecated Event<ClientPickBlockCallback> EVENT = EventFactory.createArrayBacked(ClientPickBlockCallback.class,
(listeners) -> (player, result, container) -> {
for (ClientPickBlockCallback event : listeners) {
if (!event.pick(player, result, container)) {

View file

@ -16,29 +16,31 @@
package net.fabricmc.fabric.api.event.client.player;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.hit.HitResult;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* This event is emitted at the beginning of the block picking process in
* order to find any applicable ItemStack. The first non-empty ItemStack
* will be returned, overriding vanilla behaviour.
*/
public interface ClientPickBlockGatherCallback {
public static final Event<ClientPickBlockGatherCallback> EVENT = EventFactory.createArrayBacked(ClientPickBlockGatherCallback.class,
(listeners) -> (player, result) -> {
for (ClientPickBlockGatherCallback event : listeners) {
ItemStack stack = event.pick(player, result);
if (stack != ItemStack.EMPTY && !stack.isEmpty()) {
return stack;
}
}
Event<ClientPickBlockGatherCallback> EVENT = EventFactory.createArrayBacked(ClientPickBlockGatherCallback.class,
(listeners) -> (player, result) -> {
for (ClientPickBlockGatherCallback event : listeners) {
ItemStack stack = event.pick(player, result);
return ItemStack.EMPTY;
}
if (stack != ItemStack.EMPTY && !stack.isEmpty()) {
return stack;
}
}
return ItemStack.EMPTY;
}
);
ItemStack pick(PlayerEntity player, HitResult result);

View file

@ -16,8 +16,6 @@
package net.fabricmc.fabric.api.event.player;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
@ -25,29 +23,33 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* Callback for left-clicking ("attacking") a block.
* Is hooked in before the spectator check, so make sure to check for the player's game mode as well!
* <p>
* Upon return:
* - SUCCESS cancels further processing and, on the client, sends a packet to the server.
* - PASS falls back to further processing.
* - FAIL cancels further processing and does not send a packet to the server.
* <p>
* ATTACK_BLOCK does not let you control the packet sending process yet.
*
* <p>Upon return:
* <ul><li>SUCCESS cancels further processing and, on the client, sends a packet to the server.
* <li>PASS falls back to further processing.
* <li>FAIL cancels further processing and does not send a packet to the server.</ul>
*
* <p>ATTACK_BLOCK does not let you control the packet sending process yet.
*/
public interface AttackBlockCallback {
public static final Event<AttackBlockCallback> EVENT = EventFactory.createArrayBacked(AttackBlockCallback.class,
(listeners) -> (player, world, hand, pos, direction) -> {
for (AttackBlockCallback event : listeners) {
ActionResult result = event.interact(player, world, hand, pos, direction);
if (result != ActionResult.PASS) {
return result;
}
}
Event<AttackBlockCallback> EVENT = EventFactory.createArrayBacked(AttackBlockCallback.class,
(listeners) -> (player, world, hand, pos, direction) -> {
for (AttackBlockCallback event : listeners) {
ActionResult result = event.interact(player, world, hand, pos, direction);
return ActionResult.PASS;
}
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
}
);
ActionResult interact(PlayerEntity player, World world, Hand hand, BlockPos pos, Direction direction);

View file

@ -16,8 +16,6 @@
package net.fabricmc.fabric.api.event.player;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
@ -25,27 +23,31 @@ import net.minecraft.util.Hand;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* Callback for left-clicking ("attacking") an entity.
* Is hooked in before the spectator check, so make sure to check for the player's game mode as well!
* <p>
* Upon return:
* - SUCCESS cancels further processing and, on the client, sends a packet to the server.
* - PASS falls back to further processing.
* - FAIL cancels further processing and does not send a packet to the server.
*
* <p>Upon return:
* <ul><li>SUCCESS cancels further processing and, on the client, sends a packet to the server.
* <li>PASS falls back to further processing.
* <li>FAIL cancels further processing and does not send a packet to the server.</ul>
*/
public interface AttackEntityCallback {
public static final Event<AttackEntityCallback> EVENT = EventFactory.createArrayBacked(AttackEntityCallback.class,
(listeners) -> (player, world, hand, entity, hitResult) -> {
for (AttackEntityCallback event : listeners) {
ActionResult result = event.interact(player, world, hand, entity, hitResult);
if (result != ActionResult.PASS) {
return result;
}
}
Event<AttackEntityCallback> EVENT = EventFactory.createArrayBacked(AttackEntityCallback.class,
(listeners) -> (player, world, hand, entity, hitResult) -> {
for (AttackEntityCallback event : listeners) {
ActionResult result = event.interact(player, world, hand, entity, hitResult);
return ActionResult.PASS;
}
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
}
);
ActionResult interact(PlayerEntity player, World world, Hand hand, Entity entity, /* Nullable */ EntityHitResult hitResult);

View file

@ -16,35 +16,37 @@
package net.fabricmc.fabric.api.event.player;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* Callback for right-clicking ("using") a block.
* Is hooked in before the spectator check, so make sure to check for the player's game mode as well!
* <p>
* Upon return:
* - SUCCESS cancels further processing and, on the client, sends a packet to the server.
* - PASS falls back to further processing.
* - FAIL cancels further processing and does not send a packet to the server.
*
* <p>Upon return:
* <ul><li>SUCCESS cancels further processing and, on the client, sends a packet to the server.
* <li>PASS falls back to further processing.
* <li>FAIL cancels further processing and does not send a packet to the server.</ul>
*/
public interface UseBlockCallback {
public static final Event<UseBlockCallback> EVENT = EventFactory.createArrayBacked(UseBlockCallback.class,
(listeners) -> (player, world, hand, hitResult) -> {
for (UseBlockCallback event : listeners) {
ActionResult result = event.interact(player, world, hand, hitResult);
if (result != ActionResult.PASS) {
return result;
}
}
Event<UseBlockCallback> EVENT = EventFactory.createArrayBacked(UseBlockCallback.class,
(listeners) -> (player, world, hand, hitResult) -> {
for (UseBlockCallback event : listeners) {
ActionResult result = event.interact(player, world, hand, hitResult);
return ActionResult.PASS;
}
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
}
);
ActionResult interact(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult);

View file

@ -16,8 +16,6 @@
package net.fabricmc.fabric.api.event.player;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
@ -25,27 +23,31 @@ import net.minecraft.util.Hand;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* Callback for right-clicking ("using") an entity.
* Is hooked in before the spectator check, so make sure to check for the player's game mode as well!
* <p>
* Upon return:
* - SUCCESS cancels further processing and, on the client, sends a packet to the server.
* - PASS falls back to further processing.
* - FAIL cancels further processing and does not send a packet to the server.
*
* <p>Upon return:
* <ul><li>SUCCESS cancels further processing and, on the client, sends a packet to the server.
* <li>PASS falls back to further processing.
* <li>FAIL cancels further processing and does not send a packet to the server.</ul>
*/
public interface UseEntityCallback {
public static final Event<UseEntityCallback> EVENT = EventFactory.createArrayBacked(UseEntityCallback.class,
(listeners) -> (player, world, hand, entity, hitResult) -> {
for (UseEntityCallback event : listeners) {
ActionResult result = event.interact(player, world, hand, entity, hitResult);
if (result != ActionResult.PASS) {
return result;
}
}
Event<UseEntityCallback> EVENT = EventFactory.createArrayBacked(UseEntityCallback.class,
(listeners) -> (player, world, hand, entity, hitResult) -> {
for (UseEntityCallback event : listeners) {
ActionResult result = event.interact(player, world, hand, entity, hitResult);
return ActionResult.PASS;
}
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
}
);
ActionResult interact(PlayerEntity player, World world, Hand hand, Entity entity, /* Nullable */ EntityHitResult hitResult);

View file

@ -16,8 +16,6 @@
package net.fabricmc.fabric.api.event.player;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
@ -25,27 +23,31 @@ import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* Callback for right-clicking ("using") an item.
* Is hooked in before the spectator check, so make sure to check for the player's game mode as well!
* <p>
* Upon return:
* - SUCCESS cancels further processing and, on the client, sends a packet to the server.
* - PASS falls back to further processing.
* - FAIL cancels further processing and does not send a packet to the server.
*
* <p>Upon return:
* <ul><li>SUCCESS cancels further processing and, on the client, sends a packet to the server.
* <li>PASS falls back to further processing.
* <li>FAIL cancels further processing and does not send a packet to the server.</ul>
*/
public interface UseItemCallback {
public static final Event<UseItemCallback> EVENT = EventFactory.createArrayBacked(UseItemCallback.class,
listeners -> (player, world, hand) -> {
for (UseItemCallback event : listeners) {
TypedActionResult<ItemStack> result = event.interact(player, world, hand);
if (result.getResult() != ActionResult.PASS) {
return result;
}
}
Event<UseItemCallback> EVENT = EventFactory.createArrayBacked(UseItemCallback.class,
listeners -> (player, world, hand) -> {
for (UseItemCallback event : listeners) {
TypedActionResult<ItemStack> result = event.interact(player, world, hand);
return TypedActionResult.pass(ItemStack.EMPTY);
}
if (result.getResult() != ActionResult.PASS) {
return result;
}
}
return TypedActionResult.pass(ItemStack.EMPTY);
}
);
TypedActionResult<ItemStack> interact(PlayerEntity player, World world, Hand hand);

View file

@ -16,17 +16,19 @@
package net.fabricmc.fabric.impl.event;
import net.minecraft.block.BlockState;
import net.minecraft.util.ActionResult;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.block.BlockAttackInteractionAware;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.minecraft.block.BlockState;
import net.minecraft.util.ActionResult;
public class InteractionEventsRouter implements ModInitializer {
@Override
public void onInitialize() {
AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> {
BlockState state = world.getBlockState(pos);
if (state instanceof BlockAttackInteractionAware) {
if (((BlockAttackInteractionAware) state).onAttackInteraction(state, world, pos, player, hand, direction)) {
return ActionResult.FAIL;

View file

@ -16,10 +16,6 @@
package net.fabricmc.fabric.impl.event;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.block.BlockPickInteractionAware;
import net.fabricmc.fabric.api.entity.EntityPickInteractionAware;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
@ -28,6 +24,11 @@ import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.block.BlockPickInteractionAware;
import net.fabricmc.fabric.api.entity.EntityPickInteractionAware;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
public class InteractionEventsRouterClient implements ClientModInitializer {
@Override
public void onInitializeClient() {

View file

@ -16,7 +16,13 @@
package net.fabricmc.fabric.mixin.eventsinteraction;
import net.fabricmc.fabric.api.event.player.*;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
@ -38,12 +44,12 @@ import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameMode;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
@Mixin(ClientPlayerInteractionManager.class)
public class MixinClientPlayerInteractionManager {
@ -57,6 +63,7 @@ public class MixinClientPlayerInteractionManager {
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/world/GameMode;isCreative()Z", ordinal = 0), method = "attackBlock", cancellable = true)
public void attackBlock(BlockPos pos, Direction direction, CallbackInfoReturnable<Boolean> info) {
ActionResult result = AttackBlockCallback.EVENT.invoker().interact(client.player, client.world, Hand.MAIN_HAND, pos, direction);
if (result != ActionResult.PASS) {
info.setReturnValue(result == ActionResult.SUCCESS);
info.cancel();
@ -70,6 +77,7 @@ public class MixinClientPlayerInteractionManager {
}
ActionResult result = AttackBlockCallback.EVENT.invoker().interact(client.player, client.world, Hand.MAIN_HAND, pos, direction);
if (result != ActionResult.PASS) {
info.setReturnValue(result == ActionResult.SUCCESS);
info.cancel();
@ -79,10 +87,12 @@ public class MixinClientPlayerInteractionManager {
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getStackInHand(Lnet/minecraft/util/Hand;)Lnet/minecraft/item/ItemStack;", ordinal = 0), method = "interactBlock", cancellable = true)
public void interactBlock(ClientPlayerEntity player, ClientWorld world, Hand hand, BlockHitResult blockHitResult, CallbackInfoReturnable<ActionResult> info) {
ActionResult result = UseBlockCallback.EVENT.invoker().interact(player, world, hand, blockHitResult);
if (result != ActionResult.PASS) {
if (result == ActionResult.SUCCESS) {
this.networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(hand, blockHitResult));
}
info.setReturnValue(result);
info.cancel();
}
@ -91,10 +101,12 @@ public class MixinClientPlayerInteractionManager {
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V", ordinal = 0), method = "interactItem", cancellable = true)
public void interactItem(PlayerEntity player, World world, Hand hand, CallbackInfoReturnable<TypedActionResult<ItemStack>> info) {
TypedActionResult<ItemStack> result = UseItemCallback.EVENT.invoker().interact(player, world, hand);
if (result.getResult() != ActionResult.PASS) {
if (result.getResult() == ActionResult.SUCCESS) {
this.networkHandler.sendPacket(new PlayerInteractItemC2SPacket(hand));
}
info.setReturnValue(result);
info.cancel();
return;
@ -104,10 +116,12 @@ public class MixinClientPlayerInteractionManager {
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V", ordinal = 0), method = "attackEntity", cancellable = true)
public void attackEntity(PlayerEntity player, Entity entity, CallbackInfo info) {
ActionResult result = AttackEntityCallback.EVENT.invoker().interact(player, player.getEntityWorld(), Hand.MAIN_HAND /* TODO */, entity, null);
if (result != ActionResult.PASS) {
if (result == ActionResult.SUCCESS) {
this.networkHandler.sendPacket(new PlayerInteractEntityC2SPacket(entity));
}
info.cancel();
}
}
@ -115,11 +129,13 @@ public class MixinClientPlayerInteractionManager {
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V", ordinal = 0), method = "interactEntityAtLocation", cancellable = true)
public void interactEntityAtLocation(PlayerEntity player, Entity entity, EntityHitResult hitResult, Hand hand, CallbackInfoReturnable<ActionResult> info) {
ActionResult result = UseEntityCallback.EVENT.invoker().interact(player, player.getEntityWorld(), hand, entity, hitResult);
if (result != ActionResult.PASS) {
if (result == ActionResult.SUCCESS) {
Vec3d hitVec = hitResult.getPos().subtract(entity.getX(), entity.getY(), entity.getZ());
this.networkHandler.sendPacket(new PlayerInteractEntityC2SPacket(entity, hand, hitVec));
}
info.setReturnValue(result);
info.cancel();
return;

View file

@ -16,9 +16,13 @@
package net.fabricmc.fabric.mixin.eventsinteraction;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockApplyCallback;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockCallback;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
@ -27,12 +31,10 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockApplyCallback;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockCallback;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
@Mixin(MinecraftClient.class)
public abstract class MixinMinecraftClient {
@ -52,6 +54,7 @@ public abstract class MixinMinecraftClient {
// Do a "best effort" emulation of the old events.
ItemStack stack = ClientPickBlockGatherCallback.EVENT.invoker().pick(client.player, client.hitResult);
// TODO: Remove in 0.3.0
if (stack.isEmpty()) {
stack = fabric_emulateOldPick();
@ -67,12 +70,14 @@ public abstract class MixinMinecraftClient {
if (client.player.abilities.creativeMode && Screen.hasControlDown() && client.hitResult.getType() == HitResult.Type.BLOCK) {
BlockEntity be = client.world.getBlockEntity(((BlockHitResult) client.hitResult).getBlockPos());
if (be != null) {
stack = addBlockEntityNbt(stack, be);
}
}
stack = ClientPickBlockApplyCallback.EVENT.invoker().pick(client.player, client.hitResult, stack);
if (stack.isEmpty()) {
return;
}
@ -82,6 +87,7 @@ public abstract class MixinMinecraftClient {
client.interactionManager.clickCreativeStack(client.player.getStackInHand(Hand.MAIN_HAND), 36 + playerInventory.selectedSlot);
} else {
int slot = playerInventory.getSlotWithStack(stack);
if (slot >= 0) {
if (PlayerInventory.isValidHotbarIndex(slot)) {
playerInventory.selectedSlot = slot;

View file

@ -16,7 +16,12 @@
package net.fabricmc.fabric.mixin.eventsinteraction;
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.entity.Entity;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
@ -24,11 +29,8 @@ import net.minecraft.server.network.packet.PlayerInteractEntityC2SPacket;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
@Mixin(ServerPlayNetworkHandler.class)
public class MixinServerPlayNetworkHandler {
@ -39,10 +41,12 @@ public class MixinServerPlayNetworkHandler {
public void onPlayerInteractEntity(PlayerInteractEntityC2SPacket packet, CallbackInfo info) {
World world = player.getEntityWorld();
Entity entity = packet.getEntity(world);
if (entity != null) {
EntityHitResult hitResult = new EntityHitResult(entity, packet.getHitPosition().add(entity.getX(), entity.getY(), entity.getZ()));
ActionResult result = UseEntityCallback.EVENT.invoker().interact(player, world, packet.getHand(), entity, hitResult);
if (result != ActionResult.PASS) {
info.cancel();
}

View file

@ -16,22 +16,25 @@
package net.fabricmc.fabric.mixin.eventsinteraction;
import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
import net.minecraft.entity.Entity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.entity.Entity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
@Mixin(ServerPlayerEntity.class)
public class MixinServerPlayerEntity {
@Inject(method = "attack", at = @At("HEAD"), cancellable = true)
public void onPlayerInteractEntity(Entity target, CallbackInfo info) {
ServerPlayerEntity player = (ServerPlayerEntity) (Object) this;
ActionResult result = AttackEntityCallback.EVENT.invoker().interact(player, player.getEntityWorld(), Hand.MAIN_HAND, target, null);
if (result != ActionResult.PASS) {
info.cancel();
}

View file

@ -16,9 +16,13 @@
package net.fabricmc.fabric.mixin.eventsinteraction;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.client.network.packet.BlockUpdateS2CPacket;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
@ -33,12 +37,10 @@ import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
@Mixin(ServerPlayerInteractionManager.class)
public class MixinServerPlayerInteractionManager {
@ -50,6 +52,7 @@ public class MixinServerPlayerInteractionManager {
@Inject(at = @At("HEAD"), method = "processBlockBreakingAction", cancellable = true)
public void startBlockBreak(BlockPos pos, PlayerActionC2SPacket.Action playerAction, Direction direction, int i, CallbackInfo info) {
ActionResult result = AttackBlockCallback.EVENT.invoker().interact(player, world, Hand.MAIN_HAND, pos, direction);
if (result != ActionResult.PASS) {
// The client might have broken the block on its side, so make sure to let it know.
this.player.networkHandler.sendPacket(new BlockUpdateS2CPacket(world, pos));
@ -60,6 +63,7 @@ public class MixinServerPlayerInteractionManager {
@Inject(at = @At("HEAD"), method = "interactBlock", cancellable = true)
public void interactBlock(PlayerEntity player, World world, ItemStack stack, Hand hand, BlockHitResult blockHitResult, CallbackInfoReturnable<ActionResult> info) {
ActionResult result = UseBlockCallback.EVENT.invoker().interact(player, world, hand, blockHitResult);
if (result != ActionResult.PASS) {
info.setReturnValue(result);
info.cancel();
@ -70,6 +74,7 @@ public class MixinServerPlayerInteractionManager {
@Inject(at = @At("HEAD"), method = "interactItem", cancellable = true)
public void interactItem(PlayerEntity player, World world, ItemStack stack, Hand hand, CallbackInfoReturnable<ActionResult> info) {
TypedActionResult<ItemStack> result = UseItemCallback.EVENT.invoker().interact(player, world, hand);
if (result.getResult() != ActionResult.PASS) {
info.setReturnValue(result.getResult());
info.cancel();

View file

@ -16,31 +16,34 @@
package net.fabricmc.fabric.api.event.client;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.client.MinecraftClient;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface ClientTickCallback {
public static final Event<ClientTickCallback> EVENT = EventFactory.createArrayBacked(ClientTickCallback.class,
(listeners) -> {
if (EventFactory.isProfilingEnabled()) {
return (client) -> {
client.getProfiler().push("fabricClientTick");
for (ClientTickCallback event : listeners) {
client.getProfiler().push(EventFactory.getHandlerName(event));
event.tick(client);
Event<ClientTickCallback> EVENT = EventFactory.createArrayBacked(ClientTickCallback.class,
(listeners) -> {
if (EventFactory.isProfilingEnabled()) {
return (client) -> {
client.getProfiler().push("fabricClientTick");
for (ClientTickCallback event : listeners) {
client.getProfiler().push(EventFactory.getHandlerName(event));
event.tick(client);
client.getProfiler().pop();
}
client.getProfiler().pop();
}
client.getProfiler().pop();
};
} else {
return (client) -> {
for (ClientTickCallback event : listeners) {
event.tick(client);
}
};
};
} else {
return (client) -> {
for (ClientTickCallback event : listeners) {
event.tick(client);
}
};
}
}
}
);
void tick(MinecraftClient client);

View file

@ -16,24 +16,23 @@
package net.fabricmc.fabric.api.event.client;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import java.util.List;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import java.util.List;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface ItemTooltipCallback {
/** Fired after the game has appended all base tooltip lines to the list */
/** Fired after the game has appended all base tooltip lines to the list. */
Event<ItemTooltipCallback> EVENT = EventFactory.createArrayBacked(ItemTooltipCallback.class, (listeners) ->
(stack, tooltipContext, lines) -> {
for(ItemTooltipCallback callback : listeners){
callback.getTooltip(stack, tooltipContext, lines);
}
(stack, tooltipContext, lines) -> {
for (ItemTooltipCallback callback : listeners) {
callback.getTooltip(stack, tooltipContext, lines);
}
);
});
/**
* Called when an item stack's tooltip is rendered. Text added to {@code lines} will be
@ -41,5 +40,4 @@ public interface ItemTooltipCallback {
* @param lines the list containing the lines of text displayed on the stack's tooltip
*/
void getTooltip(ItemStack stack, TooltipContext tooltipContext, List<Text> lines);
}

View file

@ -16,17 +16,18 @@
package net.fabricmc.fabric.api.event.server;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.server.MinecraftServer;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface ServerStartCallback {
public static final Event<ServerStartCallback> EVENT = EventFactory.createArrayBacked(ServerStartCallback.class,
(listeners) -> (server) -> {
for (ServerStartCallback event : listeners) {
event.onStartServer(server);
Event<ServerStartCallback> EVENT = EventFactory.createArrayBacked(ServerStartCallback.class,
(listeners) -> (server) -> {
for (ServerStartCallback event : listeners) {
event.onStartServer(server);
}
}
}
);
void onStartServer(MinecraftServer server);

View file

@ -16,17 +16,18 @@
package net.fabricmc.fabric.api.event.server;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.server.MinecraftServer;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface ServerStopCallback {
public static final Event<ServerStopCallback> EVENT = EventFactory.createArrayBacked(ServerStopCallback.class,
(listeners) -> (server) -> {
for (ServerStopCallback event : listeners) {
event.onStopServer(server);
Event<ServerStopCallback> EVENT = EventFactory.createArrayBacked(ServerStopCallback.class,
(listeners) -> (server) -> {
for (ServerStopCallback event : listeners) {
event.onStopServer(server);
}
}
}
);
void onStopServer(MinecraftServer server);

View file

@ -16,31 +16,34 @@
package net.fabricmc.fabric.api.event.server;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.server.MinecraftServer;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface ServerTickCallback {
public static final Event<ServerTickCallback> EVENT = EventFactory.createArrayBacked(ServerTickCallback.class,
(listeners) -> {
if (EventFactory.isProfilingEnabled()) {
return (server) -> {
server.getProfiler().push("fabricServerTick");
for (ServerTickCallback event : listeners) {
server.getProfiler().push(EventFactory.getHandlerName(event));
event.tick(server);
Event<ServerTickCallback> EVENT = EventFactory.createArrayBacked(ServerTickCallback.class,
(listeners) -> {
if (EventFactory.isProfilingEnabled()) {
return (server) -> {
server.getProfiler().push("fabricServerTick");
for (ServerTickCallback event : listeners) {
server.getProfiler().push(EventFactory.getHandlerName(event));
event.tick(server);
server.getProfiler().pop();
}
server.getProfiler().pop();
}
server.getProfiler().pop();
};
} else {
return (server) -> {
for (ServerTickCallback event : listeners) {
event.tick(server);
}
};
};
} else {
return (server) -> {
for (ServerTickCallback event : listeners) {
event.tick(server);
}
};
}
}
}
);
void tick(MinecraftServer server);

View file

@ -16,31 +16,34 @@
package net.fabricmc.fabric.api.event.world;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface WorldTickCallback {
public static final Event<WorldTickCallback> EVENT = EventFactory.createArrayBacked(WorldTickCallback.class,
(listeners) -> {
if (EventFactory.isProfilingEnabled()) {
return (world) -> {
world.getProfiler().push("fabricWorldTick");
for (WorldTickCallback event : listeners) {
world.getProfiler().push(EventFactory.getHandlerName(event));
event.tick(world);
Event<WorldTickCallback> EVENT = EventFactory.createArrayBacked(WorldTickCallback.class,
(listeners) -> {
if (EventFactory.isProfilingEnabled()) {
return (world) -> {
world.getProfiler().push("fabricWorldTick");
for (WorldTickCallback event : listeners) {
world.getProfiler().push(EventFactory.getHandlerName(event));
event.tick(world);
world.getProfiler().pop();
}
world.getProfiler().pop();
}
world.getProfiler().pop();
};
} else {
return (world) -> {
for (WorldTickCallback event : listeners) {
event.tick(world);
}
};
};
} else {
return (world) -> {
for (WorldTickCallback event : listeners) {
event.tick(world);
}
};
}
}
}
);
void tick(World world);

View file

@ -16,25 +16,24 @@
package net.fabricmc.fabric.mixin.eventslifecycle;
import net.fabricmc.fabric.api.event.client.ItemTooltipCallback;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import java.util.List;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.List;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.fabricmc.fabric.api.event.client.ItemTooltipCallback;
@Mixin(ItemStack.class)
public class MixinItemStack {
@Inject(method = "getTooltip", at = @At("RETURN"))
private void getTooltip(PlayerEntity entity, TooltipContext tooltipContext, CallbackInfoReturnable<List<Text>> info){
ItemTooltipCallback.EVENT.invoker().getTooltip((ItemStack) (Object)this, tooltipContext, info.getReturnValue());
private void getTooltip(PlayerEntity entity, TooltipContext tooltipContext, CallbackInfoReturnable<List<Text>> info) {
ItemTooltipCallback.EVENT.invoker().getTooltip((ItemStack) (Object) this, tooltipContext, info.getReturnValue());
}
}

View file

@ -16,13 +16,15 @@
package net.fabricmc.fabric.mixin.eventslifecycle;
import net.fabricmc.fabric.api.event.client.ClientTickCallback;
import net.minecraft.client.MinecraftClient;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.MinecraftClient;
import net.fabricmc.fabric.api.event.client.ClientTickCallback;
@Mixin(MinecraftClient.class)
public class MixinMinecraftClient {
@Inject(at = @At("RETURN"), method = "tick")

View file

@ -16,16 +16,18 @@
package net.fabricmc.fabric.mixin.eventslifecycle;
import net.fabricmc.fabric.api.event.server.ServerStartCallback;
import net.fabricmc.fabric.api.event.server.ServerStopCallback;
import net.fabricmc.fabric.api.event.server.ServerTickCallback;
import net.minecraft.server.MinecraftServer;
import java.util.function.BooleanSupplier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.function.BooleanSupplier;
import net.minecraft.server.MinecraftServer;
import net.fabricmc.fabric.api.event.server.ServerStartCallback;
import net.fabricmc.fabric.api.event.server.ServerStopCallback;
import net.fabricmc.fabric.api.event.server.ServerTickCallback;
@Mixin(MinecraftServer.class)
public class MixinMinecraftServer {

View file

@ -16,13 +16,15 @@
package net.fabricmc.fabric.mixin.eventslifecycle;
import net.fabricmc.fabric.api.event.world.WorldTickCallback;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.event.world.WorldTickCallback;
@Mixin(World.class)
public class MixinWorld {
// TODO split into ClientWorld/ServerWorld ticks? mmm need more mappings

View file

@ -16,18 +16,18 @@
package net.fabricmc.fabric.api.client.itemgroup;
import net.fabricmc.fabric.impl.itemgroup.ItemGroupExtensions;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import net.fabricmc.fabric.impl.itemgroup.ItemGroupExtensions;
public final class FabricItemGroupBuilder {
private Identifier identifier;
private Supplier<ItemStack> stackSupplier = () -> ItemStack.EMPTY;
private Consumer<List<ItemStack>> stacksForDisplay;
@ -37,7 +37,7 @@ public final class FabricItemGroupBuilder {
}
/**
* Create a new Item Group Builder
* Create a new Item Group Builder.
*
* @param identifier the id will become the name of the ItemGroup and will be used for the translation key
* @return a FabricItemGroupBuilder
@ -47,7 +47,7 @@ public final class FabricItemGroupBuilder {
}
/**
* This is used to add an icon to to the item group
* This is used to add an icon to to the item group.
*
* @param stackSupplier the supplier should return the item stack that you wish to show on the tab
* @return a reference to the FabricItemGroupBuilder
@ -58,7 +58,7 @@ public final class FabricItemGroupBuilder {
}
/**
* This allows for a custom list of items to be displayed in a tab, this enabled tabs to be created with a custom set of items
* This allows for a custom list of items to be displayed in a tab, this enabled tabs to be created with a custom set of items.
*
* @param appender Add ItemStack's to this list to show in the ItemGroup
* @return a reference to the FabricItemGroupBuilder
@ -70,7 +70,7 @@ public final class FabricItemGroupBuilder {
}
/**
* This allows for a custom list of items to be displayed in a tab, this enabled tabs to be created with a custom set of items
* This allows for a custom list of items to be displayed in a tab, this enabled tabs to be created with a custom set of items.
*
* @param stacksForDisplay Add ItemStack's to this list to show in the ItemGroup
* @return a reference to the FabricItemGroupBuilder
@ -81,7 +81,7 @@ public final class FabricItemGroupBuilder {
}
/**
* This is a single method that makes creating an ItemGroup with an icon one call
* This is a single method that makes creating an ItemGroup with an icon one call.
*
* @param identifier the id will become the name of the ItemGroup and will be used for the translation key
* @param stackSupplier the supplier should return the item stack that you wish to show on the tab
@ -92,7 +92,7 @@ public final class FabricItemGroupBuilder {
}
/**
* Create an instance of the ItemGroup
* Create an instance of the ItemGroup.
*
* @return An instance of the built ItemGroup
*/
@ -110,9 +110,9 @@ public final class FabricItemGroupBuilder {
stacksForDisplay.accept(stacks);
return;
}
super.appendStacks(stacks);
}
};
}
}

View file

@ -17,7 +17,6 @@
package net.fabricmc.fabric.impl.itemgroup;
public interface CreativeGuiExtensions {
void fabric_nextPage();
void fabric_previousPage();

View file

@ -16,21 +16,20 @@
package net.fabricmc.fabric.impl.itemgroup;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.item.ItemGroup;
import net.minecraft.util.Identifier;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
public class FabricCreativeGuiComponents {
private static final Identifier BUTTON_TEX = new Identifier("fabric", "textures/gui/creative_buttons.png");
public static final Set<ItemGroup> COMMON_GROUPS = new HashSet<>();
@ -41,7 +40,6 @@ public class FabricCreativeGuiComponents {
}
public static class ItemGroupButtonWidget extends ButtonWidget {
CreativeGuiExtensions extensions;
CreativeInventoryScreen gui;
Type type;
@ -73,7 +71,6 @@ public class FabricCreativeGuiComponents {
}
public enum Type {
NEXT(">", CreativeGuiExtensions::fabric_nextPage),
PREVIOUS("<", CreativeGuiExtensions::fabric_previousPage);
@ -85,5 +82,4 @@ public class FabricCreativeGuiComponents {
this.clickConsumer = clickConsumer;
}
}
}

View file

@ -17,7 +17,5 @@
package net.fabricmc.fabric.impl.itemgroup;
public interface ItemGroupExtensions {
void fabric_expandArray();
}

View file

@ -16,16 +16,17 @@
package net.fabricmc.fabric.mixin.itemgroup;
import net.fabricmc.fabric.impl.itemgroup.ItemGroupExtensions;
import net.minecraft.item.ItemGroup;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.item.ItemGroup;
import net.fabricmc.fabric.impl.itemgroup.ItemGroupExtensions;
@Mixin(ItemGroup.class)
public abstract class MixinItemGroup implements ItemGroupExtensions {
@Shadow
@Final
@Mutable
@ -35,9 +36,9 @@ public abstract class MixinItemGroup implements ItemGroupExtensions {
public void fabric_expandArray() {
ItemGroup[] tempGroups = GROUPS;
GROUPS = new ItemGroup[GROUPS.length + 1];
for (int i = 0; i < tempGroups.length; i++) {
GROUPS[i] = tempGroups[i];
}
}
}

View file

@ -16,14 +16,6 @@
package net.fabricmc.fabric.mixin.itemgroup.client;
import net.fabricmc.fabric.impl.itemgroup.CreativeGuiExtensions;
import net.fabricmc.fabric.impl.itemgroup.FabricCreativeGuiComponents;
import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.container.Container;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemGroup;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -31,9 +23,18 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.container.Container;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemGroup;
import net.minecraft.text.Text;
import net.fabricmc.fabric.impl.itemgroup.CreativeGuiExtensions;
import net.fabricmc.fabric.impl.itemgroup.FabricCreativeGuiComponents;
@Mixin(CreativeInventoryScreen.class)
public abstract class MixinCreativePlayerInventoryGui extends AbstractInventoryScreen implements CreativeGuiExtensions {
public MixinCreativePlayerInventoryGui(Container container_1, PlayerInventory playerInventory_1, Text textComponent_1) {
super(container_1, playerInventory_1, textComponent_1);
}
@ -49,12 +50,12 @@ public abstract class MixinCreativePlayerInventoryGui extends AbstractInventoryS
private int fabric_getPageOffset(int page) {
switch (page) {
case 0:
return 0;
case 1:
return 12;
default:
return 12 + ((12 - FabricCreativeGuiComponents.COMMON_GROUPS.size()) * (page - 1));
case 0:
return 0;
case 1:
return 12;
default:
return 12 + ((12 - FabricCreativeGuiComponents.COMMON_GROUPS.size()) * (page - 1));
}
}
@ -71,6 +72,7 @@ public abstract class MixinCreativePlayerInventoryGui extends AbstractInventoryS
if (fabric_getPageOffset(fabric_currentPage + 1) >= ItemGroup.GROUPS.length) {
return;
}
fabric_currentPage++;
fabric_updateSelection();
}
@ -80,6 +82,7 @@ public abstract class MixinCreativePlayerInventoryGui extends AbstractInventoryS
if (fabric_currentPage == 0) {
return;
}
fabric_currentPage--;
fabric_updateSelection();
}
@ -94,9 +97,11 @@ public abstract class MixinCreativePlayerInventoryGui extends AbstractInventoryS
if (type == FabricCreativeGuiComponents.Type.NEXT) {
return !(fabric_getPageOffset(fabric_currentPage + 1) >= ItemGroup.GROUPS.length);
}
if (type == FabricCreativeGuiComponents.Type.PREVIOUS) {
return fabric_currentPage != 0;
}
return false;
}
@ -119,7 +124,6 @@ public abstract class MixinCreativePlayerInventoryGui extends AbstractInventoryS
addButton(new FabricCreativeGuiComponents.ItemGroupButtonWidget(xpos + 10, ypos, FabricCreativeGuiComponents.Type.NEXT, this));
addButton(new FabricCreativeGuiComponents.ItemGroupButtonWidget(xpos, ypos, FabricCreativeGuiComponents.Type.PREVIOUS, this));
}
@Inject(method = "setSelectedTab", at = @At("HEAD"), cancellable = true)
@ -154,8 +158,8 @@ public abstract class MixinCreativePlayerInventoryGui extends AbstractInventoryS
if (FabricCreativeGuiComponents.COMMON_GROUPS.contains(itemGroup)) {
return true;
}
return fabric_currentPage == fabric_getOffsetPage(itemGroup.getIndex());
return fabric_currentPage == fabric_getOffsetPage(itemGroup.getIndex());
}
@Override

View file

@ -16,14 +16,16 @@
package net.fabricmc.fabric.mixin.itemgroup.client;
import net.fabricmc.fabric.impl.itemgroup.FabricCreativeGuiComponents;
import net.minecraft.item.ItemGroup;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.item.ItemGroup;
import net.fabricmc.fabric.impl.itemgroup.FabricCreativeGuiComponents;
@Mixin(ItemGroup.class)
public abstract class MixinItemGroup {
@Shadow
@ -47,7 +49,6 @@ public abstract class MixinItemGroup {
} else {
info.setReturnValue((getIndex() - 12) % (12 - FabricCreativeGuiComponents.COMMON_GROUPS.size()) - 4);
}
}
}
}

View file

@ -16,15 +16,16 @@
package net.fabricmc.fabric.api.client.keybinding;
import net.fabricmc.fabric.mixin.client.keybinding.KeyCodeAccessor;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.mixin.client.keybinding.KeyCodeAccessor;
/**
* Expanded version of {@link KeyBinding} for use by Fabric mods.
* <p>
* *ALL* instantiated FabricKeyBindings should be registered in
*
* <p>*ALL* instantiated FabricKeyBindings should be registered in
* {@link KeyBindingRegistry#register(FabricKeyBinding)}!
*/
public class FabricKeyBinding extends KeyBinding {

View file

@ -16,16 +16,17 @@
package net.fabricmc.fabric.api.client.keybinding;
import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl;
import net.minecraft.client.options.KeyBinding;
import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl;
/**
* Interface for registering key bindings.
*
* @see KeyBinding
*/
public interface KeyBindingRegistry {
static KeyBindingRegistry INSTANCE = KeyBindingRegistryImpl.INSTANCE;
KeyBindingRegistry INSTANCE = KeyBindingRegistryImpl.INSTANCE;
/**
* Add a new key binding category.

Some files were not shown because too many files have changed in this diff Show more