From 56e22834c7a39f3c1e10d2b6f9b886fd1102d9fc Mon Sep 17 00:00:00 2001 From: FalsePattern <30945458+FalsePattern@users.noreply.github.com> Date: Thu, 9 Mar 2023 21:44:17 +0100 Subject: [PATCH] trying random stuff, nothing serious yet --- README.MD | 19 +++++++ gradle.properties | 8 +-- .../java/com/falsepattern/chunk/ChunkAPI.java | 11 ---- .../chunk/api/ChunkDataManager.java | 55 ++++++++++++++++++ .../chunk/api/ChunkDataRegistry.java | 17 ++++++ .../falsepattern/chunk/api/ModdedChunk.java | 38 +++++++++++++ .../ManagerRegistrationException.java | 35 ++++++++++++ .../falsepattern/chunk/api/package-info.java | 4 ++ .../falsepattern/chunk/internal/ChunkAPI.java | 27 +++++++++ .../chunk/internal/ChunkDataRegistryImpl.java | 56 +++++++++++++++++++ .../chunk/{ => internal}/Common.java | 2 +- .../chunk/{ => internal}/Tags.java | 2 +- .../mixins/common/vanilla/ChunkDataMixin.java | 48 ++++++++++++++++ .../{ => internal}/mixin/plugin/Mixin.java | 2 +- .../mixin/plugin/MixinPlugin.java | 4 +- .../mixin/plugin/TargetedMod.java | 2 +- .../chunk/internal/package-info.java | 4 ++ .../net/minecraft/world/chunk/Chunk.java | 12 ++++ src/main/resources/mixins.fplib_chunkapi.json | 4 +- 19 files changed, 327 insertions(+), 23 deletions(-) create mode 100644 README.MD delete mode 100644 src/main/java/com/falsepattern/chunk/ChunkAPI.java create mode 100644 src/main/java/com/falsepattern/chunk/api/ChunkDataManager.java create mode 100644 src/main/java/com/falsepattern/chunk/api/ChunkDataRegistry.java create mode 100644 src/main/java/com/falsepattern/chunk/api/ModdedChunk.java create mode 100644 src/main/java/com/falsepattern/chunk/api/exception/ManagerRegistrationException.java create mode 100644 src/main/java/com/falsepattern/chunk/api/package-info.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/ChunkAPI.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/ChunkDataRegistryImpl.java rename src/main/java/com/falsepattern/chunk/{ => internal}/Common.java (86%) rename src/main/java/com/falsepattern/chunk/{ => internal}/Tags.java (87%) create mode 100644 src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/ChunkDataMixin.java rename src/main/java/com/falsepattern/chunk/{ => internal}/mixin/plugin/Mixin.java (96%) rename src/main/java/com/falsepattern/chunk/{ => internal}/mixin/plugin/MixinPlugin.java (93%) rename src/main/java/com/falsepattern/chunk/{ => internal}/mixin/plugin/TargetedMod.java (96%) create mode 100644 src/main/java/com/falsepattern/chunk/internal/package-info.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/stubpackage/net/minecraft/world/chunk/Chunk.java diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..f5b03da --- /dev/null +++ b/README.MD @@ -0,0 +1,19 @@ +# ChunkAPI +A multipurpose chunk hooking library that makes adding arbitrary extra data to chunks much easier. + +## How +Read the code. +TL;DR: Replacing the vanilla chunk netcode and save logic with a modular system, and reimplementing the stock vanilla +logic on top of this. You can then add your own stuff. + +## Compatibility +This will definitely break things, but the mods that were developed on top of this would've broken stuff anyways, and +having the most breaking changes centralized in a single hook mod makes writing compat much simpler. + +## API +You can use the api of this mod to add your own chunk data. Minimum requirements you need: +1. A unique ID string for your data (collision avoidance) +2. An object that can be stored in a Map inside each chunk (note: the vanilla replacements bypass this!) +3. Packet data size/serialization/deserialization (for client/server communication) +4. NBT serialization/serialization (for savegames) + diff --git a/gradle.properties b/gradle.properties index 518680d..e50656f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ modName = ChunkAPI # This is a case-sensitive string to identify your mod. Convention is to use lower case. -modId = fplib_chunkapi +modId = fp_chunkapi # The "root package" of your mod. All of your mod classes *should* be placed under this package for simplicity. modGroup = com.falsepattern.chunk @@ -145,13 +145,13 @@ usesMixins = true # if a dependency requires mixins BUT this mod doesn't. hasMixinDeps = false # Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. -mixinPlugin = mixin.plugin.MixinPlugin +mixinPlugin = internal.mixin.plugin.MixinPlugin # Whether you want the plugin to be configured as a PREINIT mixin mixinPluginPreInit = false # The minimum SpongePowered Mixins version required by the plugin. Internal default is 0.8.5 (GasStation) mixinPluginMinimumVersion = # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! -mixinsPackage = mixin.mixins +mixinsPackage = internal.mixin.mixins # Specify any custom mixin .json configs here. If you have multiple, comma-separate them. If you don't want to load # any jsons manually, leave this empty. You can use custom configs even if you already have a plugin added. # note: mixins..json is used by the mixinPlugin's autogenerated config. Additionally, the refmap from the mixinsPackage @@ -201,7 +201,7 @@ usesShadowedDependencies = false # path will be removed, and all classes that refer to said classes will be modified so that the "stubpackage" will map # to the root package instead. This is useful for referring to compile-time inaccessible classes, such as classes in the # default package -remapStubs = false +remapStubs = true # Set this to true if you want to publish a proprietary mod without visible source code. #noPublishedSources = diff --git a/src/main/java/com/falsepattern/chunk/ChunkAPI.java b/src/main/java/com/falsepattern/chunk/ChunkAPI.java deleted file mode 100644 index 17ee8f6..0000000 --- a/src/main/java/com/falsepattern/chunk/ChunkAPI.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.falsepattern.chunk; - -import cpw.mods.fml.common.Mod; - -@Mod(modid = Tags.MODID, - version = Tags.VERSION, - name = Tags.MODNAME, - acceptedMinecraftVersions = "[1.7.10]", - dependencies = "required-after:falsepatternlib@[0.10.15,);") -public class ChunkAPI { -} \ No newline at end of file diff --git a/src/main/java/com/falsepattern/chunk/api/ChunkDataManager.java b/src/main/java/com/falsepattern/chunk/api/ChunkDataManager.java new file mode 100644 index 0000000..6a21ea6 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/api/ChunkDataManager.java @@ -0,0 +1,55 @@ +package com.falsepattern.chunk.api; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.world.chunk.Chunk; + +/** + * Singleton instances that can manage custom in chunks. + * Note: All the methods should be thread-safe and stateless unless otherwise specified. + */ +public interface ChunkDataManager { + /** + * The unique identifier of your data. The common convention is modid:dataid. + * @return The unique identifier of your data. Should be unique across all mods. + * @apiNote Ideally, this should be an interned string for maximum performance. (see {@link String#intern()}). + * @implNote This is used to identify your data in packets and NBT tags. + */ + String id(); + /** + * Initializes your data in a chunk. This is called when the chunk is first created. + * @param chunk The chunk to initialize. + */ + void init(ModdedChunk chunk); + /** + * The amount of bytes your data will take up in a packet. + * @param chunk The chunk that the data is in. + * @return The amount of bytes your data will take up in a packet. -1 if the data is not present. + */ + int getPacketSize(ModdedChunk chunk); + /** + * Serializes your data into a packet. Not called if {@link #getPacketSize(ModdedChunk)} returns -1. + * @param chunk The chunk that the data is in. + * @param buffer The packet buffer to write to. + */ + void writeToPacket(ModdedChunk chunk, PacketBuffer buffer); + /** + * Deserializes your data from a packet. Not called if {@link #getPacketSize(ModdedChunk)} returned -1 on the other end. + * @param chunk The chunk that the data is in. + * @param buffer The packet buffer to read from. + * @return The deserialized data. + */ + void readFromPacket(ModdedChunk chunk, PacketBuffer buffer); + /** + * Serializes your data into an NBT tag. This is used when saving the chunk to disk. + * @param chunk The chunk that the data is in. + * @param tag The tag to write to. + */ + void writeToNBT(ModdedChunk chunk, NBTTagCompound tag); + /** + * Deserializes your data from an NBT tag. This is used when loading the chunk from disk. + * @param chunk The chunk that the data gets loaded into. + * @param tag The tag to read from. + */ + void readFromNBT(ModdedChunk chunk, NBTTagCompound tag); +} diff --git a/src/main/java/com/falsepattern/chunk/api/ChunkDataRegistry.java b/src/main/java/com/falsepattern/chunk/api/ChunkDataRegistry.java new file mode 100644 index 0000000..557a053 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/api/ChunkDataRegistry.java @@ -0,0 +1,17 @@ +package com.falsepattern.chunk.api; + +import com.falsepattern.chunk.internal.ChunkDataRegistryImpl; +import com.falsepattern.chunk.api.exception.ManagerRegistrationException; + +/** + * This class is used to register ChunkDataManagers. + */ +public class ChunkDataRegistry { + public static void registerDataManager(ChunkDataManager manager) throws ManagerRegistrationException { + ChunkDataRegistryImpl.registerDataManager(manager); + } + + public static void disableDataManager(String id) { + ChunkDataRegistryImpl.disableDataManager(id); + } +} diff --git a/src/main/java/com/falsepattern/chunk/api/ModdedChunk.java b/src/main/java/com/falsepattern/chunk/api/ModdedChunk.java new file mode 100644 index 0000000..e8270f5 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/api/ModdedChunk.java @@ -0,0 +1,38 @@ +package com.falsepattern.chunk.api; + +/** + * This interface is injected into {@link net.minecraft.world.chunk.Chunk} by ChunkAPI. You can cast any Chunk instance + * to this to access the API methods. + */ +public interface ModdedChunk { + /** + * Gets the data stored in this chunk by the specified manager. + * @param manager The manager to get the data from. + * @return The data stored in this chunk by the specified manager. + * @param The type of the data. + */ + T getData(ChunkDataManager manager); + + /** + * Sets the data stored in this chunk by the specified manager. + * @param manager The manager to set the data for. + * @param data The data to store in this chunk. + * @param The type of the data. + */ + void setData(ChunkDataManager manager, T data); + + /** + * Checks if this chunk has data stored by the specified manager. + * @param manager The manager to check for. + * @return True if this chunk has data stored by the specified manager. + */ + boolean hasData(ChunkDataManager manager); + + /** + * Removes the data stored in this chunk by the specified manager. + * @param manager The manager to remove the data from. + * @return The data that was stored in this chunk by the specified manager. + * @param The type of the data. + */ + T removeData(ChunkDataManager manager); +} diff --git a/src/main/java/com/falsepattern/chunk/api/exception/ManagerRegistrationException.java b/src/main/java/com/falsepattern/chunk/api/exception/ManagerRegistrationException.java new file mode 100644 index 0000000..a493fef --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/api/exception/ManagerRegistrationException.java @@ -0,0 +1,35 @@ +package com.falsepattern.chunk.api.exception; + +import com.falsepattern.chunk.api.ChunkDataManager; + +/** + * This exception is thrown when a {@link ChunkDataManager} could not be registered. + *

+ * Possible reasons include: + *

    + *
  • The manager is already registered
  • + *
  • The manager's name collides with a different manager
  • + *
  • The manager was registered too late (should be done in init)
  • + *
+ */ +public class ManagerRegistrationException extends RuntimeException { + public ManagerRegistrationException() { + super(); + } + + public ManagerRegistrationException(String message) { + super(message); + } + + public ManagerRegistrationException(String message, Throwable cause) { + super(message, cause); + } + + public ManagerRegistrationException(Throwable cause) { + super(cause); + } + + protected ManagerRegistrationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/com/falsepattern/chunk/api/package-info.java b/src/main/java/com/falsepattern/chunk/api/package-info.java new file mode 100644 index 0000000..79706b5 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/api/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the classes that you will use to interact with the ChunkAPI library. + */ +package com.falsepattern.chunk.api; \ No newline at end of file diff --git a/src/main/java/com/falsepattern/chunk/internal/ChunkAPI.java b/src/main/java/com/falsepattern/chunk/internal/ChunkAPI.java new file mode 100644 index 0000000..ffce22c --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/ChunkAPI.java @@ -0,0 +1,27 @@ +package com.falsepattern.chunk.internal; + +import lombok.Getter; + +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; + +@Mod(modid = Tags.MODID, + version = Tags.VERSION, + name = Tags.MODNAME, + acceptedMinecraftVersions = "[1.7.10]", + dependencies = "required-after:falsepatternlib@[0.10.15,);") +public class ChunkAPI { + @Getter + private static boolean registrationStage = false; + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) { + registrationStage = true; + } + + @Mod.EventHandler + public void postInit(FMLPostInitializationEvent event) { + registrationStage = false; + } +} \ No newline at end of file diff --git a/src/main/java/com/falsepattern/chunk/internal/ChunkDataRegistryImpl.java b/src/main/java/com/falsepattern/chunk/internal/ChunkDataRegistryImpl.java new file mode 100644 index 0000000..ae7b5b7 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/ChunkDataRegistryImpl.java @@ -0,0 +1,56 @@ +package com.falsepattern.chunk.internal; + +import com.falsepattern.chunk.api.ChunkDataManager; +import com.falsepattern.chunk.api.exception.ManagerRegistrationException; +import lombok.val; +import lombok.var; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class ChunkDataRegistryImpl { + private static final Map managers = new HashMap<>(); + private static final Set disabledManagers = new HashSet<>(); + public static void registerDataManager(ChunkDataManager manager) throws ManagerRegistrationException { + if (!ChunkAPI.isRegistrationStage()) { + throw new ManagerRegistrationException("ChunkDataManager registration is not allowed at this time! " + + "Please register your ChunkDataManager in the init phase of your mod."); + } + var id = manager.id(); + if (id == null) { + throw new ManagerRegistrationException("ChunkDataManager " + manager + " has a null id!"); + } + id = id.intern(); + if (managers.containsKey(id)) { + throw new ManagerRegistrationException("ChunkDataManager " + manager + " has a duplicate id!"); + } + + // If the manager was disabled, do not add it to the list of managers. + if (disabledManagers.contains(id)) { + return; + } + + managers.put(id, manager); + } + + public static void disableDataManager(String id) { + if (!ChunkAPI.isRegistrationStage()) { + throw new ManagerRegistrationException("ChunkDataManager disabling is not allowed at this time! " + + "Please disable any ChunkDataManagers in the init phase of your mod."); + } + if (id == null) { + throw new ManagerRegistrationException("ChunkDataManager id cannot be null!"); + } + id = id.intern(); + Common.LOG.warn("Disabling ChunkDataManager " + id + ". See the stacktrace for the source of this event.", new Throwable()); + //Remove the manager from the list of managers, if it exists + managers.remove(id); + + //Add the manager to the list of disabled managers, in case it gets registered after this disable call. + disabledManagers.add(id); + } +} diff --git a/src/main/java/com/falsepattern/chunk/Common.java b/src/main/java/com/falsepattern/chunk/internal/Common.java similarity index 86% rename from src/main/java/com/falsepattern/chunk/Common.java rename to src/main/java/com/falsepattern/chunk/internal/Common.java index f2152f3..438c088 100644 --- a/src/main/java/com/falsepattern/chunk/Common.java +++ b/src/main/java/com/falsepattern/chunk/internal/Common.java @@ -1,4 +1,4 @@ -package com.falsepattern.chunk; +package com.falsepattern.chunk.internal; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/com/falsepattern/chunk/Tags.java b/src/main/java/com/falsepattern/chunk/internal/Tags.java similarity index 87% rename from src/main/java/com/falsepattern/chunk/Tags.java rename to src/main/java/com/falsepattern/chunk/internal/Tags.java index 46e1f2b..9d6142d 100644 --- a/src/main/java/com/falsepattern/chunk/Tags.java +++ b/src/main/java/com/falsepattern/chunk/internal/Tags.java @@ -1,4 +1,4 @@ -package com.falsepattern.chunk; +package com.falsepattern.chunk.internal; public class Tags { public static final String MODID = "GRADLETOKEN_MODID"; diff --git a/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/ChunkDataMixin.java b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/ChunkDataMixin.java new file mode 100644 index 0000000..be0b6c0 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/ChunkDataMixin.java @@ -0,0 +1,48 @@ +package com.falsepattern.chunk.internal.mixin.mixins.common.vanilla; + +import com.falsepattern.chunk.api.ChunkDataManager; +import com.falsepattern.chunk.api.ModdedChunk; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +import java.util.HashMap; +import java.util.Map; + +/** + * This mixin injects the {@link ModdedChunk} interface into {@link Chunk}, and also creates the data map. + */ +@Mixin(Chunk.class) +public abstract class ChunkDataMixin implements ModdedChunk { + private Map data; + + @Inject(method = "(Lnet/minecraft/world/World;II)V", + at = @At("RETURN")) + private void init(World p_i1995_1_, int p_i1995_2_, int p_i1995_3_, CallbackInfo ci) { + data = new HashMap<>(); + } + + @Override + public T getData(ChunkDataManager manager) { + return (T) data.get(manager.id()); + } + + @Override + public void setData(ChunkDataManager manager, T data) { + this.data.put(manager.id(), data); + } + + @Override + public boolean hasData(ChunkDataManager manager) { + return data.containsKey(manager.id()); + } + + @Override + public T removeData(ChunkDataManager manager) { + return (T) data.remove(manager.id()); + } +} diff --git a/src/main/java/com/falsepattern/chunk/mixin/plugin/Mixin.java b/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/Mixin.java similarity index 96% rename from src/main/java/com/falsepattern/chunk/mixin/plugin/Mixin.java rename to src/main/java/com/falsepattern/chunk/internal/mixin/plugin/Mixin.java index b376a4b..4e38b67 100644 --- a/src/main/java/com/falsepattern/chunk/mixin/plugin/Mixin.java +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/Mixin.java @@ -21,7 +21,7 @@ * along with this program. If not, see . */ -package com.falsepattern.chunk.mixin.plugin; +package com.falsepattern.chunk.internal.mixin.plugin; import com.falsepattern.lib.mixin.IMixin; import com.falsepattern.lib.mixin.ITargetedMod; diff --git a/src/main/java/com/falsepattern/chunk/mixin/plugin/MixinPlugin.java b/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/MixinPlugin.java similarity index 93% rename from src/main/java/com/falsepattern/chunk/mixin/plugin/MixinPlugin.java rename to src/main/java/com/falsepattern/chunk/internal/mixin/plugin/MixinPlugin.java index 32edb43..94ac04a 100644 --- a/src/main/java/com/falsepattern/chunk/mixin/plugin/MixinPlugin.java +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/MixinPlugin.java @@ -21,9 +21,9 @@ * along with this program. If not, see . */ -package com.falsepattern.chunk.mixin.plugin; +package com.falsepattern.chunk.internal.mixin.plugin; -import com.falsepattern.chunk.Tags; +import com.falsepattern.chunk.internal.Tags; import com.falsepattern.lib.mixin.IMixin; import com.falsepattern.lib.mixin.IMixinPlugin; import com.falsepattern.lib.mixin.ITargetedMod; diff --git a/src/main/java/com/falsepattern/chunk/mixin/plugin/TargetedMod.java b/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/TargetedMod.java similarity index 96% rename from src/main/java/com/falsepattern/chunk/mixin/plugin/TargetedMod.java rename to src/main/java/com/falsepattern/chunk/internal/mixin/plugin/TargetedMod.java index 2ba3f0a..3bfa5a9 100644 --- a/src/main/java/com/falsepattern/chunk/mixin/plugin/TargetedMod.java +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/TargetedMod.java @@ -21,7 +21,7 @@ * along with this program. If not, see . */ -package com.falsepattern.chunk.mixin.plugin; +package com.falsepattern.chunk.internal.mixin.plugin; import com.falsepattern.lib.mixin.ITargetedMod; import lombok.Getter; diff --git a/src/main/java/com/falsepattern/chunk/internal/package-info.java b/src/main/java/com/falsepattern/chunk/internal/package-info.java new file mode 100644 index 0000000..e338d37 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the internal classes of the ChunkAPI library. Do not use these classes directly. + */ +package com.falsepattern.chunk.internal; \ No newline at end of file diff --git a/src/main/java/com/falsepattern/chunk/internal/stubpackage/net/minecraft/world/chunk/Chunk.java b/src/main/java/com/falsepattern/chunk/internal/stubpackage/net/minecraft/world/chunk/Chunk.java new file mode 100644 index 0000000..45b5d5d --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/stubpackage/net/minecraft/world/chunk/Chunk.java @@ -0,0 +1,12 @@ +package com.falsepattern.chunk.internal.stubpackage.net.minecraft.world.chunk; + +import com.falsepattern.chunk.api.ModdedChunk; + +import net.minecraft.world.World; + +//Internal stub class, do not use +public abstract class Chunk extends net.minecraft.world.chunk.Chunk implements ModdedChunk { + private Chunk(World p_i1995_1_, int p_i1995_2_, int p_i1995_3_) { + super(p_i1995_1_, p_i1995_2_, p_i1995_3_); + } +} diff --git a/src/main/resources/mixins.fplib_chunkapi.json b/src/main/resources/mixins.fplib_chunkapi.json index f05b1b9..f139ea1 100644 --- a/src/main/resources/mixins.fplib_chunkapi.json +++ b/src/main/resources/mixins.fplib_chunkapi.json @@ -1,8 +1,8 @@ { "required": true, "minVersion": "0.8.5", - "package": "com.falsepattern.chunk.mixin.mixins", - "plugin": "com.falsepattern.chunk.mixin.plugin.MixinPlugin", + "package": "com.falsepattern.chunk.internal.mixin.mixins", + "plugin": "com.falsepattern.chunk.internal.mixin.plugin.MixinPlugin", "refmap": "mixins.fplib_chunkapi.refmap.json", "target": "@env(DEFAULT)", "compatibilityLevel": "JAVA_8"