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 .gradle
# Eclipse # Eclipse
.checkstyle
.classpath .classpath
.metadata .metadata
.settings .settings

View file

@ -43,6 +43,7 @@ def getBranch(){
} }
allprojects { allprojects {
apply plugin: 'checkstyle'
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
apply plugin: 'fabric-loom' apply plugin: 'fabric-loom'
apply plugin: 'net.minecrell.licenser' apply plugin: 'net.minecrell.licenser'
@ -52,8 +53,6 @@ allprojects {
group = "net.fabricmc.fabric-api" group = "net.fabricmc.fabric-api"
dependencies { dependencies {
minecraft "com.mojang:minecraft:$Globals.mcVersion" minecraft "com.mojang:minecraft:$Globals.mcVersion"
mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}" mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}"
@ -105,9 +104,14 @@ allprojects {
classifier = 'sources' classifier = 'sources'
from sourceSets.main.allSource from sourceSets.main.allSource
} }
checkstyle {
configFile = rootProject.file("checkstyle.xml")
toolVersion = '8.25'
}
} }
javadoc{
javadoc {
options.memberLevel = "PACKAGE" options.memberLevel = "PACKAGE"
allprojects.each{ allprojects.each{
source( it.sourceSets.main.allJava.srcDirs) 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. * 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 * listeners of type T under one instance of type T, executing
* them and leaving early as necessary. * them and leaving early as necessary.
* *

View file

@ -16,19 +16,17 @@
package net.fabricmc.fabric.api.event; package net.fabricmc.fabric.api.event;
import net.fabricmc.fabric.impl.event.EventFactoryImpl;
import java.util.function.Function; import java.util.function.Function;
import net.fabricmc.fabric.impl.event.EventFactoryImpl;
/** /**
* Helper for creating {@link Event} classes. * Helper for creating {@link Event} classes.
*/ */
public final class EventFactory { public final class EventFactory {
private static boolean profilingEnabled = true; private static boolean profilingEnabled = true;
private EventFactory() { private EventFactory() { }
}
/** /**
* @return True if events are supposed to be profiled. * @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. * 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 * relative to iterating over an empty array; however, it only really matters
* if the event is executed thousands of times a second. * 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. * 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 CompoundTag#containsKey(String, int)
* @see Tag#idToString(int) * @see Tag#idToString(int)
* <p>
* For the current list of types, check with {@link Tag#TYPES}.
*/ */
public final class NbtType { public final class NbtType {
public static final int END = 0; public static final int END = 0;
@ -49,7 +49,5 @@ public final class NbtType {
*/ */
public static final int NUMBER = 99; public static final int NUMBER = 99;
private NbtType() { private NbtType() { }
}
} }

View file

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

View file

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

View file

@ -16,24 +16,22 @@
package net.fabricmc.fabric.api.biomes.v1; package net.fabricmc.fabric.api.biomes.v1;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.minecraft.world.biome.Biome; 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 { 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 * @param biome a biome the player should be able to spawn in
*/ */
public static void addSpawnBiome(Biome biome) { public static void addSpawnBiome(Biome biome) {
InternalBiomeData.addSpawnBiome(biome); InternalBiomeData.addSpawnBiome(biome);
} }
} }

View file

@ -16,16 +16,15 @@
package net.fabricmc.fabric.api.biomes.v1; package net.fabricmc.fabric.api.biomes.v1;
import net.fabricmc.fabric.impl.biomes.InternalBiomeData;
import net.minecraft.world.biome.Biome; 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 { 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. * 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 parent the biome to where the hills variant is added
* @param hills the biome to be set as a hills variant * @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 parent the base biome to where the shore biome is added
* @param shore the biome to be added as a shore biome * @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 parent the base biome to where the edge biome is added
* @param edge the biome to be added as an edge biome * @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. * 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, * 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 * 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 * 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) { public static void setRiverBiome(Biome parent, Biome river) {
InternalBiomeData.setOverworldRiverBiome(parent, river); InternalBiomeData.setOverworldRiverBiome(parent, river);
} }
} }

View file

@ -17,27 +17,26 @@
package net.fabricmc.fabric.api.biomes.v1; 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 { 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, SNOWY,
/** /**
* Includes Forest, Taiga, Mountains, and Plains (all with weights of 1) * Includes Forest, Taiga, Mountains, and Plains (all with weights of 1).
*/ */
COOL, 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, 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 DRY
} }

View file

@ -19,10 +19,9 @@ package net.fabricmc.fabric.impl.biomes;
import net.minecraft.world.biome.Biome; 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 { final class BiomeVariant {
private final Biome variant; private final Biome variant;
private final double chance; private final double chance;
@ -48,5 +47,4 @@ final class BiomeVariant {
double getChance() { double getChance() {
return chance; return chance;
} }
} }

View file

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

View file

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

View file

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

View file

@ -16,17 +16,18 @@
package net.fabricmc.fabric.impl.biomes; 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.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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 { final class VariantTransformer {
private final SubTransformer defaultTransformer = new SubTransformer(); 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 replaced biome to transform
* @param random the {@link LayerRandomnessSource} from the layer * @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 replaced biome to transform
* @param random the {@link LayerRandomnessSource} from the layer * @param random the {@link LayerRandomnessSource} from the layer
@ -93,6 +94,7 @@ final class VariantTransformer {
return variant.getVariant(); return variant.getVariant();
} }
} }
return replaced; return replaced;
} }
} }

View file

@ -16,13 +16,14 @@
package net.fabricmc.fabric.impl.biomes; 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.ArrayList;
import java.util.List; 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. * Picks biomes with arbitrary double weights using a binary search.
*/ */
@ -46,13 +47,13 @@ public final class WeightedBiomePicker {
} }
public Biome pickRandom(LayerRandomnessSource random) { 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(); 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 * @param target The target value, must satisfy the constraint 0 <= target <= currentTotal
* @return The result of the search * @return The result of the search
@ -67,6 +68,7 @@ public final class WeightedBiomePicker {
while (low < high) { while (low < high) {
int mid = (high + low) >>> 1; int mid = (high + low) >>> 1;
if (target < entries.get(mid).getUpperWeightBound()) { if (target < entries.get(mid).getUpperWeightBound()) {
high = mid; high = mid;
} else { } else {

View file

@ -16,32 +16,33 @@
package net.fabricmc.fabric.mixin.biomes; 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.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 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) @Mixin(AddEdgeBiomesLayer.class)
public class MixinAddEdgeBiomesLayer { public class MixinAddEdgeBiomesLayer {
@Inject(at = @At("HEAD"), method = "sample", cancellable = true) @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) { private void sample(LayerRandomnessSource rand, int north, int east, int south, int west, int center, CallbackInfoReturnable<Integer> info) {
Biome centerBiome = Registry.BIOME.get(center); Biome centerBiome = Registry.BIOME.get(center);
if (InternalBiomeData.getOverworldShores().containsKey(centerBiome) && InternalBiomeUtils.neighborsOcean(north, east, south, west)) { if (InternalBiomeData.getOverworldShores().containsKey(centerBiome) && InternalBiomeUtils.neighborsOcean(north, east, south, west)) {
info.setReturnValue(Registry.BIOME.getRawId(InternalBiomeData.getOverworldShores().get(centerBiome).pickRandom(rand))); info.setReturnValue(Registry.BIOME.getRawId(InternalBiomeData.getOverworldShores().get(centerBiome).pickRandom(rand)));
} else if (InternalBiomeData.getOverworldEdges().containsKey(centerBiome) && InternalBiomeUtils.isEdge(north, east, south, west, center)) { } else if (InternalBiomeData.getOverworldEdges().containsKey(centerBiome) && InternalBiomeUtils.isEdge(north, east, south, west, center)) {
info.setReturnValue(Registry.BIOME.getRawId(InternalBiomeData.getOverworldEdges().get(centerBiome).pickRandom(rand))); info.setReturnValue(Registry.BIOME.getRawId(InternalBiomeData.getOverworldEdges().get(centerBiome).pickRandom(rand)));
} }
} }
} }

View file

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

View file

@ -16,13 +16,8 @@
package net.fabricmc.fabric.mixin.biomes; package net.fabricmc.fabric.mixin.biomes;
import net.fabricmc.fabric.api.biomes.v1.OverworldBiomes; import java.util.Map;
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 org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; 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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 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) @Mixin(AddRiversLayer.class)
public class MixinAddRiversLayer { public class MixinAddRiversLayer {
@Shadow @Shadow
@Final @Final
private static int RIVER_ID; private static int RIVER_ID;
@ -49,10 +50,10 @@ public class MixinAddRiversLayer {
int riverBiomeId = riverSampler.sample(x, z); int riverBiomeId = riverSampler.sample(x, z);
Map<Biome, Biome> overworldRivers = InternalBiomeData.getOverworldRivers(); Map<Biome, Biome> overworldRivers = InternalBiomeData.getOverworldRivers();
if (overworldRivers.containsKey(landBiome) && riverBiomeId == RIVER_ID) { if (overworldRivers.containsKey(landBiome) && riverBiomeId == RIVER_ID) {
Biome riverBiome = overworldRivers.get(landBiome); Biome riverBiome = overworldRivers.get(landBiome);
info.setReturnValue(riverBiome == null ? landBiomeId : Registry.BIOME.getRawId(riverBiome)); info.setReturnValue(riverBiome == null ? landBiomeId : Registry.BIOME.getRawId(riverBiome));
} }
} }
} }

View file

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

View file

@ -16,12 +16,6 @@
package net.fabricmc.fabric.mixin.biomes; 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.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable; 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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 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) @Mixin(SetBaseBiomesLayer.class)
public class MixinSetBaseBiomesLayer { public class MixinSetBaseBiomesLayer {
@Shadow @Shadow
@Final @Final
@Mutable @Mutable
@ -112,5 +113,4 @@ public class MixinSetBaseBiomesLayer {
info.setReturnValue(InternalBiomeUtils.transformBiome(random, biome, climate)); info.setReturnValue(InternalBiomeUtils.transformBiome(random, biome, climate));
} }
} }

View file

@ -16,9 +16,9 @@
package net.fabricmc.fabric.mixin.biomes; package net.fabricmc.fabric.mixin.biomes;
import net.minecraft.world.biome.Biome; import java.util.HashSet;
import net.minecraft.world.biome.source.VanillaLayeredBiomeSource; import java.util.Set;
import net.minecraft.world.gen.feature.StructureFeature;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable; 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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.HashSet; import net.minecraft.world.biome.Biome;
import java.util.Set; 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. * 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) @Mixin(VanillaLayeredBiomeSource.class)
public class MixinVanillaLayeredBiomeSource { public class MixinVanillaLayeredBiomeSource {
@Shadow @Shadow
@Final @Final
@Mutable @Mutable
private static Set<Biome> BIOMES; private static Set<Biome> BIOMES;
@Inject(method = "<clinit>", at = @At("RETURN")) @Inject(method = "<clinit>", at = @At("RETURN"))
private static void cinit(CallbackInfo info){ private static void cinit(CallbackInfo info) {
BIOMES = new HashSet<>(BIOMES); BIOMES = new HashSet<>(BIOMES);
} }
@ -51,5 +51,4 @@ public class MixinVanillaLayeredBiomeSource {
private static void fabric_injectBiome(Biome biome) { private static void fabric_injectBiome(Biome biome) {
BIOMES.add(biome); BIOMES.add(biome);
} }
} }

View file

@ -16,31 +16,32 @@
package net.fabricmc.fabric.api.blockrenderlayer.v1; package net.fabricmc.fabric.api.blockrenderlayer.v1;
import net.fabricmc.fabric.impl.blockrenderlayer.BlockRenderLayerMapImpl;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.RenderLayer;
import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item; 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. * Use to associate blocks or fluids with block render layer other than default.
* Replaces the {@code renderLayer} property previously on {@code Block}.<p> * Replaces the {@code renderLayer} property previously on {@code Block}.
* *
* {@code BlockRenderLayer} controls how sprite pixels for fluids and blocks are blended * <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> * with the scene. Consult the vanilla {@code BlockRenderLayer} implementation for examples.
* *
* The Fabric Renderer API can be used to control this at a per-quad level at the code * <p>The Fabric Renderer API can be used to control this at a per-quad level at the code
* via {@code BlendMode}.<p> * via {@code BlendMode}.
* *
* Client-side only. * <p>Client-side only.
*/ */
public interface BlockRenderLayerMap { public interface BlockRenderLayerMap {
BlockRenderLayerMap INSTANCE = BlockRenderLayerMapImpl.INSTANCE; 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. * 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. * 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 block Identifies block to be mapped.
* @param renderLayer Render layer. Should be one of the layers used for terrain rendering. * @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. * 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. * 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 fluid Identifies fluid to be mapped.
* @param renderLayer Render layer. Should be one of the layers used for terrain rendering. * @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.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import net.minecraft.block.Block;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.RenderLayer;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.minecraft.block.Block;
import net.minecraft.fluid.Fluid;
public class BlockRenderLayerMapImpl implements BlockRenderLayerMap { public class BlockRenderLayerMapImpl implements BlockRenderLayerMap {
private BlockRenderLayerMapImpl() {} private BlockRenderLayerMapImpl() { }
@Override @Override
public void putBlock(Block block, RenderLayer renderLayer) { public void putBlock(Block block, RenderLayer renderLayer) {
if (block == null) throw new IllegalArgumentException("Request to map null block to BlockRenderLayer"); 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); fluidHandler.accept(fluid, renderLayer);
} }
public static final BlockRenderLayerMap INSTANCE = new BlockRenderLayerMapImpl(); public static final BlockRenderLayerMap INSTANCE = new BlockRenderLayerMapImpl();
private static Map<Block, RenderLayer> blockRenderLayerMap = new HashMap<>(); 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 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.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 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.block.Block;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item;
import net.fabricmc.fabric.impl.blockrenderlayer.BlockRenderLayerMapImpl;
@Mixin(class_4696.class) @Mixin(class_4696.class)
public class MixinBlockRenderLayer { public class MixinBlockRenderLayer {
@Shadow private static Map<Block, RenderLayer> field_21469; @Shadow private static Map<Block, RenderLayer> field_21469;
@Shadow private static Map<Item, RenderLayer> field_21470; @Shadow private static Map<Item, RenderLayer> field_21470;
@Shadow private static Map<Fluid, RenderLayer> field_21471; @Shadow private static Map<Fluid, RenderLayer> field_21471;
@Inject(method = "<clinit>*", at = @At("RETURN")) @Inject(method = "<clinit>*", at = @At("RETURN"))
private static void onInitialize(CallbackInfo info) { private static void onInitialize(CallbackInfo info) {
BlockRenderLayerMapImpl.initialize(field_21469::put, field_21470::put, field_21471::put); BlockRenderLayerMapImpl.initialize(field_21469::put, field_21470::put, field_21471::put);

View file

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

View file

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

View file

@ -17,15 +17,17 @@
package net.fabricmc.fabric.mixin.registrycommands; package net.fabricmc.fabric.mixin.registrycommands;
import com.mojang.brigadier.CommandDispatcher; 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.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 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) @Mixin(CommandManager.class)
public class MixinCommandManagerIntegrated { public class MixinCommandManagerIntegrated {
@Shadow @Shadow

View file

@ -16,27 +16,28 @@
package net.fabricmc.fabric.mixin.registrycommands; package net.fabricmc.fabric.mixin.registrycommands;
import java.io.File;
import java.net.Proxy;
import com.mojang.authlib.GameProfileRepository; import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.minecraft.MinecraftSessionService; import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.datafixers.DataFixer; 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.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.File; import net.minecraft.server.MinecraftServer;
import java.net.Proxy; 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) @Mixin(MinecraftDedicatedServer.class)
public abstract class MixinMinecraftDedicatedServer extends MinecraftServer { 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) { 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); 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 @FunctionalInterface
public interface ContainerScreenFactory<C extends Container> { public interface ContainerScreenFactory<C extends Container> {
AbstractContainerScreen create(C container); AbstractContainerScreen create(C container);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,10 +16,11 @@
package net.fabricmc.fabric.mixin.container; package net.fabricmc.fabric.mixin.container;
import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.server.network.ServerPlayerEntity;
@Mixin(ServerPlayerEntity.class) @Mixin(ServerPlayerEntity.class)
public interface ServerPlayerEntityAccessor { public interface ServerPlayerEntityAccessor {
@Accessor @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 * 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> { 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; 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.Block;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.tag.Tag; 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> { public interface FlammableBlockRegistry extends Block2ObjectMap<FlammableBlockRegistry.Entry> {
static FlammableBlockRegistry getDefaultInstance() { static FlammableBlockRegistry getDefaultInstance() {
return getInstance(Blocks.FIRE); return getInstance(Blocks.FIRE);
@ -39,7 +40,7 @@ public interface FlammableBlockRegistry extends Block2ObjectMap<FlammableBlockRe
this.add(tag, new Entry(burn, spread)); this.add(tag, new Entry(burn, spread));
} }
public static final class Entry { final class Entry {
private final int burn, spread; private final int burn, spread;
public Entry(int burn, int 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. * Registry of items to 0-32767 fuel burn time values, in in-game ticks.
*/ */
public interface FuelRegistry extends Item2ObjectMap<Integer> { 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; package net.fabricmc.fabric.api.registry;
import net.minecraft.world.loot.entry.LootEntry;
import net.fabricmc.fabric.impl.registry.LootEntryTypeRegistryImpl; 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 Use {@link net.fabricmc.fabric.api.loot.v1.LootEntryTypeRegistry}
*/ */
@Deprecated @Deprecated
public interface LootEntryTypeRegistry { public interface LootEntryTypeRegistry {
@Deprecated @Deprecated
final LootEntryTypeRegistry INSTANCE = LootEntryTypeRegistryImpl.INSTANCE; LootEntryTypeRegistry INSTANCE = LootEntryTypeRegistryImpl.INSTANCE;
@Deprecated @Deprecated
void register(LootEntry.Serializer<?> serializer); void register(LootEntry.Serializer<?> serializer);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,18 +16,20 @@
package net.fabricmc.fabric.mixin.crash; package net.fabricmc.fabric.mixin.crash;
import net.fabricmc.loader.api.FabricLoader; import java.util.Map;
import net.fabricmc.loader.api.ModContainer; import java.util.TreeMap;
import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.crash.CrashReportSection;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map; import net.minecraft.util.crash.CrashReport;
import java.util.TreeMap; import net.minecraft.util.crash.CrashReportSection;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
@Mixin(CrashReport.class) @Mixin(CrashReport.class)
public abstract class MixinCrashReport { public abstract class MixinCrashReport {
@ -38,6 +40,7 @@ public abstract class MixinCrashReport {
private void fillSystemDetails(CallbackInfo info) { private void fillSystemDetails(CallbackInfo info) {
getSystemDetailsSection().add("Fabric Mods", () -> { getSystemDetailsSection().add("Fabric Mods", () -> {
Map<String, String> mods = new TreeMap<>(); Map<String, String> mods = new TreeMap<>();
for (ModContainer container : FabricLoader.getInstance().getAllMods()) { for (ModContainer container : FabricLoader.getInstance().getAllMods()) {
mods.put(container.getMetadata().getId(), container.getMetadata().getName() + " " + container.getMetadata().getVersion().getFriendlyString()); 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.entity.Entity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.world.dimension.DimensionType;
/** /**
* Responsible for placing an Entity once they have entered a dimension. * 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. * Handles the placement of an entity going to a dimension.
* Utilized by {@link FabricDimensions#teleport(Entity, DimensionType, EntityPlacer)} to specify placement logic when needed. * 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. * or the creation of a chunk loading ticket.
* *
* @param portalDir the direction the portal is facing, meaningless if no portal was used * @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; package net.fabricmc.fabric.api.dimension.v1;
import java.util.function.BiFunction;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import net.minecraft.entity.Entity; 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.Dimension;
import net.minecraft.world.dimension.DimensionType; 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. * 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}. * {@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 { public final class FabricDimensionType extends DimensionType {
private final EntityPlacer defaultPlacement; private final EntityPlacer defaultPlacement;
private int desiredRawId; 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; private int fixedRawId;
/** /**
@ -77,7 +77,7 @@ public final class FabricDimensionType extends DimensionType {
/** /**
* Return the current raw id for this dimension type. * 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. * 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. * 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. * 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. * 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 * {@link EntityPlacer#placeEntity(Entity, ServerWorld, Direction, double, double) placeEntity} method
* is called. * 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 * If this method is not called, the value defaults to the raw registry id
* of the dimension type. * 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 * when it does not conflict with any existing id, and the world
* save does not map the dimension to a different raw id. * 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}. * 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. * a unique name both for the dimension suffix and the save directory.
* *
* @param dimensionId the id used to name and register the dimension * @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.checkArgument(Registry.DIMENSION.get(dimensionId) == null);
Preconditions.checkState(this.defaultPlacer != null, "No defaultPlacer has been specified!"); Preconditions.checkState(this.defaultPlacer != null, "No defaultPlacer has been specified!");
Preconditions.checkState(this.factory != null, "No dimension factory has been specified!"); Preconditions.checkState(this.factory != null, "No dimension factory has been specified!");
String suffix = dimensionId.getNamespace() + "_" + dimensionId.getPath(); String suffix = dimensionId.getNamespace() + "_" + dimensionId.getPath();
String saveDir = "DIM_" + dimensionId.getNamespace() + "_" + dimensionId.getPath(); String saveDir = "DIM_" + dimensionId.getNamespace() + "_" + dimensionId.getPath();
FabricDimensionType built = new FabricDimensionType(suffix, saveDir, this); FabricDimensionType built = new FabricDimensionType(suffix, saveDir, this);

View file

@ -17,10 +17,12 @@
package net.fabricmc.fabric.api.dimension.v1; package net.fabricmc.fabric.api.dimension.v1;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.world.dimension.DimensionType; 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. * 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. * 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> * <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 * is {@link FabricDimensionType#getDefaultPlacement()}. If {@code destination} is
* the nether or the overworld, the default logic is the vanilla path. * the nether or the overworld, the default logic is the vanilla path.
* For any other dimension, the default placement behaviour is undefined. * 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 * {@code lastPortalDirectionVector}, and {@code lastPortalDirection} fields should be updated
* before calling this method. * 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. * the returned entity for any further manipulation.
* *
* @param teleported the entity to teleport * @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. * 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> * <pre>{@code teleported.changeDimension(destination)}</pre>
* The {@code customPlacement} may itself return {@code null}, in which case * The {@code customPlacement} may itself return {@code null}, in which case
* the default placement logic for that dimension will be run. * 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 * is {@link FabricDimensionType#getDefaultPlacement()}. If {@code destination} is the nether
* or the overworld, the default logic is the vanilla path. * or the overworld, the default logic is the vanilla path.
* For any other dimension, the default placement behaviour is undefined. * 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 * {@code lastPortalDirectionVector}, and {@code lastPortalDirection} fields should be updated
* before calling this method. * 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. * the returned entity for any further manipulation.
* *
* @param teleported the entity to teleport * @param teleported the entity to teleport

View file

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

View file

@ -19,7 +19,7 @@ package net.fabricmc.fabric.impl.dimension;
import net.minecraft.nbt.CompoundTag; 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 { public interface DimensionIdsHolder {
CompoundTag fabric_getDimensionIds(); CompoundTag fabric_getDimensionIds();

View file

@ -16,18 +16,20 @@
package net.fabricmc.fabric.impl.dimension; package net.fabricmc.fabric.impl.dimension;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; import org.apache.logging.log4j.LogManager;
import net.fabricmc.fabric.api.network.PacketContext; import org.apache.logging.log4j.Logger;
import net.fabricmc.fabric.impl.registry.RemapException;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.text.LiteralText; 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 { public final class FabricDimensionClientInit {
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
@ -55,8 +57,7 @@ public final class FabricDimensionClientInit {
LOGGER.error("Dimension id remapping failed!", e); LOGGER.error("Dimension id remapping failed!", e);
MinecraftClient.getInstance().execute(() -> ((ClientPlayerEntity) ctx.getPlayer()).networkHandler.getConnection().disconnect( 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; package net.fabricmc.fabric.impl.dimension;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import net.fabricmc.fabric.api.dimension.v1.EntityPlacer; import org.apache.logging.log4j.LogManager;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensionType; import org.apache.logging.log4j.Logger;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensions;
import net.fabricmc.fabric.mixin.EntityHooks;
import net.minecraft.block.pattern.BlockPattern; import net.minecraft.block.pattern.BlockPattern;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.world.dimension.DimensionType; 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 { public final class FabricDimensionInternals {
private FabricDimensionInternals() { private FabricDimensionInternals() {
@ -38,11 +40,11 @@ public final class FabricDimensionInternals {
public static final Logger LOGGER = LogManager.getLogger(); 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<>(); 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; private static EntityPlacer customPlacement;
@ -65,9 +67,11 @@ public final class FabricDimensionInternals {
// Set values used by `PortalForcer#changeDimension` to prevent a NPE crash. // Set values used by `PortalForcer#changeDimension` to prevent a NPE crash.
EntityHooks access = ((EntityHooks) entity); EntityHooks access = ((EntityHooks) entity);
if (entity.getLastPortalDirectionVector() == null) { if (entity.getLastPortalDirectionVector() == null) {
access.setLastPortalDirectionVector(entity.getRotationVector()); access.setLastPortalDirectionVector(entity.getRotationVector());
} }
if (entity.getLastPortalDirection() == null) { if (entity.getLastPortalDirection() == null) {
access.setLastPortalDirection(entity.getHorizontalFacing()); 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 // Custom placement logic, falls back to default dimension placement if no placement or target found
EntityPlacer customPlacement = FabricDimensionInternals.customPlacement; EntityPlacer customPlacement = FabricDimensionInternals.customPlacement;
if (customPlacement != null) { if (customPlacement != null) {
BlockPattern.TeleportTarget customTarget = customPlacement.placeEntity(teleported, destination, portalDir, portalX, portalY); 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 // Default placement logic, falls back to vanilla if not a fabric dimension
DimensionType dimType = destination.getDimension().getType(); DimensionType dimType = destination.getDimension().getType();
if (dimType instanceof FabricDimensionType) { if (dimType instanceof FabricDimensionType) {
BlockPattern.TeleportTarget defaultTarget = ((FabricDimensionType) dimType).getDefaultPlacement().placeEntity(teleported, destination, portalDir, portalX, portalY); BlockPattern.TeleportTarget defaultTarget = ((FabricDimensionType) dimType).getDefaultPlacement().placeEntity(teleported, destination, portalDir, portalX, portalY);
if (defaultTarget == null) { if (defaultTarget == null) {
throw new IllegalStateException("Mod dimension " + DimensionType.getId(dimType) + " returned an invalid teleport target"); throw new IllegalStateException("Mod dimension " + DimensionType.getId(dimType) + " returned an invalid teleport target");
} }
return defaultTarget; return defaultTarget;
} }
@ -121,5 +128,4 @@ public final class FabricDimensionInternals {
customPlacement = null; customPlacement = null;
} }
} }
} }

View file

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

View file

@ -16,17 +16,18 @@
package net.fabricmc.fabric.mixin; 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.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 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) @Mixin(Entity.class)
public abstract class MixinEntity { public abstract class MixinEntity {
// Inject right before the direction vector is retrieved by the game // 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;")) @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) { private void onGetPortal(DimensionType dimension, CallbackInfoReturnable<Entity> cir) {

View file

@ -16,7 +16,13 @@
package net.fabricmc.fabric.mixin; 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.block.pattern.BlockPattern;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld; 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.Direction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.PortalForcer; import net.minecraft.world.PortalForcer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import net.fabricmc.fabric.impl.dimension.FabricDimensionInternals;
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;
@Mixin(PortalForcer.class) @Mixin(PortalForcer.class)
public abstract class MixinPortalForcer { public abstract class MixinPortalForcer {

View file

@ -16,13 +16,14 @@
package net.fabricmc.fabric.mixin.idremap; 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.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 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 // NOTE: This probably goes into dimension-fixes
@Mixin(DimensionType.class) @Mixin(DimensionType.class)
public abstract class MixinDimensionRawIndexFix { public abstract class MixinDimensionRawIndexFix {

View file

@ -17,18 +17,20 @@
package net.fabricmc.fabric.mixin.idremap; package net.fabricmc.fabric.mixin.idremap;
import com.mojang.datafixers.DataFixer; 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.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 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) @Mixin(LevelProperties.class)
public abstract class MixinLevelProperties implements DimensionIdsHolder { public abstract class MixinLevelProperties implements DimensionIdsHolder {
@Unique @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")) @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) { private void readDimensionIds(CompoundTag data, DataFixer fixer, int version, CompoundTag player, CallbackInfo ci) {
CompoundTag savedIds = data.getCompound("fabric_DimensionIds"); CompoundTag savedIds = data.getCompound("fabric_DimensionIds");
try { try {
this.fabricDimensionIds = DimensionIdsFixer.apply(savedIds); this.fabricDimensionIds = DimensionIdsFixer.apply(savedIds);
} catch (RemapException e) { } catch (RemapException e) {

View file

@ -16,12 +16,14 @@
package net.fabricmc.fabric.mixin.idremap; 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.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import net.minecraft.world.level.storage.LevelStorage;
import net.fabricmc.fabric.impl.dimension.DimensionRemapException;
@Mixin(LevelStorage.class) @Mixin(LevelStorage.class)
public abstract class MixinLevelStorage { 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) @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; 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.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 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) @Mixin(PlayerManager.class)
public abstract class MixinPlayerManager { 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")) @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) { private void onPlayerConnect(ClientConnection conn, ServerPlayerEntity player, CallbackInfo info) {

View file

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

View file

@ -16,31 +16,33 @@
package net.fabricmc.fabric.api.event.client.player; 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.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.hit.HitResult; 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 * 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 * 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. * ItemStack will cause the event to leave, and no block to be picked.
*/ */
public interface ClientPickBlockApplyCallback { public interface ClientPickBlockApplyCallback {
public static final Event<ClientPickBlockApplyCallback> EVENT = EventFactory.createArrayBacked(ClientPickBlockApplyCallback.class, Event<ClientPickBlockApplyCallback> EVENT = EventFactory.createArrayBacked(ClientPickBlockApplyCallback.class,
(listeners) -> (player, result, _stack) -> { (listeners) -> (player, result, _stack) -> {
ItemStack stack = _stack; ItemStack stack = _stack;
for (ClientPickBlockApplyCallback event : listeners) { for (ClientPickBlockApplyCallback event : listeners) {
stack = event.pick(player, result, stack); stack = event.pick(player, result, stack);
if (stack.isEmpty()) {
return ItemStack.EMPTY; if (stack.isEmpty()) {
return ItemStack.EMPTY;
}
} }
}
return stack; return stack;
} }
); );
ItemStack pick(PlayerEntity player, HitResult result, ItemStack stack); ItemStack pick(PlayerEntity player, HitResult result, ItemStack stack);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,10 +16,6 @@
package net.fabricmc.fabric.impl.event; 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.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -28,6 +24,11 @@ import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView; 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 { public class InteractionEventsRouterClient implements ClientModInitializer {
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {

View file

@ -16,7 +16,13 @@
package net.fabricmc.fabric.mixin.eventsinteraction; 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.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity; 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.util.math.Vec3d;
import net.minecraft.world.GameMode; import net.minecraft.world.GameMode;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import org.spongepowered.asm.mixin.injection.At; import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
import org.spongepowered.asm.mixin.injection.Inject; import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.fabricmc.fabric.api.event.player.UseEntityCallback;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.fabricmc.fabric.api.event.player.UseItemCallback;
@Mixin(ClientPlayerInteractionManager.class) @Mixin(ClientPlayerInteractionManager.class)
public class MixinClientPlayerInteractionManager { 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) @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) { 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); ActionResult result = AttackBlockCallback.EVENT.invoker().interact(client.player, client.world, Hand.MAIN_HAND, pos, direction);
if (result != ActionResult.PASS) { if (result != ActionResult.PASS) {
info.setReturnValue(result == ActionResult.SUCCESS); info.setReturnValue(result == ActionResult.SUCCESS);
info.cancel(); info.cancel();
@ -70,6 +77,7 @@ public class MixinClientPlayerInteractionManager {
} }
ActionResult result = AttackBlockCallback.EVENT.invoker().interact(client.player, client.world, Hand.MAIN_HAND, pos, direction); ActionResult result = AttackBlockCallback.EVENT.invoker().interact(client.player, client.world, Hand.MAIN_HAND, pos, direction);
if (result != ActionResult.PASS) { if (result != ActionResult.PASS) {
info.setReturnValue(result == ActionResult.SUCCESS); info.setReturnValue(result == ActionResult.SUCCESS);
info.cancel(); 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) @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) { public void interactBlock(ClientPlayerEntity player, ClientWorld world, Hand hand, BlockHitResult blockHitResult, CallbackInfoReturnable<ActionResult> info) {
ActionResult result = UseBlockCallback.EVENT.invoker().interact(player, world, hand, blockHitResult); ActionResult result = UseBlockCallback.EVENT.invoker().interact(player, world, hand, blockHitResult);
if (result != ActionResult.PASS) { if (result != ActionResult.PASS) {
if (result == ActionResult.SUCCESS) { if (result == ActionResult.SUCCESS) {
this.networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(hand, blockHitResult)); this.networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(hand, blockHitResult));
} }
info.setReturnValue(result); info.setReturnValue(result);
info.cancel(); 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) @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) { public void interactItem(PlayerEntity player, World world, Hand hand, CallbackInfoReturnable<TypedActionResult<ItemStack>> info) {
TypedActionResult<ItemStack> result = UseItemCallback.EVENT.invoker().interact(player, world, hand); TypedActionResult<ItemStack> result = UseItemCallback.EVENT.invoker().interact(player, world, hand);
if (result.getResult() != ActionResult.PASS) { if (result.getResult() != ActionResult.PASS) {
if (result.getResult() == ActionResult.SUCCESS) { if (result.getResult() == ActionResult.SUCCESS) {
this.networkHandler.sendPacket(new PlayerInteractItemC2SPacket(hand)); this.networkHandler.sendPacket(new PlayerInteractItemC2SPacket(hand));
} }
info.setReturnValue(result); info.setReturnValue(result);
info.cancel(); info.cancel();
return; 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) @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) { public void attackEntity(PlayerEntity player, Entity entity, CallbackInfo info) {
ActionResult result = AttackEntityCallback.EVENT.invoker().interact(player, player.getEntityWorld(), Hand.MAIN_HAND /* TODO */, entity, null); ActionResult result = AttackEntityCallback.EVENT.invoker().interact(player, player.getEntityWorld(), Hand.MAIN_HAND /* TODO */, entity, null);
if (result != ActionResult.PASS) { if (result != ActionResult.PASS) {
if (result == ActionResult.SUCCESS) { if (result == ActionResult.SUCCESS) {
this.networkHandler.sendPacket(new PlayerInteractEntityC2SPacket(entity)); this.networkHandler.sendPacket(new PlayerInteractEntityC2SPacket(entity));
} }
info.cancel(); 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) @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) { 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); ActionResult result = UseEntityCallback.EVENT.invoker().interact(player, player.getEntityWorld(), hand, entity, hitResult);
if (result != ActionResult.PASS) { if (result != ActionResult.PASS) {
if (result == ActionResult.SUCCESS) { if (result == ActionResult.SUCCESS) {
Vec3d hitVec = hitResult.getPos().subtract(entity.getX(), entity.getY(), entity.getZ()); Vec3d hitVec = hitResult.getPos().subtract(entity.getX(), entity.getY(), entity.getZ());
this.networkHandler.sendPacket(new PlayerInteractEntityC2SPacket(entity, hand, hitVec)); this.networkHandler.sendPacket(new PlayerInteractEntityC2SPacket(entity, hand, hitVec));
} }
info.setReturnValue(result); info.setReturnValue(result);
info.cancel(); info.cancel();
return; return;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,24 +16,23 @@
package net.fabricmc.fabric.api.event.client; package net.fabricmc.fabric.api.event.client;
import net.fabricmc.fabric.api.event.Event; import java.util.List;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.client.item.TooltipContext; import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.text.Text; 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 { 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) -> Event<ItemTooltipCallback> EVENT = EventFactory.createArrayBacked(ItemTooltipCallback.class, (listeners) ->
(stack, tooltipContext, lines) -> { (stack, tooltipContext, lines) -> {
for(ItemTooltipCallback callback : listeners){ for (ItemTooltipCallback callback : listeners) {
callback.getTooltip(stack, tooltipContext, lines); callback.getTooltip(stack, tooltipContext, lines);
}
} }
); });
/** /**
* Called when an item stack's tooltip is rendered. Text added to {@code lines} will be * 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 * @param lines the list containing the lines of text displayed on the stack's tooltip
*/ */
void getTooltip(ItemStack stack, TooltipContext tooltipContext, List<Text> lines); void getTooltip(ItemStack stack, TooltipContext tooltipContext, List<Text> lines);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,18 +16,18 @@
package net.fabricmc.fabric.api.client.itemgroup; 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.ItemGroup;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.DefaultedList; import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import java.util.List; import net.fabricmc.fabric.impl.itemgroup.ItemGroupExtensions;
import java.util.function.Consumer;
import java.util.function.Supplier;
public final class FabricItemGroupBuilder { public final class FabricItemGroupBuilder {
private Identifier identifier; private Identifier identifier;
private Supplier<ItemStack> stackSupplier = () -> ItemStack.EMPTY; private Supplier<ItemStack> stackSupplier = () -> ItemStack.EMPTY;
private Consumer<List<ItemStack>> stacksForDisplay; 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 * @param identifier the id will become the name of the ItemGroup and will be used for the translation key
* @return a FabricItemGroupBuilder * @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 * @param stackSupplier the supplier should return the item stack that you wish to show on the tab
* @return a reference to the FabricItemGroupBuilder * @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 * @param appender Add ItemStack's to this list to show in the ItemGroup
* @return a reference to the FabricItemGroupBuilder * @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 * @param stacksForDisplay Add ItemStack's to this list to show in the ItemGroup
* @return a reference to the FabricItemGroupBuilder * @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 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 * @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 * @return An instance of the built ItemGroup
*/ */
@ -110,9 +110,9 @@ public final class FabricItemGroupBuilder {
stacksForDisplay.accept(stacks); stacksForDisplay.accept(stacks);
return; return;
} }
super.appendStacks(stacks); super.appendStacks(stacks);
} }
}; };
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,15 +16,16 @@
package net.fabricmc.fabric.api.client.keybinding; 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.options.KeyBinding;
import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.InputUtil;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.fabricmc.fabric.mixin.client.keybinding.KeyCodeAccessor;
/** /**
* Expanded version of {@link KeyBinding} for use by Fabric mods. * 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)}! * {@link KeyBindingRegistry#register(FabricKeyBinding)}!
*/ */
public class FabricKeyBinding extends KeyBinding { public class FabricKeyBinding extends KeyBinding {

View file

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

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