From d8914434fa61a9f6a5aeef32c871cfe26e9de326 Mon Sep 17 00:00:00 2001 From: florensie Date: Sun, 19 Jul 2020 21:09:20 +0200 Subject: [PATCH 01/73] Add access widener for SpawnRestriction.register (#135) --- patchwork-registries/build.gradle | 4 ++++ patchwork-registries/src/main/resources/fabric.mod.json | 1 + .../src/main/resources/patchwork-registries.accesswidener | 3 +++ 3 files changed, 8 insertions(+) create mode 100644 patchwork-registries/src/main/resources/patchwork-registries.accesswidener diff --git a/patchwork-registries/build.gradle b/patchwork-registries/build.gradle index 2d6ea957..63ae5d33 100644 --- a/patchwork-registries/build.gradle +++ b/patchwork-registries/build.gradle @@ -4,3 +4,7 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { compile project(path: ':patchwork-fml', configuration: 'dev') } + +minecraft { + accessWidener "src/main/resources/patchwork-registries.accesswidener" +} diff --git a/patchwork-registries/src/main/resources/fabric.mod.json b/patchwork-registries/src/main/resources/fabric.mod.json index 0f861440..1715ad9d 100644 --- a/patchwork-registries/src/main/resources/fabric.mod.json +++ b/patchwork-registries/src/main/resources/fabric.mod.json @@ -20,6 +20,7 @@ "mixins": [ "patchwork-registries.mixins.json" ], + "accessWidener": "patchwork-registries.accesswidener", "custom": { "modmenu:api": true, "modmenu:parent": "patchwork" diff --git a/patchwork-registries/src/main/resources/patchwork-registries.accesswidener b/patchwork-registries/src/main/resources/patchwork-registries.accesswidener new file mode 100644 index 00000000..91b7b260 --- /dev/null +++ b/patchwork-registries/src/main/resources/patchwork-registries.accesswidener @@ -0,0 +1,3 @@ +accessWidener v1 named + +accessible method net/minecraft/entity/SpawnRestriction register (Lnet/minecraft/entity/EntityType;Lnet/minecraft/entity/SpawnRestriction$Location;Lnet/minecraft/world/Heightmap$Type;Lnet/minecraft/entity/SpawnRestriction$class_4306;)V From 3f504ca2a6facab68b6d72a955f7a952d8a78083 Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Sun, 19 Jul 2020 15:11:17 -0400 Subject: [PATCH 02/73] ItemTooltipEvent (#108) * ItemTooltipEvent * Commiting before you push is helpful * Remove useless import --- .../event/entity/player/ItemTooltipEvent.java | 79 +++++++++++++++++++ .../impl/event/entity/EntityEvents.java | 9 +++ .../mixin/event/entity/MixinItemStack.java | 42 ++++++++++ .../patchwork-events-entity.mixins.json | 1 + 4 files changed, 131 insertions(+) create mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/ItemTooltipEvent.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemStack.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/ItemTooltipEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/ItemTooltipEvent.java new file mode 100644 index 00000000..bac5a6c4 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/ItemTooltipEvent.java @@ -0,0 +1,79 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.player; + +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.client.item.TooltipContext; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +public class ItemTooltipEvent extends PlayerEvent { + private final TooltipContext flags; + @Nonnull + private final ItemStack itemStack; + private final List toolTip; + + /** + * This event is fired in {@link ItemStack#getTooltip(PlayerEntity, TooltipContext)}, which in turn is called from it's respective {@link net.minecraft.client.gui.screen.ingame.ContainerScreen}. + * Tooltips are also gathered with a null entityPlayer during startup by {@link net.minecraft.client.MinecraftClient#initializeSearchableContainers()}. + */ + public ItemTooltipEvent(@Nonnull ItemStack itemStack, @Nullable PlayerEntity entityPlayer, List list, TooltipContext flags) { + super(entityPlayer); + this.itemStack = itemStack; + this.toolTip = list; + this.flags = flags; + } + + /** + * Use to determine if the advanced information on item tooltips is being shown, toggled by F3+H. + */ + public TooltipContext getFlags() { + return flags; + } + + /** + * The {@link ItemStack} with the tooltip. + */ + @Nonnull + public ItemStack getItemStack() { + return itemStack; + } + + /** + * The {@link ItemStack} tooltip. + */ + public List getToolTip() { + return toolTip; + } + + /** + * This event is fired with a null player during startup when populating search trees for tooltips. + */ + @Override + @Nullable + public PlayerEntity getPlayer() { + return super.getPlayer(); + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index 3c753fd4..9355e90f 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -19,6 +19,8 @@ package net.patchworkmc.impl.event.entity; +import java.util.List; + import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.extensions.IForgeItem; import net.minecraftforge.event.entity.EntityEvent; @@ -32,6 +34,7 @@ import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; import net.minecraftforge.event.entity.living.LivingSpawnEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerFlyableFallEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; @@ -40,6 +43,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityPose; @@ -50,6 +54,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.world.IWorld; @@ -181,6 +186,10 @@ public static boolean attackEntity(PlayerEntity player, Entity target) { return !item.onLeftClickEntity(stack, player, target); } + public static void onItemTooltip(ItemStack itemStack, PlayerEntity entityPlayer, List list, TooltipContext flags) { + MinecraftForge.EVENT_BUS.post(new ItemTooltipEvent(itemStack, entityPlayer, list, flags)); + } + @Override public void onInitialize() { UseItemCallback.EVENT.register((player, world, hand) -> { diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemStack.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemStack.java new file mode 100644 index 00000000..6389a5de --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemStack.java @@ -0,0 +1,42 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.client.item.TooltipContext; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(ItemStack.class) +public class MixinItemStack { + @Inject(method = "getTooltip", at = @At("RETURN")) + private void onGetTooltip(PlayerEntity player, TooltipContext context, CallbackInfoReturnable> cir) { + EntityEvents.onItemTooltip((ItemStack) (Object) this, player, cir.getReturnValue(), context); + } +} diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 7b7c0180..081b587e 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -20,6 +20,7 @@ "client": [ "MixinClientWorld", "MixinClientPlayerEntity", + "MixinItemStack", "MixinOtherClientPlayerEntity" ], "injectors": { From 90ba4b0ec76509e1612ebc89e4b6087fbf70aeb6 Mon Sep 17 00:00:00 2001 From: Kitlith Date: Sun, 19 Jul 2020 13:52:36 -0700 Subject: [PATCH 03/73] Implement ForgeEventFactory.gatherCapabilities (#129) * Move implementation of gatherCapabilities to CapabilityEvents * Dispatch ForgeEventFactory.gatherCapabilities to CapabilityEvents * Remove restriction on ForgeEventFactory --- .../capabilities/CapabilityProvider.java | 13 ++---- .../capability/BaseCapabilityProvider.java | 12 +----- .../impl/capability/CapabilityEvents.java | 43 +++++++++++++++++++ patchwork-god-classes/build.gradle | 1 + .../event/ForgeEventFactory.java | 16 +++++++ .../src/main/resources/fabric.mod.json | 1 + 6 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/CapabilityEvents.java diff --git a/patchwork-capabilities/src/main/java/net/minecraftforge/common/capabilities/CapabilityProvider.java b/patchwork-capabilities/src/main/java/net/minecraftforge/common/capabilities/CapabilityProvider.java index a2d23d43..3215229d 100644 --- a/patchwork-capabilities/src/main/java/net/minecraftforge/common/capabilities/CapabilityProvider.java +++ b/patchwork-capabilities/src/main/java/net/minecraftforge/common/capabilities/CapabilityProvider.java @@ -23,13 +23,13 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.math.Direction; +import net.patchworkmc.impl.capability.CapabilityEvents; + @ParametersAreNonnullByDefault public abstract class CapabilityProvider implements ICapabilityProvider { protected final Class baseClass; @@ -45,14 +45,7 @@ public final void gatherCapabilities() { } public void gatherCapabilities(@Nullable ICapabilityProvider parent) { - AttachCapabilitiesEvent event = new AttachCapabilitiesEvent<>(baseClass, (B) this); - MinecraftForge.EVENT_BUS.post(event); - - if (!event.getCapabilities().isEmpty() || parent != null) { - capabilities = new CapabilityDispatcher(event.getCapabilities(), event.getListeners(), parent); - } else { - capabilities = null; - } + capabilities = CapabilityEvents.gatherCapabilities(baseClass, this, parent); } public final @Nullable CapabilityDispatcher getCapabilities() { diff --git a/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/BaseCapabilityProvider.java b/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/BaseCapabilityProvider.java index 31a3d2c1..1b682810 100644 --- a/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/BaseCapabilityProvider.java +++ b/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/BaseCapabilityProvider.java @@ -21,11 +21,8 @@ import javax.annotation.Nullable; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.capabilities.CapabilityDispatcher; import net.minecraftforge.common.capabilities.CapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.event.AttachCapabilitiesEvent; public class BaseCapabilityProvider extends CapabilityProvider { private final T provider; @@ -37,13 +34,6 @@ public BaseCapabilityProvider(Class baseClass, T provider) { @Override public void gatherCapabilities(@Nullable ICapabilityProvider parent) { - AttachCapabilitiesEvent event = new AttachCapabilitiesEvent<>(baseClass, provider); - MinecraftForge.EVENT_BUS.post(event); - - if (!event.getCapabilities().isEmpty() || parent != null) { - capabilities = new CapabilityDispatcher(event.getCapabilities(), event.getListeners(), parent); - } else { - capabilities = null; - } + capabilities = CapabilityEvents.gatherCapabilities(baseClass, provider, parent); } } diff --git a/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/CapabilityEvents.java b/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/CapabilityEvents.java new file mode 100644 index 00000000..42794d67 --- /dev/null +++ b/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/CapabilityEvents.java @@ -0,0 +1,43 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.capability; + +import javax.annotation.Nullable; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.CapabilityDispatcher; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.event.AttachCapabilitiesEvent; + +public class CapabilityEvents { + // This is less restrictive than Forge's implementation, since patchwork can't make vanilla extend stuff at random. + @SuppressWarnings("unchecked") + @Nullable + public static CapabilityDispatcher gatherCapabilities(Class type, T provider, @Nullable ICapabilityProvider parent) { + AttachCapabilitiesEvent event = new AttachCapabilitiesEvent((Class) type, provider); + MinecraftForge.EVENT_BUS.post(event); + + if (!event.getCapabilities().isEmpty() || parent != null) { + return new CapabilityDispatcher(event.getCapabilities(), event.getListeners(), parent); + } else { + return null; + } + } +} diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 6768d533..445a1e9b 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -3,5 +3,6 @@ version = getSubprojectVersion(project, "0.1.0") dependencies { compile project(path: ':patchwork-fml', configuration: 'dev') + compile project(path: ':patchwork-capabilities', configuration: 'dev') compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index f9e54a66..9d526437 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -19,9 +19,25 @@ package net.minecraftforge.event; +import javax.annotation.Nullable; + +import net.minecraftforge.common.capabilities.CapabilityDispatcher; +import net.minecraftforge.common.capabilities.ICapabilityProvider; + +import net.patchworkmc.impl.capability.CapabilityEvents; + /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. * Do not keep implementation details here, methods should be thin wrappers around methods in other modules. */ public class ForgeEventFactory { + @Nullable + public static CapabilityDispatcher gatherCapabilities(Class type, T provider) { + return gatherCapabilities(type, provider, null); + } + + @Nullable + public static CapabilityDispatcher gatherCapabilities(Class type, T provider, @Nullable ICapabilityProvider parent) { + return CapabilityEvents.gatherCapabilities(type, provider, parent); + } } diff --git a/patchwork-god-classes/src/main/resources/fabric.mod.json b/patchwork-god-classes/src/main/resources/fabric.mod.json index 7c0f2121..102bb0d7 100644 --- a/patchwork-god-classes/src/main/resources/fabric.mod.json +++ b/patchwork-god-classes/src/main/resources/fabric.mod.json @@ -17,6 +17,7 @@ "depends": { "fabricloader": ">=0.8.4", "patchwork-fml": "*", + "patchwork-capabilities": "*", "patchwork-events-lifecycle": "*" }, "custom": { From a2c372e9c7981b07610731bdbfddb5f6e8eb8db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Wed, 22 Jul 2020 09:12:41 +1000 Subject: [PATCH 04/73] Impl ModelBakeEvent, ModelRegistryEvent and some ModelLoader methods (#106) * Impl ModelBakeEvent, ModelRegistryEvent and some ModelLoader methods * Apply suggestions from code review Co-authored-by: Glitch * Rename AbstractModelLoader to SpecialModelProvider * Simplify MixinModelLoader * Add comments * Apply suggestions from code review Co-authored-by: famous1622 <8428080+famous1622@users.noreply.github.com> * Update ModelEventDispatcher.java * Better mixin target Co-authored-by: Glitch Co-authored-by: famous1622 <8428080+famous1622@users.noreply.github.com> --- patchwork-dispatcher/build.gradle | 1 + .../java/net/patchworkmc/impl/Patchwork.java | 2 + patchwork-model-loader/build.gradle | 6 + .../client/event/ModelBakeEvent.java | 59 ++++++++++ .../client/event/ModelRegistryEvent.java | 29 +++++ .../client/model/ModelLoader.java | 109 ++++++++++++++++++ .../modelloader/ModelEventDispatcher.java | 47 ++++++++ .../impl/modelloader/Signatures.java | 34 ++++++ .../modelloader/SpecialModelProvider.java | 30 +++++ .../modelloader/MixinBakedModelManager.java | 59 ++++++++++ .../mixin/modelloader/MixinModelLoader.java | 89 ++++++++++++++ .../assets/patchwork-model-loader/icon.png | Bin 0 -> 22738 bytes .../src/main/resources/fabric.mod.json | 27 +++++ .../patchwork-model-loader.mixins.json | 12 ++ settings.gradle | 1 + 15 files changed, 505 insertions(+) create mode 100644 patchwork-model-loader/build.gradle create mode 100644 patchwork-model-loader/src/main/java/net/minecraftforge/client/event/ModelBakeEvent.java create mode 100644 patchwork-model-loader/src/main/java/net/minecraftforge/client/event/ModelRegistryEvent.java create mode 100644 patchwork-model-loader/src/main/java/net/minecraftforge/client/model/ModelLoader.java create mode 100644 patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/ModelEventDispatcher.java create mode 100644 patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/Signatures.java create mode 100644 patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/SpecialModelProvider.java create mode 100644 patchwork-model-loader/src/main/java/net/patchworkmc/mixin/modelloader/MixinBakedModelManager.java create mode 100644 patchwork-model-loader/src/main/java/net/patchworkmc/mixin/modelloader/MixinModelLoader.java create mode 100644 patchwork-model-loader/src/main/resources/assets/patchwork-model-loader/icon.png create mode 100644 patchwork-model-loader/src/main/resources/fabric.mod.json create mode 100644 patchwork-model-loader/src/main/resources/patchwork-model-loader.mixins.json diff --git a/patchwork-dispatcher/build.gradle b/patchwork-dispatcher/build.gradle index 3efbace5..6f243688 100644 --- a/patchwork-dispatcher/build.gradle +++ b/patchwork-dispatcher/build.gradle @@ -6,4 +6,5 @@ dependencies { compile project(path: ':patchwork-registries', configuration: 'dev') compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') compile project(path: ':patchwork-events-rendering', configuration: 'dev') + compile project(path: ':patchwork-model-loader', configuration: 'dev') } diff --git a/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java b/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java index 6a0d999b..59b74ed9 100644 --- a/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java +++ b/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java @@ -54,6 +54,7 @@ import net.patchworkmc.api.ForgeInitializer; import net.patchworkmc.impl.event.lifecycle.LifecycleEvents; import net.patchworkmc.impl.event.render.RenderEvents; +import net.patchworkmc.impl.modelloader.ModelEventDispatcher; import net.patchworkmc.impl.registries.RegistryEventDispatcher; public class Patchwork implements ModInitializer { @@ -127,6 +128,7 @@ public void onInitialize() { dispatch(mods, FMLCommonSetupEvent::new); DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + ModelEventDispatcher.fireModelRegistryEvent(); dispatch(mods, container -> new FMLClientSetupEvent(MinecraftClient::getInstance, container)); RenderEvents.registerEventDispatcher(event -> dispatch(mods, event)); }); diff --git a/patchwork-model-loader/build.gradle b/patchwork-model-loader/build.gradle new file mode 100644 index 00000000..0baf9131 --- /dev/null +++ b/patchwork-model-loader/build.gradle @@ -0,0 +1,6 @@ +archivesBaseName = "patchwork-model-loader" +version = getSubprojectVersion(project, "0.1.0") + +dependencies { + compile project(path: ':patchwork-fml', configuration: 'dev') +} diff --git a/patchwork-model-loader/src/main/java/net/minecraftforge/client/event/ModelBakeEvent.java b/patchwork-model-loader/src/main/java/net/minecraftforge/client/event/ModelBakeEvent.java new file mode 100644 index 00000000..18ac9787 --- /dev/null +++ b/patchwork-model-loader/src/main/java/net/minecraftforge/client/event/ModelBakeEvent.java @@ -0,0 +1,59 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.event; + +import java.util.Map; + +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.eventbus.api.Event; + +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BakedModelManager; +import net.minecraft.util.Identifier; + +/** + * Fired when the BakedModelManager is notified of the resource manager reloading. + * Called after model registry is setup, but before it's passed to + * BlockModelShapes. + */ +public class ModelBakeEvent extends Event { + private final BakedModelManager modelManager; + private final Map modelRegistry; + private final ModelLoader modelLoader; + + public ModelBakeEvent(BakedModelManager modelManager, Map modelRegistry, + ModelLoader modelLoader) { + this.modelManager = modelManager; + this.modelRegistry = modelRegistry; + this.modelLoader = modelLoader; + } + + public BakedModelManager getModelManager() { + return modelManager; + } + + public Map getModelRegistry() { + return modelRegistry; + } + + public ModelLoader getModelLoader() { + return modelLoader; + } +} diff --git a/patchwork-model-loader/src/main/java/net/minecraftforge/client/event/ModelRegistryEvent.java b/patchwork-model-loader/src/main/java/net/minecraftforge/client/event/ModelRegistryEvent.java new file mode 100644 index 00000000..d31900d6 --- /dev/null +++ b/patchwork-model-loader/src/main/java/net/minecraftforge/client/event/ModelRegistryEvent.java @@ -0,0 +1,29 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.event; + +import net.minecraftforge.eventbus.api.Event; + +/** + * Fired when the {@link net.minecraftforge.client.model.ModelLoader} is ready + * to receive registrations. + */ +public class ModelRegistryEvent extends Event { +} diff --git a/patchwork-model-loader/src/main/java/net/minecraftforge/client/model/ModelLoader.java b/patchwork-model-loader/src/main/java/net/minecraftforge/client/model/ModelLoader.java new file mode 100644 index 00000000..54dcafca --- /dev/null +++ b/patchwork-model-loader/src/main/java/net/minecraftforge/client/model/ModelLoader.java @@ -0,0 +1,109 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.model; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.MarkerManager; + +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.util.profiler.Profiler; + +import net.patchworkmc.impl.modelloader.SpecialModelProvider; + +public class ModelLoader extends net.minecraft.client.render.model.ModelLoader implements SpecialModelProvider { + private static final Marker MODELLOADING = MarkerManager.getMarker("MODELLOADING"); + private static Set specialModels = new HashSet<>(); + private static final Logger LOGGER = LogManager.getLogger(); + private final Map loadingExceptions = new HashMap<>(); + private boolean isLoading = false; + private static ModelLoader instance; + + @Nullable + public static ModelLoader instance() { + return instance; + } + + public boolean isLoading() { + return isLoading; + } + + public ModelLoader(ResourceManager resourceManager, SpriteAtlasTexture spriteAtlas, BlockColors blockColors, + Profiler profiler) { + super(resourceManager, spriteAtlas, blockColors, profiler); + } + + /** + * Indicate to vanilla that it should load and bake the given model, even if no + * blocks or items use it. This is useful if e.g. you have baked models only for + * entity renderers. Call during + * {@link net.minecraftforge.client.event.ModelRegistryEvent} + * + * @param rl The model, either {@link ModelResourceLocation} to point to a + * blockstate variant, or plain {@link ResourceLocation} to point + * directly to a json in the models folder. + */ + public static void addSpecialModel(Identifier rl) { + specialModels.add(rl); + } + + @Override + public Set getSpecialModels() { + return specialModels; + } + + /** + * Internal, do not use. + */ + public void onPostBakeEvent(Map modelRegistry) { + BakedModel missingModel = modelRegistry.get(MISSING); + + for (Map.Entry entry : loadingExceptions.entrySet()) { + // ignoring pure Identifier arguments, all things we care about pass + // ModelIdentifier + if (entry.getKey() instanceof ModelIdentifier) { + LOGGER.debug(MODELLOADING, "Model {} failed to load: {}", entry.getKey().toString(), + entry.getValue().getLocalizedMessage()); + final ModelIdentifier location = (ModelIdentifier) entry.getKey(); + final BakedModel model = modelRegistry.get(location); + + if (model == null) { + modelRegistry.put(location, missingModel); + } + } + } + + loadingExceptions.clear(); + isLoading = false; + } +} diff --git a/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/ModelEventDispatcher.java b/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/ModelEventDispatcher.java new file mode 100644 index 00000000..1924e55c --- /dev/null +++ b/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/ModelEventDispatcher.java @@ -0,0 +1,47 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.modelloader; + +import java.util.Map; + +import net.minecraftforge.client.event.ModelBakeEvent; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.fml.ModLoader; + +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BakedModelManager; +import net.minecraft.util.Identifier; + +public class ModelEventDispatcher { + /** + * In Forge, ModelRegistryEvent is fired in parallel with FMLClientSetupEvent. + * Here we fire ModelRegistryEvent before FMLClientSetupEvent. + * The official forge does not set the ModLoadingContext here, so this should be fine. + */ + public static void fireModelRegistryEvent() { + ModLoader.get().postEvent(new ModelRegistryEvent()); + } + + public static void onModelBake(BakedModelManager modelManager, Map modelRegistry, ModelLoader modelLoader) { + ModLoader.get().postEvent(new ModelBakeEvent(modelManager, modelRegistry, modelLoader)); + modelLoader.onPostBakeEvent(modelRegistry); + } +} diff --git a/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/Signatures.java b/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/Signatures.java new file mode 100644 index 00000000..735b2b3a --- /dev/null +++ b/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/Signatures.java @@ -0,0 +1,34 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.modelloader; + +public class Signatures { + public static final String Profiler_swap = "net/minecraft/util/profiler/Profiler.swap(Ljava/lang/String;)V"; + + public static final String ModelLoader_new = "(" + + "Lnet/minecraft/resource/ResourceManager;" + + "Lnet/minecraft/client/texture/SpriteAtlasTexture;" + + "Lnet/minecraft/client/color/block/BlockColors;" + + "Lnet/minecraft/util/profiler/Profiler;" + + ")" + + "Lnet/minecraft/client/render/model/ModelLoader;"; + + public static final String ModelLoader_addModel = "net/minecraft/client/render/model/ModelLoader.addModel(Lnet/minecraft/client/util/ModelIdentifier;)V"; +} diff --git a/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/SpecialModelProvider.java b/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/SpecialModelProvider.java new file mode 100644 index 00000000..e39b5a46 --- /dev/null +++ b/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/SpecialModelProvider.java @@ -0,0 +1,30 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.modelloader; + +import java.util.Set; + +import net.minecraft.util.Identifier; + +public interface SpecialModelProvider { + default Set getSpecialModels() { + return java.util.Collections.emptySet(); + } +} diff --git a/patchwork-model-loader/src/main/java/net/patchworkmc/mixin/modelloader/MixinBakedModelManager.java b/patchwork-model-loader/src/main/java/net/patchworkmc/mixin/modelloader/MixinBakedModelManager.java new file mode 100644 index 00000000..e2169543 --- /dev/null +++ b/patchwork-model-loader/src/main/java/net/patchworkmc/mixin/modelloader/MixinBakedModelManager.java @@ -0,0 +1,59 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.modelloader; + +import java.util.Map; + +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.Redirect; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BakedModelManager; +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.util.profiler.Profiler; + +import net.patchworkmc.impl.modelloader.ModelEventDispatcher; +import net.patchworkmc.impl.modelloader.Signatures; + +@Mixin(BakedModelManager.class) +public abstract class MixinBakedModelManager { + @Shadow + private Map models; + + @Redirect(method = "prepare", at = @At(value = "NEW", target = Signatures.ModelLoader_new, ordinal = 0)) + private ModelLoader patchwork_prepare_new_ModelLoader(ResourceManager resourceManager, SpriteAtlasTexture spriteAtlas, BlockColors blockColors, Profiler profiler) { + return new net.minecraftforge.client.model.ModelLoader(resourceManager, spriteAtlas, blockColors, profiler); + } + + @Inject(method = "apply", at = @At(shift = Shift.BEFORE, value = "INVOKE", target = Signatures.Profiler_swap, ordinal = 0)) + protected void patchwork_apply_swap(ModelLoader modelLoader, ResourceManager resourceManager, Profiler profiler, CallbackInfo ci) { + BakedModelManager me = (BakedModelManager) (Object) this; + ModelEventDispatcher.onModelBake(me, models, (net.minecraftforge.client.model.ModelLoader) modelLoader); + } +} diff --git a/patchwork-model-loader/src/main/java/net/patchworkmc/mixin/modelloader/MixinModelLoader.java b/patchwork-model-loader/src/main/java/net/patchworkmc/mixin/modelloader/MixinModelLoader.java new file mode 100644 index 00000000..fc082222 --- /dev/null +++ b/patchwork-model-loader/src/main/java/net/patchworkmc/mixin/modelloader/MixinModelLoader.java @@ -0,0 +1,89 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.modelloader; + +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; + +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.render.model.UnbakedModel; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.util.Identifier; + +import net.patchworkmc.impl.modelloader.Signatures; +import net.patchworkmc.impl.modelloader.SpecialModelProvider; + +@Mixin(ModelLoader.class) +public abstract class MixinModelLoader implements SpecialModelProvider { + @Unique + private static final ModelIdentifier TRIDENT_INV = new ModelIdentifier("minecraft:trident_in_hand#inventory"); + @Unique + private static final Logger LOGGER = LogManager.getLogger(ModelLoader.class); + + @Shadow + @Final + private Map modelsToBake; + + @Shadow + @Final + private Map unbakedModels; + + @Unique + private void patchwork$loadSpecialModel() { + for (Identifier id : getSpecialModels()) { + ModelLoader me = (ModelLoader) (Object) this; + UnbakedModel iunbakedmodel = me.getOrLoadModel(id); + this.unbakedModels.put(id, iunbakedmodel); + this.modelsToBake.put(id, iunbakedmodel); + } + } + + @Shadow + private void addModel(ModelIdentifier modelId) { } + + /** + * Due to the limitations of mixin, when targeting a constructor, we cannot use injection points other than "TAIL". + * There are multiple occurrences of addModel in the constructor, Forge inserts the patch after adding model for the trident. + * Here we just do another check to ensure that the injection point is correct. + * @param me + * @param modelId + */ + @Redirect(slice = @Slice(from = @At(value = "INVOKE_STRING", target = Signatures.Profiler_swap, args = "ldc=special")), + method = "", at = @At(value = "INVOKE", target = Signatures.ModelLoader_addModel, ordinal = 0)) + private void patchwork_addModel_return(ModelLoader me, ModelIdentifier modelId) { + addModel(modelId); + + if (modelId.equals(TRIDENT_INV)) { + LOGGER.debug("Patchwork is loading special models for Forge mods"); + patchwork$loadSpecialModel(); + } else { + LOGGER.warn("Patchwork was unable to load special models for Forge mods"); + } + } +} diff --git a/patchwork-model-loader/src/main/resources/assets/patchwork-model-loader/icon.png b/patchwork-model-loader/src/main/resources/assets/patchwork-model-loader/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-model-loader/src/main/resources/fabric.mod.json b/patchwork-model-loader/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..33b4c93d --- /dev/null +++ b/patchwork-model-loader/src/main/resources/fabric.mod.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "id": "patchwork-model-loader", + "name": "Patchwork Model Loader", + "version": "${version}", + "license": "LGPL-2.1-only", + "icon": "assets/patchwork-model-loader/icon.png", + "contact": { + "issues": "https://github.com/PatchworkMC/patchwork-api/issues", + "sources": "https://github.com/PatchworkMC/patchwork-api" + }, + "authors": [ + "PatchworkMC" + ], + "depends": { + "fabricloader": ">=0.8.4", + "patchwork-fml": "*" + }, + "mixins": [ + "patchwork-model-loader.mixins.json" + ], + "description": "Implementation of the Forge Model Loader.", + "custom": { + "modmenu:api": true, + "modmenu:parent": "patchwork" + } +} diff --git a/patchwork-model-loader/src/main/resources/patchwork-model-loader.mixins.json b/patchwork-model-loader/src/main/resources/patchwork-model-loader.mixins.json new file mode 100644 index 00000000..9bd996d7 --- /dev/null +++ b/patchwork-model-loader/src/main/resources/patchwork-model-loader.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.modelloader", + "compatibilityLevel": "JAVA_8", + "client": [ + "MixinBakedModelManager", + "MixinModelLoader" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/settings.gradle b/settings.gradle index 444b4685..56e3d173 100644 --- a/settings.gradle +++ b/settings.gradle @@ -31,6 +31,7 @@ include 'patchwork-god-classes' include 'patchwork-gui' include 'patchwork-level-generators' include 'patchwork-loot' +include 'patchwork-model-loader' include 'patchwork-networking' include 'patchwork-networking-messages' include 'patchwork-recipes' From 56953c04c7a428f4f778c79d0ebe638041755fa5 Mon Sep 17 00:00:00 2001 From: Kitlith Date: Tue, 21 Jul 2020 16:14:41 -0700 Subject: [PATCH 05/73] Dispatch from ForgeHooksClient to RenderEvents (#132) --- patchwork-god-classes/build.gradle | 1 + .../client/ForgeHooksClient.java | 24 +++++++++++++++++++ .../src/main/resources/fabric.mod.json | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 445a1e9b..914132e0 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -5,4 +5,5 @@ dependencies { compile project(path: ':patchwork-fml', configuration: 'dev') compile project(path: ':patchwork-capabilities', configuration: 'dev') compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') + compile project(path: ':patchwork-events-rendering', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index ef6b02e5..9a369e8e 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -19,9 +19,33 @@ package net.minecraftforge.client; +import java.util.Set; + +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.color.item.ItemColors; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.util.Identifier; + +import net.patchworkmc.impl.event.render.RenderEvents; + /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. * Do not keep implementation details here, methods should be thin wrappers around methods in other modules. */ public class ForgeHooksClient { + public static void onBlockColorsInit(BlockColors blockColors) { + RenderEvents.onBlockColorsInit(blockColors); + } + + public static void onItemColorsInit(ItemColors itemColors, BlockColors blockColors) { + RenderEvents.onItemColorsInit(itemColors, blockColors); + } + + public static void onTextureStitchedPre(SpriteAtlasTexture map, Set resourceLocations) { + RenderEvents.onTextureStitchPre(map, resourceLocations); + } + + public static void onTextureStitchedPost(SpriteAtlasTexture map) { + RenderEvents.onTextureStitchPost(map); + } } diff --git a/patchwork-god-classes/src/main/resources/fabric.mod.json b/patchwork-god-classes/src/main/resources/fabric.mod.json index 102bb0d7..07c35810 100644 --- a/patchwork-god-classes/src/main/resources/fabric.mod.json +++ b/patchwork-god-classes/src/main/resources/fabric.mod.json @@ -18,7 +18,8 @@ "fabricloader": ">=0.8.4", "patchwork-fml": "*", "patchwork-capabilities": "*", - "patchwork-events-lifecycle": "*" + "patchwork-events-lifecycle": "*", + "patchwork-events-rendering": "*" }, "custom": { "modmenu:api": true, From 7be7f5f6491ee412e8b5cb6e605dab28546d8733 Mon Sep 17 00:00:00 2001 From: Kitlith Date: Tue, 21 Jul 2020 16:15:45 -0700 Subject: [PATCH 06/73] Dispatch to EntityEvents from ForgeHooks, etc. (#134) * Move onLivingDrops to EntityEvents * Dispatch from patchwork-god-classes to EntityEvents --- .../impl/event/entity/EntityEvents.java | 10 ++- .../mixin/event/entity/MixinLivingEntity.java | 4 +- patchwork-god-classes/build.gradle | 1 + .../net/minecraftforge/common/ForgeHooks.java | 74 +++++++++++++++++++ .../event/ForgeEventFactory.java | 25 +++++++ .../fml/hooks/BasicEventHooks.java | 5 ++ 6 files changed, 114 insertions(+), 5 deletions(-) diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index 9355e90f..73cf8679 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -20,6 +20,7 @@ package net.patchworkmc.impl.event.entity; import java.util.List; +import java.util.Collection; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.extensions.IForgeItem; @@ -28,6 +29,7 @@ import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingDamageEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingDropsEvent; import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; @@ -47,13 +49,13 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityPose; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnType; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -97,7 +99,7 @@ public static void onEnteringChunk(Entity entity, int newChunkX, int newChunkZ, } // PlayerEvents - public static void onPlayerLoggedIn(ServerPlayerEntity playerEntity) { + public static void onPlayerLoggedIn(PlayerEntity playerEntity) { MinecraftForge.EVENT_BUS.post(new PlayerEvent.PlayerLoggedInEvent(playerEntity)); } @@ -128,6 +130,10 @@ public static float onLivingDamage(LivingEntity entity, DamageSource src, float return MinecraftForge.EVENT_BUS.post(event) ? 0 : event.getAmount(); } + public static boolean onLivingDrops(LivingEntity entity, DamageSource source, Collection drops, int lootingLevel, boolean recentlyHit) { + return MinecraftForge.EVENT_BUS.post(new LivingDropsEvent(entity, source, drops, lootingLevel, recentlyHit)); + } + public static float getEyeHeight(Entity entity, EntityPose pose, EntityDimensions size, float defaultHeight) { EntityEvent.EyeHeight event = new EntityEvent.EyeHeight(entity, pose, size, defaultHeight); MinecraftForge.EVENT_BUS.post(event); diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLivingEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLivingEntity.java index 21fe772a..d7e2f0d1 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLivingEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLivingEntity.java @@ -22,9 +22,7 @@ import java.util.ArrayList; import java.util.Collection; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.extensions.IForgeEntity; -import net.minecraftforge.event.entity.living.LivingDropsEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -154,7 +152,7 @@ private void hookDropForDropsEvent(DamageSource src, CallbackInfo info) { IForgeEntity forgeEntity = (IForgeEntity) this; Collection drops = forgeEntity.captureDrops(null); - if (!MinecraftForge.EVENT_BUS.post(new LivingDropsEvent(entity, src, drops, dropLootingLevel.get(), playerHitTimer > 0))) { + if (!EntityEvents.onLivingDrops(entity, src, drops, dropLootingLevel.get(), playerHitTimer > 0)) { for (ItemEntity item : drops) { forgeEntity.getEntity().world.spawnEntity(item); } diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 914132e0..24901999 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -4,6 +4,7 @@ version = getSubprojectVersion(project, "0.1.0") dependencies { compile project(path: ':patchwork-fml', configuration: 'dev') compile project(path: ':patchwork-capabilities', configuration: 'dev') + compile project(path: ':patchwork-events-entity', configuration: 'dev') compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') compile project(path: ':patchwork-events-rendering', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java index ed4d8220..dea1ec51 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -19,9 +19,83 @@ package net.minecraftforge.common; +import java.util.Collection; + +import javax.annotation.Nullable; + +import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.eventbus.api.Event; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnType; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.world.IWorld; +import net.minecraft.world.MobSpawnerLogic; + +import net.patchworkmc.impl.event.entity.EntityEvents; + /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. * Do not keep implementation details here, methods should be thin wrappers around methods in other modules. */ public class ForgeHooks { + public static int canEntitySpawn(MobEntity entity, IWorld world, double x, double y, double z, MobSpawnerLogic spawner, SpawnType spawnReason) { + Event.Result res = ForgeEventFactory.canEntitySpawn(entity, world, x, y, z, null, spawnReason); + return res == Event.Result.DEFAULT ? 0 : res == Event.Result.DENY ? -1 : 1; + } + + // TODO: onInteractEntityAt + + public static ActionResult onInteractEntity(PlayerEntity player, Entity entity, Hand hand) { + return EntityEvents.onInteractEntity(player, entity, hand); + } + + public static boolean onLivingDeath(LivingEntity entity, DamageSource src) { + return EntityEvents.onLivingDeath(entity, src); + } + + public static boolean onLivingUpdate(LivingEntity entity) { + return EntityEvents.onLivingUpdateEvent(entity); + } + + // TODO: forge calls the equivilant to this in LivingEntity, but patchwork only calls the equivilant to onPlayerAttack + public static boolean onLivingAttack(LivingEntity entity, DamageSource src, float amount) { + return entity instanceof PlayerEntity || onPlayerAttack(entity, src, amount); + } + + public static boolean onPlayerAttack(LivingEntity entity, DamageSource src, float amount) { + return !EntityEvents.onLivingAttack(entity, src, amount); + } + + // optifine wants this? O.o + public static void onLivingSetAttackTarget(LivingEntity entity, LivingEntity target) { + EntityEvents.onLivingSetAttackTarget(entity, target); + } + + public static float onLivingHurt(LivingEntity entity, DamageSource src, float amount) { + return EntityEvents.onLivingHurt(entity, src, amount); + } + + @Nullable + public static float[] onLivingFall(LivingEntity entity, float distance, float damageMultiplier) { + return EntityEvents.onLivingFall(entity, distance, damageMultiplier); + } + + public static float onLivingDamage(LivingEntity entity, DamageSource src, float amount) { + return EntityEvents.onLivingDamage(entity, src, amount); + } + + public static boolean onLivingDrops(LivingEntity entity, DamageSource source, Collection drops, int lootingLevel, boolean recentlyHit) { + return EntityEvents.onLivingDrops(entity, source, drops, lootingLevel, recentlyHit); + } + + public static boolean onPlayerAttackTarget(PlayerEntity player, Entity target) { + return EntityEvents.attackEntity(player, target); + } } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 9d526437..f6bc5485 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -23,8 +23,17 @@ import net.minecraftforge.common.capabilities.CapabilityDispatcher; import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.eventbus.api.Event; + +import net.minecraft.entity.SpawnType; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.world.IWorld; +import net.minecraft.world.MobSpawnerLogic; +import net.minecraft.world.World; import net.patchworkmc.impl.capability.CapabilityEvents; +import net.patchworkmc.impl.event.entity.EntityEvents; /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. @@ -40,4 +49,20 @@ public static CapabilityDispatcher gatherCapabilities(Class typ public static CapabilityDispatcher gatherCapabilities(Class type, T provider, @Nullable ICapabilityProvider parent) { return CapabilityEvents.gatherCapabilities(type, provider, parent); } + + public static Event.Result canEntitySpawn(MobEntity entity, IWorld world, double x, double y, double z, MobSpawnerLogic spawner, SpawnType spawnReason) { + return EntityEvents.canEntitySpawn(entity, world, x, y, z, spawner, spawnReason); + } + + public static boolean canEntitySpawnSpawner(MobEntity entity, World world, float x, float y, float z, MobSpawnerLogic spawner) { + return EntityEvents.canEntitySpawnFromSpawner(entity, world, x, y, z, spawner); + } + + public static void onPlayerFall(PlayerEntity player, float distance, float multiplier) { + EntityEvents.onFlyablePlayerFall(player, distance, multiplier); + } + + public static boolean doSpecialSpawn(MobEntity entity, World world, float x, float y, float z, MobSpawnerLogic spawner, SpawnType spawnReason) { + return EntityEvents.doSpecialSpawn(entity, world, x, y, z, spawner, spawnReason); + } } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java index aaebffd3..ca968de2 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java @@ -24,6 +24,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.World; +import net.patchworkmc.impl.event.entity.EntityEvents; import net.patchworkmc.impl.event.lifecycle.LifecycleEvents; /* @@ -31,6 +32,10 @@ * Do not keep implementation details here, methods should be thin wrappers around methods in other modules. */ public class BasicEventHooks { + public static void firePlayerLoggedIn(PlayerEntity player) { + EntityEvents.onPlayerLoggedIn(player); + } + public static void onPlayerPreTick(PlayerEntity player) { LifecycleEvents.firePlayerTickEvent(TickEvent.Phase.START, player); } From 0316d313f80e6629f26b1acc7a0255cbefc83feb Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Tue, 21 Jul 2020 19:16:46 -0400 Subject: [PATCH 07/73] Change IForgeRegistryEntry.setRegistryName to return V, not IForgeRegistryEntry (#131) * Change IForgeRegistryEntry.setRegistryName to return V, not IForgeRegistryEntry * ExtendedForgeRegistryEntry * Appease checkstyle --- .../net/minecraftforge/registries/ForgeRegistryEntry.java | 8 ++++---- .../minecraftforge/registries/IForgeRegistryEntry.java | 2 +- .../impl/registries/ExtendedForgeRegistryEntry.java | 4 ++-- .../net/patchworkmc/mixin/registries/MixinActivity.java | 5 ++--- .../java/net/patchworkmc/mixin/registries/MixinBiome.java | 5 ++--- .../mixin/registries/MixinBiomeSourceType.java | 5 ++--- .../java/net/patchworkmc/mixin/registries/MixinBlock.java | 5 ++--- .../mixin/registries/MixinBlockEntityType.java | 7 +++---- .../net/patchworkmc/mixin/registries/MixinCarver.java | 5 ++--- .../mixin/registries/MixinChunkGeneratorType.java | 5 ++--- .../patchworkmc/mixin/registries/MixinChunkStatus.java | 5 ++--- .../patchworkmc/mixin/registries/MixinContainerType.java | 5 ++--- .../net/patchworkmc/mixin/registries/MixinDecorator.java | 5 ++--- .../patchworkmc/mixin/registries/MixinEnchantment.java | 5 ++--- .../net/patchworkmc/mixin/registries/MixinEntityType.java | 5 ++--- .../net/patchworkmc/mixin/registries/MixinFeature.java | 5 ++--- .../java/net/patchworkmc/mixin/registries/MixinFluid.java | 5 ++--- .../java/net/patchworkmc/mixin/registries/MixinItem.java | 5 ++--- .../mixin/registries/MixinMemoryModuleType.java | 5 ++--- .../patchworkmc/mixin/registries/MixinPaintingMotive.java | 5 ++--- .../patchworkmc/mixin/registries/MixinParticleType.java | 5 ++--- .../mixin/registries/MixinPointOfInterestType.java | 5 ++--- .../net/patchworkmc/mixin/registries/MixinPotion.java | 5 ++--- .../mixin/registries/MixinRecipeSerializerSubclass.java | 5 ++--- .../net/patchworkmc/mixin/registries/MixinSchedule.java | 5 ++--- .../net/patchworkmc/mixin/registries/MixinSensorType.java | 5 ++--- .../patchworkmc/mixin/registries/MixinSimpleRegistry.java | 2 +- .../net/patchworkmc/mixin/registries/MixinSoundEvent.java | 5 ++--- .../net/patchworkmc/mixin/registries/MixinStatType.java | 5 ++--- .../patchworkmc/mixin/registries/MixinStatusEffect.java | 5 ++--- .../patchworkmc/mixin/registries/MixinSurfaceBuilder.java | 5 ++--- .../mixin/registries/MixinVillagerProfession.java | 5 ++--- 32 files changed, 65 insertions(+), 93 deletions(-) diff --git a/patchwork-registries/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java b/patchwork-registries/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java index 9a77918d..6814059e 100644 --- a/patchwork-registries/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java +++ b/patchwork-registries/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java @@ -25,20 +25,20 @@ public abstract class ForgeRegistryEntry implements IForgeRegistryEntry { private Identifier registryName; @Override - public final IForgeRegistryEntry setRegistryName(Identifier name) { + public final V setRegistryName(Identifier name) { return setRegistryName(name.toString()); } - public final IForgeRegistryEntry setRegistryName(String name) { + public final V setRegistryName(String name) { if (getRegistryName() != null) { throw new IllegalStateException("Attempted to set registry name with existing registry name! New: " + name + " Old: " + getRegistryName()); } this.registryName = GameData.checkPrefix(name, true); - return this; + return (V) this; } - public final IForgeRegistryEntry setRegistryName(String modID, String name) { + public final V setRegistryName(String modID, String name) { return setRegistryName(modID + ":" + name); } diff --git a/patchwork-registries/src/main/java/net/minecraftforge/registries/IForgeRegistryEntry.java b/patchwork-registries/src/main/java/net/minecraftforge/registries/IForgeRegistryEntry.java index 9834ab7f..6a79c353 100644 --- a/patchwork-registries/src/main/java/net/minecraftforge/registries/IForgeRegistryEntry.java +++ b/patchwork-registries/src/main/java/net/minecraftforge/registries/IForgeRegistryEntry.java @@ -39,7 +39,7 @@ public interface IForgeRegistryEntry { * @param name the unique {@link Identifier} * @return this instance, to allow for chaining */ - IForgeRegistryEntry setRegistryName(Identifier name); + V setRegistryName(Identifier name); /** * Determines the type for this entry, used to look up the correct registry in the global registries list as there can only be one diff --git a/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java b/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java index 17907290..ec39a098 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java @@ -25,7 +25,7 @@ import net.minecraft.util.Identifier; public interface ExtendedForgeRegistryEntry extends IForgeRegistryEntry { - default IForgeRegistryEntry setRegistryName(String full) { + default V setRegistryName(String full) { String activeNamespace = ModLoadingContext.get().getActiveNamespace(); if (activeNamespace == null || activeNamespace.equals("minecraft")) { @@ -47,7 +47,7 @@ default IForgeRegistryEntry setRegistryName(String full) { return this.setRegistryName(identifier); } - default IForgeRegistryEntry setRegistryName(String namespace, String name) { + default V setRegistryName(String namespace, String name) { return this.setRegistryName(new Identifier(namespace, name)); } } diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinActivity.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinActivity.java index 6fc3279f..f1df4619 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinActivity.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinActivity.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinActivity implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Activity setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Activity) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiome.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiome.java index a4886a4d..36c5ac4d 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiome.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiome.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinBiome implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Biome setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Biome) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiomeSourceType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiomeSourceType.java index b4ae7904..a2ae2f03 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiomeSourceType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiomeSourceType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinBiomeSourceType implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public BiomeSourceType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (BiomeSourceType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlock.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlock.java index 8c4a2bc1..480317fd 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlock.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlock.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinBlock implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Block setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Block) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlockEntityType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlockEntityType.java index 5955dae2..949cd8cd 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlockEntityType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlockEntityType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,14 +35,14 @@ public class MixinBlockEntityType implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public BlockEntityType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (BlockEntityType) (Object) this; } public Identifier getRegistryName() { - BlockEntityType blockEntityType = (BlockEntityType) (Object) this; + BlockEntityType blockEntityType = (BlockEntityType) (Object) this; return Identifiers.getOrFallback(Registry.BLOCK_ENTITY, blockEntityType, registryName); } diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinCarver.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinCarver.java index 839eded0..2e926496 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinCarver.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinCarver.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinCarver implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Carver setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Carver) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkGeneratorType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkGeneratorType.java index 78619711..f960679d 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkGeneratorType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkGeneratorType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinChunkGeneratorType implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public ChunkGeneratorType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (ChunkGeneratorType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkStatus.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkStatus.java index 00d78fdb..7442a210 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkStatus.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkStatus.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinChunkStatus implements ExtendedForgeRegistryEntry private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public ChunkStatus setRegistryName(Identifier name) { this.registryName = name; - return this; + return (ChunkStatus) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinContainerType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinContainerType.java index a4f6c18a..5b3299fb 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinContainerType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinContainerType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinContainerType implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public ContainerType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (ContainerType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinDecorator.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinDecorator.java index 1574d0dd..9f9150ee 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinDecorator.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinDecorator.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinDecorator implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Decorator setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Decorator) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEnchantment.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEnchantment.java index 2aed1df2..7f9fc065 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEnchantment.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEnchantment.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinEnchantment implements ExtendedForgeRegistryEntry private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Enchantment setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Enchantment) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEntityType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEntityType.java index f2ea1ca4..347d7c1e 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEntityType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEntityType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinEntityType implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public EntityType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (EntityType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFeature.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFeature.java index fe01389c..00c88677 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFeature.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFeature.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinFeature implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Feature setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Feature) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFluid.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFluid.java index ba2f4676..4588fed4 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFluid.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFluid.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinFluid implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Fluid setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Fluid) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinItem.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinItem.java index 36cec86c..5802f540 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinItem.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinItem.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinItem implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Item setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Item) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinMemoryModuleType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinMemoryModuleType.java index feabaac7..3d49ee57 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinMemoryModuleType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinMemoryModuleType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinMemoryModuleType implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public MemoryModuleType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (MemoryModuleType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPaintingMotive.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPaintingMotive.java index 24857aaa..bb87d853 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPaintingMotive.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPaintingMotive.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinPaintingMotive implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public PaintingMotive setRegistryName(Identifier name) { this.registryName = name; - return this; + return (PaintingMotive) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinParticleType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinParticleType.java index d9df6636..1f2d2322 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinParticleType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinParticleType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinParticleType implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public ParticleType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (ParticleType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPointOfInterestType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPointOfInterestType.java index d6a4864c..b139b7cf 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPointOfInterestType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPointOfInterestType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinPointOfInterestType implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public PointOfInterestType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (PointOfInterestType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPotion.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPotion.java index 26fd4fc8..dabac439 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPotion.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPotion.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinPotion implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Potion setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Potion) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinRecipeSerializerSubclass.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinRecipeSerializerSubclass.java index c38f7da0..17c7ac4c 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinRecipeSerializerSubclass.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinRecipeSerializerSubclass.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -41,10 +40,10 @@ public class MixinRecipeSerializerSubclass implements ExtendedForgeRegistryEntry private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public RecipeSerializer setRegistryName(Identifier name) { this.registryName = name; - return this; + return (RecipeSerializer) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSchedule.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSchedule.java index 5b83c739..3118df0f 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSchedule.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSchedule.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinSchedule implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public Schedule setRegistryName(Identifier name) { this.registryName = name; - return this; + return (Schedule) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSensorType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSensorType.java index 34f56c2c..371b7d75 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSensorType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSensorType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinSensorType implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public SensorType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (SensorType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSimpleRegistry.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSimpleRegistry.java index a5d181fd..0242cbf5 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSimpleRegistry.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSimpleRegistry.java @@ -19,8 +19,8 @@ package net.patchworkmc.mixin.registries; -import org.spongepowered.asm.mixin.Mixin; import net.minecraftforge.registries.ForgeRegistry; +import org.spongepowered.asm.mixin.Mixin; import net.minecraft.util.registry.SimpleRegistry; diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSoundEvent.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSoundEvent.java index 578dbd9f..355e93f6 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSoundEvent.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSoundEvent.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinSoundEvent implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public SoundEvent setRegistryName(Identifier name) { this.registryName = name; - return this; + return (SoundEvent) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatType.java index 13c956e9..d6f8838d 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatType.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinStatType implements ExtendedForgeRegistryEntry { private Identifier registryName; @Override - public IForgeRegistryEntry setRegistryName(Identifier name) { + public StatType setRegistryName(Identifier name) { this.registryName = name; - return this; + return (StatType) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatusEffect.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatusEffect.java index 79b89da3..074e5fc0 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatusEffect.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatusEffect.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinStatusEffect implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public StatusEffect setRegistryName(Identifier name) { this.registryName = name; - return this; + return (StatusEffect) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSurfaceBuilder.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSurfaceBuilder.java index 122097c9..7b6e7e79 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSurfaceBuilder.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSurfaceBuilder.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinSurfaceBuilder implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public SurfaceBuilder setRegistryName(Identifier name) { this.registryName = name; - return this; + return (SurfaceBuilder) (Object) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinVillagerProfession.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinVillagerProfession.java index c18e3a60..d3c8bbcb 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinVillagerProfession.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinVillagerProfession.java @@ -19,7 +19,6 @@ package net.patchworkmc.mixin.registries; -import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -36,10 +35,10 @@ public class MixinVillagerProfession implements ExtendedForgeRegistryEntry setRegistryName(Identifier name) { + public VillagerProfession setRegistryName(Identifier name) { this.registryName = name; - return this; + return (VillagerProfession) (Object) this; } public Identifier getRegistryName() { From 657afda93555fe80fcf1562309982b06c3b70f25 Mon Sep 17 00:00:00 2001 From: Kitlith Date: Tue, 21 Jul 2020 16:50:13 -0700 Subject: [PATCH 08/73] Add LootTableLoadEvent, methods on LootPool/LootTable (#113) * Add LootTableLoadEvent, methods on LootPool/LootTable The mixin to LootManager is messy, and I'm open to alternative ways to doing it, even if it involves scrapping the 'forge way' of doing it and doing it a different way. For now, I'm going to get this up so that bikeshedding can happen. I'm using the "net.patchworkmc.api.*.Forge" pattern for interfaces that describe public methods added by Forge for use by mods in this commit. This is up for bikeshedding. This is untested other than starting up Minecraft and opening a world. * Fix LocalCapture.PRINT that I forgot about * Implement FMLServerStoppedEvent * Dispatch from the god classes for the events added in this PR * prevent memory leak * fixup! checkstype * Make slightly less hacky! The idea is to add an inject in the same place as the method we would be redirecting (but are instead cancelling) so that we can capture locals, and grab the builder that we would otherwise be missing. The downside is that we are effectively overwriting the lambda that vanilla uses in favor of our own. * Make the implicit "overwrite" explicit. * Make requested changes. Mainly adding Override annotations to methods for interfaces, but a few other things as well. --- .../event/server/FMLServerStoppedEvent.java | 35 ++++ .../fml/server/ServerLifecycleHooks.java | 7 + .../impl/event/lifecycle/LifecycleEvents.java | 14 ++ .../event/lifecycle/MixinMinecraftServer.java | 37 +++++ patchwork-god-classes/build.gradle | 1 + .../net/minecraftforge/common/ForgeHooks.java | 15 ++ .../event/ForgeEventFactory.java | 8 + .../src/main/resources/fabric.mod.json | 3 +- patchwork-loot/build.gradle | 5 + .../event/LootTableLoadEvent.java | 67 ++++++++ .../patchworkmc/api/loot/ForgeLootPool.java | 42 +++++ .../patchworkmc/api/loot/ForgeLootTable.java | 33 ++++ .../impl/event/loot/LootEvents.java | 39 +++++ .../net/patchworkmc/impl/loot/LootHooks.java | 149 ++++++++++++++++++ .../impl/loot/PatchworkLootPool.java | 28 ++++ .../mixin/loot/MixinJsonDataLoader.java | 44 ++++++ .../mixin/loot/MixinLootManager.java | 81 ++++++++++ .../patchworkmc/mixin/loot/MixinLootPool.java | 82 ++++++++++ .../mixin/loot/MixinLootPoolBuilder.java | 60 +++++++ .../mixin/loot/MixinLootPoolSerializer.java | 64 ++++++++ .../mixin/loot/MixinLootTable.java | 75 +++++++++ .../main/resources/patchwork-loot.mixins.json | 8 +- 22 files changed, 895 insertions(+), 2 deletions(-) create mode 100644 patchwork-events-lifecycle/src/main/java/net/minecraftforge/fml/event/server/FMLServerStoppedEvent.java create mode 100644 patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftServer.java create mode 100644 patchwork-loot/src/main/java/net/minecraftforge/event/LootTableLoadEvent.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/api/loot/ForgeLootPool.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/api/loot/ForgeLootTable.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/impl/event/loot/LootEvents.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/impl/loot/LootHooks.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/impl/loot/PatchworkLootPool.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinJsonDataLoader.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootManager.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPool.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPoolBuilder.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPoolSerializer.java create mode 100644 patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootTable.java diff --git a/patchwork-events-lifecycle/src/main/java/net/minecraftforge/fml/event/server/FMLServerStoppedEvent.java b/patchwork-events-lifecycle/src/main/java/net/minecraftforge/fml/event/server/FMLServerStoppedEvent.java new file mode 100644 index 00000000..fdd56c06 --- /dev/null +++ b/patchwork-events-lifecycle/src/main/java/net/minecraftforge/fml/event/server/FMLServerStoppedEvent.java @@ -0,0 +1,35 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.event.server; + +import net.minecraft.server.MinecraftServer; + +/** + * Called after {@link FMLServerStoppingEvent} when the server has completely shut down. + * Called immediately before shutting down, on the dedicated server, and before returning + * to the main menu on the client. + * + * @author cpw + */ +public class FMLServerStoppedEvent extends ServerLifecycleEvent { + public FMLServerStoppedEvent(MinecraftServer server) { + super(server); + } +} diff --git a/patchwork-events-lifecycle/src/main/java/net/minecraftforge/fml/server/ServerLifecycleHooks.java b/patchwork-events-lifecycle/src/main/java/net/minecraftforge/fml/server/ServerLifecycleHooks.java index c3c1b8fc..034bf4bb 100644 --- a/patchwork-events-lifecycle/src/main/java/net/minecraftforge/fml/server/ServerLifecycleHooks.java +++ b/patchwork-events-lifecycle/src/main/java/net/minecraftforge/fml/server/ServerLifecycleHooks.java @@ -19,6 +19,8 @@ package net.minecraftforge.fml.server; +import java.util.concurrent.CountDownLatch; + import net.minecraft.server.MinecraftServer; import net.patchworkmc.impl.event.lifecycle.LifecycleEvents; @@ -28,6 +30,7 @@ */ public class ServerLifecycleHooks { public static MinecraftServer currentServer; + public static volatile CountDownLatch exitLatch = null; public static MinecraftServer getCurrentServer() { return currentServer; @@ -48,4 +51,8 @@ public static boolean handleServerStarting(final MinecraftServer server) { public static void handleServerStarted(final MinecraftServer server) { LifecycleEvents.handleServerStarted(server); } + + public static void handleServerStopped(final MinecraftServer server) { + LifecycleEvents.handleServerStopped(server); + } } diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java index 8c950a0c..5dd0e083 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java @@ -20,6 +20,7 @@ package net.patchworkmc.impl.event.lifecycle; import java.nio.file.Path; +import java.util.concurrent.CountDownLatch; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent; @@ -30,6 +31,7 @@ import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent; +import net.minecraftforge.fml.event.server.FMLServerStoppedEvent; import net.minecraftforge.fml.loading.FileUtils; import net.minecraftforge.fml.server.ServerLifecycleHooks; @@ -93,6 +95,18 @@ public static void handleLoadComplete() { loadCompleteCallback.run(); } + public static void handleServerStopped(final MinecraftServer server) { + MinecraftForge.EVENT_BUS.post(new FMLServerStoppedEvent(server)); + ServerLifecycleHooks.currentServer = null; + LogicalSidedProvider.setServer(null); + CountDownLatch latch = ServerLifecycleHooks.exitLatch; + + if (latch != null) { + latch.countDown(); + ServerLifecycleHooks.exitLatch = null; + } + } + @Override public void onInitialize() { WorldTickCallback.EVENT.register(world -> fireWorldTickEvent(TickEvent.Phase.END, world)); diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftServer.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftServer.java new file mode 100644 index 00000000..6527d290 --- /dev/null +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftServer.java @@ -0,0 +1,37 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.lifecycle; + +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.server.MinecraftServer; + +import net.patchworkmc.impl.event.lifecycle.LifecycleEvents; + +@Mixin(MinecraftServer.class) +public class MixinMinecraftServer { + @Inject(method = "run", at = @At(value = "INVOKE", target = "net/minecraft/server/MinecraftServer.exit ()V")) + private void serverStoppedHook(CallbackInfo ci) { + LifecycleEvents.handleServerStopped((MinecraftServer) (Object) this); + } +} diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 24901999..ad0f0d6a 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -7,4 +7,5 @@ dependencies { compile project(path: ':patchwork-events-entity', configuration: 'dev') compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') compile project(path: ':patchwork-events-rendering', configuration: 'dev') + compile project(path: ':patchwork-loot', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java index dea1ec51..65e86ca0 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -23,6 +23,8 @@ import javax.annotation.Nullable; +import com.google.gson.Gson; +import com.google.gson.JsonObject; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.eventbus.api.Event; @@ -33,12 +35,16 @@ import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.loot.LootManager; +import net.minecraft.loot.LootTable; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; +import net.minecraft.util.Identifier; import net.minecraft.world.IWorld; import net.minecraft.world.MobSpawnerLogic; import net.patchworkmc.impl.event.entity.EntityEvents; +import net.patchworkmc.impl.loot.LootHooks; /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. @@ -98,4 +104,13 @@ public static boolean onLivingDrops(LivingEntity entity, DamageSource source, Co public static boolean onPlayerAttackTarget(PlayerEntity player, Entity target) { return EntityEvents.attackEntity(player, target); } + + @Nullable + public static LootTable loadLootTable(Gson gson, Identifier name, JsonObject data, boolean custom, LootManager lootTableManager) { + return LootHooks.loadLootTable(gson, name, data, custom, lootTableManager); + } + + public static String readPoolName(JsonObject json) { + return LootHooks.readPoolName(json); + } } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index f6bc5485..665926e3 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -28,12 +28,16 @@ import net.minecraft.entity.SpawnType; import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.loot.LootManager; +import net.minecraft.loot.LootTable; +import net.minecraft.util.Identifier; import net.minecraft.world.IWorld; import net.minecraft.world.MobSpawnerLogic; import net.minecraft.world.World; import net.patchworkmc.impl.capability.CapabilityEvents; import net.patchworkmc.impl.event.entity.EntityEvents; +import net.patchworkmc.impl.event.loot.LootEvents; /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. @@ -65,4 +69,8 @@ public static void onPlayerFall(PlayerEntity player, float distance, float multi public static boolean doSpecialSpawn(MobEntity entity, World world, float x, float y, float z, MobSpawnerLogic spawner, SpawnType spawnReason) { return EntityEvents.doSpecialSpawn(entity, world, x, y, z, spawner, spawnReason); } + + public static LootTable loadLootTable(Identifier name, LootTable table, LootManager lootTableManager) { + return LootEvents.loadLootTable(name, table, lootTableManager); + } } diff --git a/patchwork-god-classes/src/main/resources/fabric.mod.json b/patchwork-god-classes/src/main/resources/fabric.mod.json index 07c35810..388b9196 100644 --- a/patchwork-god-classes/src/main/resources/fabric.mod.json +++ b/patchwork-god-classes/src/main/resources/fabric.mod.json @@ -19,7 +19,8 @@ "patchwork-fml": "*", "patchwork-capabilities": "*", "patchwork-events-lifecycle": "*", - "patchwork-events-rendering": "*" + "patchwork-events-rendering": "*", + "patchwork-loot": "*" }, "custom": { "modmenu:api": true, diff --git a/patchwork-loot/build.gradle b/patchwork-loot/build.gradle index 9029bd24..0caa77dc 100644 --- a/patchwork-loot/build.gradle +++ b/patchwork-loot/build.gradle @@ -1,2 +1,7 @@ archivesBaseName = "patchwork-loot" version = getSubprojectVersion(project, "0.2.0") + +dependencies { + compile project(path: ':patchwork-fml', configuration: 'dev') +} + diff --git a/patchwork-loot/src/main/java/net/minecraftforge/event/LootTableLoadEvent.java b/patchwork-loot/src/main/java/net/minecraftforge/event/LootTableLoadEvent.java new file mode 100644 index 00000000..93ecb6b8 --- /dev/null +++ b/patchwork-loot/src/main/java/net/minecraftforge/event/LootTableLoadEvent.java @@ -0,0 +1,67 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event; + +import net.minecraftforge.eventbus.api.Event; + +import net.minecraft.loot.LootManager; +import net.minecraft.loot.LootTable; +import net.minecraft.util.Identifier; + +/** + * Event fired when a LootTable json is loaded from json. + * This event is fired whenever resources are loaded, or when the server starts. + * This event will NOT be fired for LootTables loaded from the world folder, these are + * considered configurations files and should not be modified by mods. + * + *

Canceling the event will make it load a empty loot table.

+ */ +public class LootTableLoadEvent extends Event { + private final Identifier name; + private LootTable table; + private LootManager lootTableManager; + + public LootTableLoadEvent(Identifier name, LootTable table, LootManager lootTableManager) { + this.name = name; + this.table = table; + this.lootTableManager = lootTableManager; + } + + public Identifier getName() { + return this.name; + } + + public LootTable getTable() { + return this.table; + } + + public void setTable(LootTable table) { + this.table = table; + } + + public LootManager getLootTableManager() { + return this.lootTableManager; + } + + @Override + public boolean isCancelable() { + return true; + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/api/loot/ForgeLootPool.java b/patchwork-loot/src/main/java/net/patchworkmc/api/loot/ForgeLootPool.java new file mode 100644 index 00000000..7aef5158 --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/api/loot/ForgeLootPool.java @@ -0,0 +1,42 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.api.loot; + +import net.minecraft.loot.LootPool; +import net.minecraft.loot.LootTableRange; +import net.minecraft.loot.UniformLootTableRange; + +/** + * Interface for adding Forge methods added to LootPool and its inner classes. + */ +public interface ForgeLootPool { + // TODO: doesn't include methods having to do with freezing yet + + String getName(); + LootTableRange getRolls(); + LootTableRange getBonusRolls(); + void setRolls(UniformLootTableRange v); + void setBonusRolls(UniformLootTableRange v); + + public interface Builder { + LootPool.Builder name(String name); + LootPool.Builder bonusRolls(float min, float max); + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/api/loot/ForgeLootTable.java b/patchwork-loot/src/main/java/net/patchworkmc/api/loot/ForgeLootTable.java new file mode 100644 index 00000000..86650bac --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/api/loot/ForgeLootTable.java @@ -0,0 +1,33 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.api.loot; + +import net.minecraft.loot.LootPool; + +/** + * Interface for adding Forge methods added to LootTable. + */ +public interface ForgeLootTable { + // TODO: doesn't include methods having to do with freezing yet + + LootPool getPool(String name); + LootPool removePool(String name); + void addPool(LootPool pool); +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/impl/event/loot/LootEvents.java b/patchwork-loot/src/main/java/net/patchworkmc/impl/event/loot/LootEvents.java new file mode 100644 index 00000000..c732f201 --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/impl/event/loot/LootEvents.java @@ -0,0 +1,39 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.event.loot; + +import net.minecraftforge.event.LootTableLoadEvent; +import net.minecraftforge.common.MinecraftForge; + +import net.minecraft.loot.LootManager; +import net.minecraft.loot.LootTable; +import net.minecraft.util.Identifier; + +public class LootEvents { + public static LootTable loadLootTable(Identifier name, LootTable table, LootManager manager) { + LootTableLoadEvent event = new LootTableLoadEvent(name, table, manager); + + if (MinecraftForge.EVENT_BUS.post(event)) { + return LootTable.EMPTY; + } + + return event.getTable(); + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/LootHooks.java b/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/LootHooks.java new file mode 100644 index 00000000..93492205 --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/LootHooks.java @@ -0,0 +1,149 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.loot; + +import java.util.Deque; +import java.util.HashSet; + +import javax.annotation.Nullable; + +import com.google.common.collect.Queues; +import com.google.common.collect.Sets; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.loot.LootManager; +import net.minecraft.loot.LootTable; +import net.minecraft.util.Identifier; +import net.minecraft.util.JsonHelper; + +import net.patchworkmc.impl.event.loot.LootEvents; + +// NOTE: this class is more or less a direct copy of parts of Forge's ForgeHooks. +public class LootHooks { + @Unique + private static ThreadLocal> lootContext = new ThreadLocal>(); + + public static LootTable loadLootTable(Gson gson, Identifier name, JsonElement data, boolean custom, LootManager lootTableManager) { + Deque que = lootContext.get(); + + if (que == null) { + que = Queues.newArrayDeque(); + lootContext.set(que); + } + + LootTable ret = null; + + try { + que.push(new LootTableContext(name, custom)); + ret = gson.fromJson(data, LootTable.class); + que.pop(); + } catch (JsonParseException e) { + que.pop(); + throw e; + } + + if (!custom) { + ret = LootEvents.loadLootTable(name, ret, lootTableManager); + } + + // if (ret != null) { + // ret.freeze(); + // } + + return ret; + } + + private static LootTableContext getLootTableContext() { + LootTableContext ctx = lootContext.get().peek(); + + if (ctx == null) { + throw new JsonParseException("Invalid call stack, could not grab json context!"); // Should I throw this? Do we care about custom deserializers outside the manager? + } + + return ctx; + } + + public static String readPoolName(JsonObject json) { + LootTableContext ctx = LootHooks.getLootTableContext(); + ctx.resetPoolCtx(); + + if (json.has("name")) { + return JsonHelper.getString(json, "name"); + } + + if (ctx.custom) { + return "custom#" + json.hashCode(); //We don't care about custom ones modders shouldn't be editing them! + } + + ctx.poolCount++; + + if (!ctx.vanilla) { + throw new JsonParseException("Loot Table \"" + ctx.name.toString() + "\" Missing `name` entry for pool #" + (ctx.poolCount - 1)); + } + + return ctx.poolCount == 1 ? "main" : "pool" + (ctx.poolCount - 1); + } + + private static class LootTableContext { + public final Identifier name; + public final boolean custom; + private final boolean vanilla; + public int poolCount = 0; + public int entryCount = 0; + private HashSet entryNames = Sets.newHashSet(); + + private LootTableContext(Identifier name, boolean custom) { + this.name = name; + this.custom = custom; + this.vanilla = "minecraft".equals(this.name.getNamespace()); + } + + private void resetPoolCtx() { + this.entryCount = 0; + this.entryNames.clear(); + } + + public String validateEntryName(@Nullable String name) { + if (name != null && !this.entryNames.contains(name)) { + this.entryNames.add(name); + return name; + } + + if (!this.vanilla) { + throw new JsonParseException("Loot Table \"" + this.name.toString() + "\" Duplicate entry name \"" + name + "\" for pool #" + (this.poolCount - 1) + " entry #" + (this.entryCount - 1)); + } + + int x = 0; + + while (this.entryNames.contains(name + "#" + x)) { + x++; + } + + name = name + "#" + x; + this.entryNames.add(name); + + return name; + } + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/PatchworkLootPool.java b/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/PatchworkLootPool.java new file mode 100644 index 00000000..68770139 --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/PatchworkLootPool.java @@ -0,0 +1,28 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.loot; + +/** + * Forge does this through patching the constructor, we just add methods with + * mixins instead. + */ +public interface PatchworkLootPool { + void patchwork$setName(String name); +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinJsonDataLoader.java b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinJsonDataLoader.java new file mode 100644 index 00000000..85b3b420 --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinJsonDataLoader.java @@ -0,0 +1,44 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.loot; + +import java.util.Map; + +import com.google.gson.JsonObject; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.resource.JsonDataLoader; +import net.minecraft.resource.SinglePreparationResourceReloadListener; +import net.minecraft.util.Identifier; + +// TODO: Is there a better place to put this? +@Mixin(JsonDataLoader.class) +public abstract class MixinJsonDataLoader extends SinglePreparationResourceReloadListener> { + @Shadow + @Final + String dataType; + + // This does not get its own interface -- any mixins on subclasses wishing to use it should probably extend this mixin. + protected Identifier getPreparedPath(Identifier id) { + return new Identifier(id.getNamespace(), dataType + "/" + id.getPath() + ".json"); + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootManager.java b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootManager.java new file mode 100644 index 00000000..4ae6cb97 --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootManager.java @@ -0,0 +1,81 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.loot; + +import java.util.Map; +import java.util.function.BiConsumer; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import net.minecraft.loot.LootManager; +import net.minecraft.loot.LootTable; +import net.minecraft.resource.Resource; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.util.profiler.Profiler; + +import net.patchworkmc.impl.loot.LootHooks; + +@Mixin(LootManager.class) +public abstract class MixinLootManager extends MixinJsonDataLoader { + @Shadow + @Final + private static Gson GSON; + + @Shadow + @Final + private static Logger LOGGER; + + @Redirect(method = "apply", at = @At(value = "INVOKE", target = "java/util/Map.forEach (Ljava/util/function/BiConsumer;)V", ordinal = 0)) + private void cancel_forEach(Map map, BiConsumer consumer) { + // ignore this call, we're gonna reintroduce it but with capturing locals + } + + @Inject(method = "apply", at = @At(value = "INVOKE", target = "java/util/Map.forEach (Ljava/util/function/BiConsumer;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) + private void reintroduce_forEach(Map map, ResourceManager resourceManager, Profiler profiler, CallbackInfo info, ImmutableMap.Builder builder) { + map.forEach((id, jsonObject) -> { + try { + LootManager lootManager = (LootManager) (Object) this; + Resource res = resourceManager.getResource(this.getPreparedPath(id)); + LootTable lootTable = LootHooks.loadLootTable(GSON, id, jsonObject, res == null || !res.getResourcePackName().equals("Default"), lootManager); + builder.put(id, lootTable); + } catch (Exception ex) { + LOGGER.error("Couldn't parse loot table {}", id, ex); + } + }); + } + + @Overwrite + private static void method_20711(ImmutableMap.Builder builder, Identifier id, JsonObject obj) { + // We are effectively overwriting this lambda with our own, so let's make that explicit by actually overwriting it. + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPool.java b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPool.java new file mode 100644 index 00000000..b538bfbf --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPool.java @@ -0,0 +1,82 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.loot; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +import net.minecraft.loot.LootPool; +import net.minecraft.loot.LootTableRange; +import net.minecraft.loot.UniformLootTableRange; + +import net.patchworkmc.api.loot.ForgeLootPool; +import net.patchworkmc.impl.loot.PatchworkLootPool; + +@Mixin(LootPool.class) +public class MixinLootPool implements PatchworkLootPool, ForgeLootPool { + // Forge has this as final, but I don't have a good way to initialize it if it is final. + @Unique + private String name; + + @Shadow + private UniformLootTableRange bonusRollsRange; + + @Shadow + private LootTableRange rollsRange; + + // implementation detail + // TODO: if we could have an inner class that was also a mixin, we could set this as protected? + @Override + public void patchwork$setName(String name) { + this.name = name; + } + + // Forge methods that should be added directly to the type + + // TODO: freezing stuff + + @Override + public String getName() { + return this.name; + } + + @Override + public LootTableRange getRolls() { + return rollsRange; + } + + @Override + public LootTableRange getBonusRolls() { + return this.bonusRollsRange; + } + + @Override + public void setRolls(UniformLootTableRange v) { + // checkFrozen(); + this.rollsRange = v; + } + + @Override + public void setBonusRolls(UniformLootTableRange v) { + // checkFrozen(); + this.bonusRollsRange = v; + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPoolBuilder.java b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPoolBuilder.java new file mode 100644 index 00000000..d2d2d8fc --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPoolBuilder.java @@ -0,0 +1,60 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.loot; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.loot.LootPool; +import net.minecraft.loot.UniformLootTableRange; + +import net.patchworkmc.api.loot.ForgeLootPool; +import net.patchworkmc.impl.loot.PatchworkLootPool; + +@Mixin(LootPool.Builder.class) +public abstract class MixinLootPoolBuilder implements ForgeLootPool.Builder { + @Unique + private String name; + + @Shadow + private UniformLootTableRange bonusRollsRange; + + @Inject(method = "build", at = @At("RETURN"), cancellable = true) + private void addNameToConstructor(CallbackInfoReturnable cir) { + LootPool ret = cir.getReturnValue(); + ((PatchworkLootPool) ret).patchwork$setName(name); + } + + @Override + public LootPool.Builder name(String name) { + this.name = name; + return (LootPool.Builder) (Object) this; + } + + @Override + public LootPool.Builder bonusRolls(float min, float max) { + this.bonusRollsRange = new UniformLootTableRange(min, max); + return (LootPool.Builder) (Object) this; + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPoolSerializer.java b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPoolSerializer.java new file mode 100644 index 00000000..5f57ca15 --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootPoolSerializer.java @@ -0,0 +1,64 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.loot; + +import java.lang.reflect.Type; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; + +import net.minecraft.loot.LootPool; + +import net.patchworkmc.api.loot.ForgeLootPool; +import net.patchworkmc.impl.loot.LootHooks; +import net.patchworkmc.impl.loot.PatchworkLootPool; + +@Mixin(LootPool.Serializer.class) +public class MixinLootPoolSerializer { + @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) + private void addNameToConstructor(JsonElement elem, Type ty, JsonDeserializationContext ctx, CallbackInfoReturnable cir, JsonObject obj) { + LootPool ret = cir.getReturnValue(); + ((PatchworkLootPool) ret).patchwork$setName(LootHooks.readPoolName(obj)); + + // is this necessary? + cir.setReturnValue(ret); + } + + @Redirect(method = "serialize", at = @At(value = "NEW", args = "class=com/google/gson/JsonObject")) + private static JsonObject serializeName(LootPool pool, Type type, JsonSerializationContext ctx) { + JsonObject ret = new JsonObject(); + + String name = ((ForgeLootPool) pool).getName(); + + if (name != null && !name.startsWith("custom#")) { + ret.add("name", ctx.serialize(name)); + } + + return ret; + } +} diff --git a/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootTable.java b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootTable.java new file mode 100644 index 00000000..346b04c3 --- /dev/null +++ b/patchwork-loot/src/main/java/net/patchworkmc/mixin/loot/MixinLootTable.java @@ -0,0 +1,75 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.loot; + +import java.util.Arrays; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.loot.LootPool; +import net.minecraft.loot.LootTable; + +import net.fabricmc.fabric.api.loot.v1.FabricLootSupplier; + +import net.patchworkmc.api.loot.ForgeLootTable; +import net.patchworkmc.api.loot.ForgeLootPool; + +@Mixin(LootTable.class) +public class MixinLootTable implements ForgeLootTable { + @Shadow + LootPool[] pools; + + // Forge added methods + + // TODO: freezing stuff + + @Override + public LootPool getPool(String name) { + return ((FabricLootSupplier) this).getPools().stream().filter(e -> name.equals(((ForgeLootPool) e).getName())).findFirst().orElse(null); + } + + @Override + public LootPool removePool(String name) { + // checkFrozen(); + for (int idx = 0; idx < pools.length; ++idx) { + LootPool pool = pools[idx]; + + if (name.equals(((ForgeLootPool) pool).getName())) { + // https://stackoverflow.com/a/644764 + System.arraycopy(pools, idx + 1, pools, idx, pools.length - 1 - idx); + return pool; + } + } + + return null; + } + + @Override + public void addPool(LootPool pool) { + // checkFrozen(); + if (((FabricLootSupplier) this).getPools().stream().anyMatch(e -> e == pool || ((ForgeLootPool) e).getName().equals(((ForgeLootPool) pool).getName()))) { + throw new RuntimeException("Attempted to add a duplicate pool to loot table: " + ((ForgeLootPool) pool).getName()); + } + + pools = Arrays.copyOf(pools, pools.length + 1); + pools[pools.length - 1] = pool; + } +} diff --git a/patchwork-loot/src/main/resources/patchwork-loot.mixins.json b/patchwork-loot/src/main/resources/patchwork-loot.mixins.json index 137951b0..4cedf63b 100644 --- a/patchwork-loot/src/main/resources/patchwork-loot.mixins.json +++ b/patchwork-loot/src/main/resources/patchwork-loot.mixins.json @@ -5,7 +5,13 @@ "mixins": [ "MixinAdvancementRewards", "MixinFishingBobberEntity", - "MixinLootContextTypes" + "MixinJsonDataLoader", + "MixinLootContextTypes", + "MixinLootManager", + "MixinLootPool", + "MixinLootPoolBuilder", + "MixinLootPoolSerializer", + "MixinLootTable" ], "injectors": { "defaultRequire": 1 From 494fd271bd27556595545e4f34ecb013127701d3 Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Thu, 23 Jul 2020 16:27:17 -0400 Subject: [PATCH 09/73] Don't crash when a mods Block has a BlockEntity but doesn't extend BlockEntityProvider (#145) --- .../block/blockentity/MixinWorldChunk.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/blockentity/MixinWorldChunk.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/blockentity/MixinWorldChunk.java index 9c6b4246..875646e0 100644 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/blockentity/MixinWorldChunk.java +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/blockentity/MixinWorldChunk.java @@ -19,7 +19,11 @@ package net.patchworkmc.mixin.extensions.block.blockentity; +import javax.annotation.Nullable; + +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; @@ -36,6 +40,7 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.BlockView; +import net.minecraft.world.World; import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.WorldChunk; @@ -44,6 +49,17 @@ @Mixin(WorldChunk.class) public abstract class MixinWorldChunk { + @Shadow + @Nullable + public abstract BlockEntity getBlockEntity(BlockPos pos, WorldChunk.CreationType creationType); + + @Shadow + @Final + private World world; + + @Shadow + private volatile boolean shouldSave; + /** * @param blockState * @return the blockEntity created by IForgeBlock.createTileEntity(BlockState, World) @@ -155,4 +171,21 @@ private BlockEntity patchwork_setBlockState_createBlockEntity(BlockEntityProvide private Block patchwork_setBlockEntity_getBlock(BlockState blockState) { return BlockContext.hasBlockEntityBlockMarker(blockState); } + + // Workaround in setBlockState for Forge Blocks with BEs that don't extend BlockEntityProvider + @Inject(method = "setBlockState", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/WorldChunk;getBlockEntity(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/chunk/WorldChunk$CreationType;)Lnet/minecraft/block/entity/BlockEntity;", ordinal = 1, shift = At.Shift.AFTER), cancellable = true) + private void postGetBlockEntity(BlockPos pos, BlockState state, boolean bl, CallbackInfoReturnable cir) { + if (!(state.getBlock() instanceof BlockEntityProvider)) { + BlockEntity blockEntity = getBlockEntity(pos, WorldChunk.CreationType.CHECK); + + if (blockEntity == null) { + IForgeBlockState forgeBlockState = (IForgeBlockState) state; + BlockEntity tileEntity = forgeBlockState.createTileEntity(world); + world.setBlockEntity(pos, tileEntity); + + this.shouldSave = true; + cir.setReturnValue(state); + } + } + } } From 14ecc17fc71e643bf5378697032defe40f486ad3 Mon Sep 17 00:00:00 2001 From: Gamma Whiskey <20158146+GammaWhiskey@users.noreply.github.com> Date: Fri, 24 Jul 2020 18:41:19 -0400 Subject: [PATCH 10/73] Add BlockEvent.HarvestDropsEvent and its respective firing method, WorldEvents.fireBlockHarvesting --- .../event/world/BlockEvent.java | 54 +++++++++++++++++++ .../impl/event/world/WorldEvents.java | 13 +++++ patchwork-god-classes/build.gradle | 1 + .../event/ForgeEventFactory.java | 9 ++++ 4 files changed, 77 insertions(+) diff --git a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java index 13ccffd6..c18bfd21 100644 --- a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java +++ b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java @@ -19,8 +19,12 @@ package net.minecraftforge.event.world; +import java.util.List; + import net.minecraftforge.eventbus.api.Event; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DefaultedList; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.BlockPos; @@ -109,4 +113,54 @@ public boolean isCancelable() { return true; } } + + /** + * Fired when a block is about to drop it's harvested items. The {@link #drops} array can be amended, as can the {@link #dropChance}. + * Note well: the {@link #harvester} player field is null in a variety of scenarios. Code expecting null. + * + *

The {@link #dropChance} is used to determine which items in this array will actually drop, compared to a random number. If you wish, you + * can pre-filter yourself, and set {@link #dropChance} to 1.0f to always drop the contents of the {@link #drops} array. + * + *

{@link #isSilkTouching} is set if this is considered a silk touch harvesting operation, vs a normal harvesting operation. Act accordingly. + */ + public static class HarvestDropsEvent extends BlockEvent { + private final int fortuneLevel; + private final DefaultedList drops; + private final boolean isSilkTouching; + private final PlayerEntity harvester; // May be null for non-player harvesting such as explosions or machines + private float dropChance; // Change to e.g. 1.0f, if you manipulate the list and want to guarantee it always drops + + public HarvestDropsEvent(World world, BlockPos pos, BlockState state, int fortuneLevel, float dropChance, DefaultedList drops, PlayerEntity harvester, boolean isSilkTouching) { + super(world, pos, state); + this.fortuneLevel = fortuneLevel; + this.setDropChance(dropChance); + this.drops = drops; + this.isSilkTouching = isSilkTouching; + this.harvester = harvester; + } + + public int getFortuneLevel() { + return fortuneLevel; + } + + public List getDrops() { + return drops; + } + + public boolean isSilkTouching() { + return isSilkTouching; + } + + public float getDropChance() { + return dropChance; + } + + public void setDropChance(float dropChance) { + this.dropChance = dropChance; + } + + public PlayerEntity getHarvester() { + return harvester; + } + } } diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index 1ee82ef6..f79e4f95 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -23,8 +23,14 @@ import java.util.List; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.WorldEvent; +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DefaultedList; +import net.minecraft.world.World; import net.minecraft.entity.EntityCategory; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; @@ -57,4 +63,11 @@ public static void onWorldUnload(IWorld world) { public static void onWorldSave(IWorld world) { MinecraftForge.EVENT_BUS.post(new WorldEvent.Save(world)); } + + // TODO: Leaving this unimplemented is intentional. See: https://github.com/MinecraftForge/MinecraftForge/issues/5828 + public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { + BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(world, pos, state, fortune, dropChance, drops, player, silkTouch); + MinecraftForge.EVENT_BUS.post(event); + return event.getDropChance(); + } } diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index ad0f0d6a..a546e86f 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -7,5 +7,6 @@ dependencies { compile project(path: ':patchwork-events-entity', configuration: 'dev') compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') compile project(path: ':patchwork-events-rendering', configuration: 'dev') + compile project(path: ':patchwork-events-world', configuration: 'dev') compile project(path: ':patchwork-loot', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 665926e3..8709d6b5 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -34,10 +34,15 @@ import net.minecraft.world.IWorld; import net.minecraft.world.MobSpawnerLogic; import net.minecraft.world.World; +import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DefaultedList; +import net.minecraft.util.math.BlockPos; import net.patchworkmc.impl.capability.CapabilityEvents; import net.patchworkmc.impl.event.entity.EntityEvents; import net.patchworkmc.impl.event.loot.LootEvents; +import net.patchworkmc.impl.event.world.WorldEvents; /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. @@ -73,4 +78,8 @@ public static boolean doSpecialSpawn(MobEntity entity, World world, float x, flo public static LootTable loadLootTable(Identifier name, LootTable table, LootManager lootTableManager) { return LootEvents.loadLootTable(name, table, lootTableManager); } + + public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { + return WorldEvents.fireBlockHarvesting(drops, world, pos, state, fortune, dropChance, silkTouch, player); + } } From c801a94d16b30f9ec4648bf6dc80188c868d7b24 Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Fri, 24 Jul 2020 20:48:57 -0400 Subject: [PATCH 11/73] ForgeRegistryEntry>, not (#141) --- .../minecraftforge/registries/ForgeRegistryEntry.java | 2 +- .../impl/registries/ExtendedForgeRegistryEntry.java | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/patchwork-registries/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java b/patchwork-registries/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java index 6814059e..02ccfab0 100644 --- a/patchwork-registries/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java +++ b/patchwork-registries/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java @@ -21,7 +21,7 @@ import net.minecraft.util.Identifier; -public abstract class ForgeRegistryEntry implements IForgeRegistryEntry { +public abstract class ForgeRegistryEntry> implements IForgeRegistryEntry { private Identifier registryName; @Override diff --git a/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java b/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java index ec39a098..701faf59 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java @@ -24,8 +24,9 @@ import net.minecraft.util.Identifier; +@SuppressWarnings("unchecked") public interface ExtendedForgeRegistryEntry extends IForgeRegistryEntry { - default V setRegistryName(String full) { + default IForgeRegistryEntry setRegistryName(String full) { String activeNamespace = ModLoadingContext.get().getActiveNamespace(); if (activeNamespace == null || activeNamespace.equals("minecraft")) { @@ -44,10 +45,10 @@ default V setRegistryName(String full) { System.err.printf("Potentially Dangerous alternative prefix `%s` for name `%s`, expected `%s`. This could be a intended override, but in most cases indicates a broken mod.\n", identifier.getNamespace(), identifier.getPath(), activeNamespace); } - return this.setRegistryName(identifier); + return (IForgeRegistryEntry) this.setRegistryName(identifier); } - default V setRegistryName(String namespace, String name) { - return this.setRegistryName(new Identifier(namespace, name)); + default IForgeRegistryEntry setRegistryName(String namespace, String name) { + return (IForgeRegistryEntry) this.setRegistryName(new Identifier(namespace, name)); } } From 6180e4e86204c3a66a0f85727aac9ed300dfd8c6 Mon Sep 17 00:00:00 2001 From: Gamma Whiskey <20158146+GammaWhiskey@users.noreply.github.com> Date: Fri, 24 Jul 2020 20:52:23 -0400 Subject: [PATCH 12/73] Improve documentation --- .../main/java/net/minecraftforge/event/world/BlockEvent.java | 4 ++-- .../java/net/patchworkmc/impl/event/world/WorldEvents.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java index c18bfd21..57308dd5 100644 --- a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java +++ b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java @@ -119,9 +119,9 @@ public boolean isCancelable() { * Note well: the {@link #harvester} player field is null in a variety of scenarios. Code expecting null. * *

The {@link #dropChance} is used to determine which items in this array will actually drop, compared to a random number. If you wish, you - * can pre-filter yourself, and set {@link #dropChance} to 1.0f to always drop the contents of the {@link #drops} array. + * can pre-filter yourself, and set {@link #dropChance} to 1.0f to always drop the contents of the {@link #drops} array.

* - *

{@link #isSilkTouching} is set if this is considered a silk touch harvesting operation, vs a normal harvesting operation. Act accordingly. + *

{@link #isSilkTouching} is set if this is considered a silk touch harvesting operation, vs a normal harvesting operation. Act accordingly.

*/ public static class HarvestDropsEvent extends BlockEvent { private final int fortuneLevel; diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index f79e4f95..fb5b748d 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -64,7 +64,7 @@ public static void onWorldSave(IWorld world) { MinecraftForge.EVENT_BUS.post(new WorldEvent.Save(world)); } - // TODO: Leaving this unimplemented is intentional. See: https://github.com/MinecraftForge/MinecraftForge/issues/5828 + // TODO: Leaving this unfired is intentional. See: https://github.com/MinecraftForge/MinecraftForge/issues/5828 public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(world, pos, state, fortune, dropChance, drops, player, silkTouch); MinecraftForge.EVENT_BUS.post(event); From 0e22a5bc0033f5b14d6aa695b8a144faa399022c Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Fri, 24 Jul 2020 23:27:01 -0400 Subject: [PATCH 13/73] Use raw types to "hand erase" the generics (#151) --- .../impl/registries/ExtendedForgeRegistryEntry.java | 13 ++++++++----- .../patchworkmc/mixin/registries/MixinActivity.java | 7 ++++--- .../patchworkmc/mixin/registries/MixinBiome.java | 7 ++++--- .../mixin/registries/MixinBiomeSourceType.java | 7 ++++--- .../patchworkmc/mixin/registries/MixinBlock.java | 7 ++++--- .../mixin/registries/MixinBlockEntityType.java | 7 ++++--- .../patchworkmc/mixin/registries/MixinCarver.java | 7 ++++--- .../mixin/registries/MixinChunkGeneratorType.java | 7 ++++--- .../mixin/registries/MixinChunkStatus.java | 7 ++++--- .../mixin/registries/MixinContainerType.java | 7 ++++--- .../mixin/registries/MixinDecorator.java | 7 ++++--- .../mixin/registries/MixinEnchantment.java | 7 ++++--- .../mixin/registries/MixinEntityType.java | 7 ++++--- .../patchworkmc/mixin/registries/MixinFeature.java | 7 ++++--- .../patchworkmc/mixin/registries/MixinFluid.java | 7 ++++--- .../net/patchworkmc/mixin/registries/MixinItem.java | 7 ++++--- .../mixin/registries/MixinMemoryModuleType.java | 7 ++++--- .../mixin/registries/MixinPaintingMotive.java | 7 ++++--- .../mixin/registries/MixinParticleType.java | 7 ++++--- .../mixin/registries/MixinPointOfInterestType.java | 7 ++++--- .../patchworkmc/mixin/registries/MixinPotion.java | 7 ++++--- .../registries/MixinRecipeSerializerSubclass.java | 7 ++++--- .../patchworkmc/mixin/registries/MixinSchedule.java | 7 ++++--- .../mixin/registries/MixinSensorType.java | 7 ++++--- .../mixin/registries/MixinSoundEvent.java | 7 ++++--- .../patchworkmc/mixin/registries/MixinStatType.java | 7 ++++--- .../mixin/registries/MixinStatusEffect.java | 7 ++++--- .../mixin/registries/MixinSurfaceBuilder.java | 7 ++++--- .../mixin/registries/MixinVillagerProfession.java | 7 ++++--- 29 files changed, 120 insertions(+), 89 deletions(-) diff --git a/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java b/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java index 701faf59..606707c3 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/impl/registries/ExtendedForgeRegistryEntry.java @@ -25,8 +25,8 @@ import net.minecraft.util.Identifier; @SuppressWarnings("unchecked") -public interface ExtendedForgeRegistryEntry extends IForgeRegistryEntry { - default IForgeRegistryEntry setRegistryName(String full) { +public interface ExtendedForgeRegistryEntry> extends IForgeRegistryEntry { + default V setRegistryName(String full) { String activeNamespace = ModLoadingContext.get().getActiveNamespace(); if (activeNamespace == null || activeNamespace.equals("minecraft")) { @@ -45,10 +45,13 @@ default IForgeRegistryEntry setRegistryName(String full) { System.err.printf("Potentially Dangerous alternative prefix `%s` for name `%s`, expected `%s`. This could be a intended override, but in most cases indicates a broken mod.\n", identifier.getNamespace(), identifier.getPath(), activeNamespace); } - return (IForgeRegistryEntry) this.setRegistryName(identifier); + return this.setRegistryName(identifier); } - default IForgeRegistryEntry setRegistryName(String namespace, String name) { - return (IForgeRegistryEntry) this.setRegistryName(new Identifier(namespace, name)); + default V setRegistryName(String namespace, String name) { + return this.setRegistryName(new Identifier(namespace, name)); } + + @Override + V setRegistryName(Identifier name); } diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinActivity.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinActivity.java index f1df4619..9809b5f0 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinActivity.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinActivity.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Activity.class) -public class MixinActivity implements ExtendedForgeRegistryEntry { +public class MixinActivity implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Activity setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Activity) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiome.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiome.java index 36c5ac4d..8b36e4cd 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiome.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiome.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Biome.class) -public class MixinBiome implements ExtendedForgeRegistryEntry { +public class MixinBiome implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Biome setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Biome) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiomeSourceType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiomeSourceType.java index a2ae2f03..aa4c7147 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiomeSourceType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBiomeSourceType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(BiomeSourceType.class) -public class MixinBiomeSourceType implements ExtendedForgeRegistryEntry { +public class MixinBiomeSourceType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public BiomeSourceType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (BiomeSourceType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlock.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlock.java index 480317fd..40c7afa6 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlock.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlock.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Block.class) -public class MixinBlock implements ExtendedForgeRegistryEntry { +public class MixinBlock implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Block setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Block) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlockEntityType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlockEntityType.java index 949cd8cd..bd700b43 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlockEntityType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinBlockEntityType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(BlockEntityType.class) -public class MixinBlockEntityType implements ExtendedForgeRegistryEntry { +public class MixinBlockEntityType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public BlockEntityType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (BlockEntityType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinCarver.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinCarver.java index 2e926496..5494bcdd 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinCarver.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinCarver.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Carver.class) -public class MixinCarver implements ExtendedForgeRegistryEntry { +public class MixinCarver implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Carver setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Carver) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkGeneratorType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkGeneratorType.java index f960679d..0e5653d5 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkGeneratorType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkGeneratorType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(ChunkGeneratorType.class) -public class MixinChunkGeneratorType implements ExtendedForgeRegistryEntry { +public class MixinChunkGeneratorType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public ChunkGeneratorType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (ChunkGeneratorType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkStatus.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkStatus.java index 7442a210..c486f7bf 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkStatus.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinChunkStatus.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(ChunkStatus.class) -public class MixinChunkStatus implements ExtendedForgeRegistryEntry { +public class MixinChunkStatus implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public ChunkStatus setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (ChunkStatus) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinContainerType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinContainerType.java index 5b3299fb..470a8909 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinContainerType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinContainerType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(ContainerType.class) -public class MixinContainerType implements ExtendedForgeRegistryEntry { +public class MixinContainerType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public ContainerType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (ContainerType) (Object) this; + return (IForgeRegistryEntry) this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinDecorator.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinDecorator.java index 9f9150ee..8a39e72e 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinDecorator.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinDecorator.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Decorator.class) -public class MixinDecorator implements ExtendedForgeRegistryEntry { +public class MixinDecorator implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Decorator setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Decorator) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEnchantment.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEnchantment.java index 7f9fc065..78457365 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEnchantment.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEnchantment.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Enchantment.class) -public class MixinEnchantment implements ExtendedForgeRegistryEntry { +public class MixinEnchantment implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Enchantment setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Enchantment) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEntityType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEntityType.java index 347d7c1e..5576cc1c 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEntityType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinEntityType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(EntityType.class) -public class MixinEntityType implements ExtendedForgeRegistryEntry { +public class MixinEntityType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public EntityType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (EntityType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFeature.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFeature.java index 00c88677..f883d181 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFeature.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFeature.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Feature.class) -public class MixinFeature implements ExtendedForgeRegistryEntry { +public class MixinFeature implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Feature setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Feature) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFluid.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFluid.java index 4588fed4..1526f58e 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFluid.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinFluid.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Fluid.class) -public class MixinFluid implements ExtendedForgeRegistryEntry { +public class MixinFluid implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Fluid setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Fluid) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinItem.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinItem.java index 5802f540..360ef3d7 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinItem.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinItem.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Item.class) -public class MixinItem implements ExtendedForgeRegistryEntry { +public class MixinItem implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Item setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Item) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinMemoryModuleType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinMemoryModuleType.java index 3d49ee57..798d7edc 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinMemoryModuleType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinMemoryModuleType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(MemoryModuleType.class) -public class MixinMemoryModuleType implements ExtendedForgeRegistryEntry { +public class MixinMemoryModuleType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public MemoryModuleType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (MemoryModuleType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPaintingMotive.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPaintingMotive.java index bb87d853..0beabe8d 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPaintingMotive.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPaintingMotive.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(PaintingMotive.class) -public class MixinPaintingMotive implements ExtendedForgeRegistryEntry { +public class MixinPaintingMotive implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public PaintingMotive setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (PaintingMotive) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinParticleType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinParticleType.java index 1f2d2322..dbadd769 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinParticleType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinParticleType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(ParticleType.class) -public class MixinParticleType implements ExtendedForgeRegistryEntry { +public class MixinParticleType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public ParticleType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (ParticleType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPointOfInterestType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPointOfInterestType.java index b139b7cf..2dda47a6 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPointOfInterestType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPointOfInterestType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(PointOfInterestType.class) -public class MixinPointOfInterestType implements ExtendedForgeRegistryEntry { +public class MixinPointOfInterestType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public PointOfInterestType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (PointOfInterestType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPotion.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPotion.java index dabac439..ae19f7e8 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPotion.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinPotion.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Potion.class) -public class MixinPotion implements ExtendedForgeRegistryEntry { +public class MixinPotion implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Potion setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Potion) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinRecipeSerializerSubclass.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinRecipeSerializerSubclass.java index 17c7ac4c..2efd2ec6 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinRecipeSerializerSubclass.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinRecipeSerializerSubclass.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -35,15 +36,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin({ShapedRecipe.Serializer.class, ShapelessRecipe.Serializer.class, CookingRecipeSerializer.class, CuttingRecipe.Serializer.class, SpecialRecipeSerializer.class}) -public class MixinRecipeSerializerSubclass implements ExtendedForgeRegistryEntry { +public class MixinRecipeSerializerSubclass implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public RecipeSerializer setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (RecipeSerializer) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSchedule.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSchedule.java index 3118df0f..e2ace86b 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSchedule.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSchedule.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(Schedule.class) -public class MixinSchedule implements ExtendedForgeRegistryEntry { +public class MixinSchedule implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public Schedule setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (Schedule) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSensorType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSensorType.java index 371b7d75..133ffef8 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSensorType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSensorType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(SensorType.class) -public class MixinSensorType implements ExtendedForgeRegistryEntry { +public class MixinSensorType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public SensorType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (SensorType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSoundEvent.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSoundEvent.java index 355e93f6..1013b038 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSoundEvent.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSoundEvent.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(SoundEvent.class) -public class MixinSoundEvent implements ExtendedForgeRegistryEntry { +public class MixinSoundEvent implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public SoundEvent setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (SoundEvent) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatType.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatType.java index d6f8838d..db14387a 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatType.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatType.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(StatType.class) -public class MixinStatType implements ExtendedForgeRegistryEntry { +public class MixinStatType implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public StatType setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (StatType) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatusEffect.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatusEffect.java index 074e5fc0..1156d377 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatusEffect.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinStatusEffect.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(StatusEffect.class) -public class MixinStatusEffect implements ExtendedForgeRegistryEntry { +public class MixinStatusEffect implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public StatusEffect setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (StatusEffect) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSurfaceBuilder.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSurfaceBuilder.java index 7b6e7e79..d96c5398 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSurfaceBuilder.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinSurfaceBuilder.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(SurfaceBuilder.class) -public class MixinSurfaceBuilder implements ExtendedForgeRegistryEntry { +public class MixinSurfaceBuilder implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public SurfaceBuilder setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (SurfaceBuilder) (Object) this; + return this; } public Identifier getRegistryName() { diff --git a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinVillagerProfession.java b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinVillagerProfession.java index d3c8bbcb..cbc79c91 100644 --- a/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinVillagerProfession.java +++ b/patchwork-registries/src/main/java/net/patchworkmc/mixin/registries/MixinVillagerProfession.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.registries; +import net.minecraftforge.registries.IForgeRegistryEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -30,15 +31,15 @@ import net.patchworkmc.impl.registries.Identifiers; @Mixin(VillagerProfession.class) -public class MixinVillagerProfession implements ExtendedForgeRegistryEntry { +public class MixinVillagerProfession implements ExtendedForgeRegistryEntry { @Unique private Identifier registryName; @Override - public VillagerProfession setRegistryName(Identifier name) { + public IForgeRegistryEntry setRegistryName(Identifier name) { this.registryName = name; - return (VillagerProfession) (Object) this; + return this; } public Identifier getRegistryName() { From 8530df3f474e8b8793a637d0db263fade672372c Mon Sep 17 00:00:00 2001 From: Kitlith Date: Sun, 26 Jul 2020 14:00:42 -0700 Subject: [PATCH 14/73] Use Fabric's world load event. (#149) * Use World Load event in fabric api introduced by 0.15.0 * Workaround: Fire overworld load event later * Add dep on fabric api to patchwork-events-world. TODO: we should go through and accurately state our fabric api dependencies for all modules. --- build.gradle | 2 +- .../impl/event/world/WorldEvents.java | 17 +++++++- .../event/world/MixinMinecraftServer.java | 43 +++---------------- .../src/main/resources/fabric.mod.json | 1 + 4 files changed, 24 insertions(+), 39 deletions(-) diff --git a/build.gradle b/build.gradle index 93e6c227..8896a885 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ allprojects { minecraft "com.mojang:minecraft:$Globals.mcVersion" mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}:v2" modCompile "net.fabricmc:fabric-loader:0.8.4+build.198" - modCompile "net.fabricmc.fabric-api:fabric-api:0.4.2+build.246-1.14" + modCompile "net.fabricmc.fabric-api:fabric-api:0.15.1+build.260-1.14" implementation 'net.patchworkmc:patchwork-eventbus:2.0.1:all' implementation 'com.google.code.findbugs:jsr305:3.0.2' diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index 1ee82ef6..19b8d250 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -29,9 +29,13 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; +import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.level.LevelInfo; -public class WorldEvents { +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; + +public class WorldEvents implements ModInitializer { public static boolean onCreateWorldSpawn(IWorld world, LevelInfo settings) { return MinecraftForge.EVENT_BUS.post(new WorldEvent.CreateSpawnPosition(world, settings)); } @@ -57,4 +61,15 @@ public static void onWorldUnload(IWorld world) { public static void onWorldSave(IWorld world) { MinecraftForge.EVENT_BUS.post(new WorldEvent.Save(world)); } + + @Override + public void onInitialize() { + ServerWorldEvents.LOAD.register((server, world) -> { + // Fabric fires this much earlier than Forge does for the overworld + // So, we're going to manually fire it for the overworld. + if (world.getDimension().getType() != DimensionType.OVERWORLD) { + onWorldLoad(world); + } + }); + } } diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinMinecraftServer.java b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinMinecraftServer.java index f55dfcb0..45265395 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinMinecraftServer.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinMinecraftServer.java @@ -20,14 +20,15 @@ package net.patchworkmc.mixin.event.world; import java.io.IOException; -import java.util.Iterator; import java.util.Map; 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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerTask; @@ -47,42 +48,10 @@ public MixinMinecraftServer(String name) { @Final private Map worlds; - /* - // This is a variant of the world load hook that is less likely to break mods and more likely to break on updates. - // Should get called once per loop, regardless of which if branch it takes. - @Inject( - method = "createWorlds", - slice = @Slice( - from = @At(value = "INVOKE", target = "java/util/Iterator.hasNext ()Z") - ), - at = @At(value = "JUMP", opcode = Opcodes.GOTO), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void hookCreateWorlds(WorldSaveHandler worldSaveHandler, LevelProperties properties, LevelInfo levelInfo, WorldGenerationProgressListener worldGenerationProgressListener, CallbackInfo ci, ServerWorld serverWorld, ServerWorld serverWorld2, Iterator var7, DimensionType dimensionType) { - WorldEvents.onWorldLoad(this.worlds.get(dimensionType)); - } - - */ - - // This injection gets called at the beginning of each loop, and is used to special case the overworld dimension type. - @Redirect(method = "createWorlds", at = @At(value = "INVOKE", target = "java/util/Iterator.next ()Ljava/lang/Object;")) - private Object proxyNextWorldToSpecialCaseOverworld(Iterator iterator) { - DimensionType type = iterator.next(); - - if (type == DimensionType.OVERWORLD) { - WorldEvents.onWorldLoad(this.worlds.get(type)); - } - - return type; - } - - // This injection handles every other dimension type. - @Redirect(method = "createWorlds", at = @At(value = "INVOKE", target = "java/util/Map.put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 1)) - private Object proxyPutWorld(Map worlds, Object type, Object world) { - worlds.put(type, world); - WorldEvents.onWorldLoad((ServerWorld) world); - - return world; + // Fabric usually fires the event much earlier in the method, so this is just picking a point closer to when Forge would fire it. + @Inject(method = "createWorlds", at = @At(value = "INVOKE", target = "net/minecraft/world/dimension/DimensionType.getAll ()Ljava/lang/Iterable;")) + private void fireLoadForOverworld(CallbackInfo info) { + WorldEvents.onWorldLoad(worlds.get(DimensionType.OVERWORLD)); } @Redirect(method = "shutdown", at = @At(value = "INVOKE", target = "net/minecraft/server/world/ServerWorld.close ()V")) diff --git a/patchwork-events-world/src/main/resources/fabric.mod.json b/patchwork-events-world/src/main/resources/fabric.mod.json index d228f734..cd2c8b0d 100644 --- a/patchwork-events-world/src/main/resources/fabric.mod.json +++ b/patchwork-events-world/src/main/resources/fabric.mod.json @@ -14,6 +14,7 @@ ], "depends": { "fabricloader": ">=0.8.4", + "fabric": ">=0.15.0", "patchwork-fml": "*" }, "mixins": [ From a1cec722bb7713e23456251f4c678f3e436efc1a Mon Sep 17 00:00:00 2001 From: p0nki Date: Sun, 26 Jul 2020 14:05:06 -0700 Subject: [PATCH 15/73] Forge Tags (#153) * Add forge tag API support * Checkstyle * Fix license * Fixed accessWidener not found in fabric.mod.json issue * Use newlines at end of file * Fix more newlines Gotta take this low effort all the way to the max * Fix issues * Oh god I think I fucked up git Co-authored-by: Ramid Khan --- patchwork-tags/build.gradle | 6 + .../java/net/minecraftforge/common/Tags.java | 271 ++++++++++++++++++ .../resources/assets/patchwork-tags/icon.png | Bin 0 -> 22738 bytes .../data/forge/tags/blocks/chests.json | 8 + .../data/forge/tags/blocks/chests/ender.json | 6 + .../forge/tags/blocks/chests/trapped.json | 6 + .../data/forge/tags/blocks/chests/wooden.json | 7 + .../data/forge/tags/blocks/cobblestone.json | 8 + .../data/forge/tags/blocks/dirt.json | 8 + .../data/forge/tags/blocks/end_stones.json | 6 + .../data/forge/tags/blocks/fence_gates.json | 6 + .../forge/tags/blocks/fence_gates/wooden.json | 11 + .../data/forge/tags/blocks/fences.json | 7 + .../tags/blocks/fences/nether_brick.json | 6 + .../data/forge/tags/blocks/fences/wooden.json | 11 + .../data/forge/tags/blocks/glass.json | 7 + .../data/forge/tags/blocks/glass/black.json | 6 + .../data/forge/tags/blocks/glass/blue.json | 6 + .../data/forge/tags/blocks/glass/brown.json | 6 + .../forge/tags/blocks/glass/colorless.json | 6 + .../data/forge/tags/blocks/glass/cyan.json | 6 + .../data/forge/tags/blocks/glass/gray.json | 6 + .../data/forge/tags/blocks/glass/green.json | 6 + .../forge/tags/blocks/glass/light_blue.json | 6 + .../forge/tags/blocks/glass/light_gray.json | 6 + .../data/forge/tags/blocks/glass/lime.json | 6 + .../data/forge/tags/blocks/glass/magenta.json | 6 + .../data/forge/tags/blocks/glass/orange.json | 6 + .../data/forge/tags/blocks/glass/pink.json | 6 + .../data/forge/tags/blocks/glass/purple.json | 6 + .../data/forge/tags/blocks/glass/red.json | 6 + .../data/forge/tags/blocks/glass/white.json | 6 + .../data/forge/tags/blocks/glass/yellow.json | 6 + .../data/forge/tags/blocks/glass_panes.json | 7 + .../forge/tags/blocks/glass_panes/black.json | 6 + .../forge/tags/blocks/glass_panes/blue.json | 6 + .../forge/tags/blocks/glass_panes/brown.json | 6 + .../tags/blocks/glass_panes/colorless.json | 6 + .../forge/tags/blocks/glass_panes/cyan.json | 6 + .../forge/tags/blocks/glass_panes/gray.json | 6 + .../forge/tags/blocks/glass_panes/green.json | 6 + .../tags/blocks/glass_panes/light_blue.json | 6 + .../tags/blocks/glass_panes/light_gray.json | 6 + .../forge/tags/blocks/glass_panes/lime.json | 6 + .../tags/blocks/glass_panes/magenta.json | 6 + .../forge/tags/blocks/glass_panes/orange.json | 6 + .../forge/tags/blocks/glass_panes/pink.json | 6 + .../forge/tags/blocks/glass_panes/purple.json | 6 + .../forge/tags/blocks/glass_panes/red.json | 6 + .../forge/tags/blocks/glass_panes/white.json | 6 + .../forge/tags/blocks/glass_panes/yellow.json | 6 + .../data/forge/tags/blocks/gravel.json | 6 + .../data/forge/tags/blocks/netherrack.json | 6 + .../data/forge/tags/blocks/obsidian.json | 6 + .../data/forge/tags/blocks/ores.json | 13 + .../data/forge/tags/blocks/ores/coal.json | 6 + .../data/forge/tags/blocks/ores/diamond.json | 6 + .../data/forge/tags/blocks/ores/emerald.json | 6 + .../data/forge/tags/blocks/ores/gold.json | 6 + .../data/forge/tags/blocks/ores/iron.json | 6 + .../data/forge/tags/blocks/ores/lapis.json | 6 + .../data/forge/tags/blocks/ores/quartz.json | 6 + .../data/forge/tags/blocks/ores/redstone.json | 6 + .../data/forge/tags/blocks/sand.json | 7 + .../forge/tags/blocks/sand/colorless.json | 6 + .../data/forge/tags/blocks/sand/red.json | 6 + .../data/forge/tags/blocks/sandstone.json | 13 + .../data/forge/tags/blocks/stained_glass.json | 21 ++ .../tags/blocks/stained_glass_panes.json | 21 ++ .../data/forge/tags/blocks/stone.json | 13 + .../forge/tags/blocks/storage_blocks.json | 13 + .../tags/blocks/storage_blocks/coal.json | 6 + .../tags/blocks/storage_blocks/diamond.json | 6 + .../tags/blocks/storage_blocks/emerald.json | 6 + .../tags/blocks/storage_blocks/gold.json | 6 + .../tags/blocks/storage_blocks/iron.json | 6 + .../tags/blocks/storage_blocks/lapis.json | 6 + .../tags/blocks/storage_blocks/quartz.json | 6 + .../tags/blocks/storage_blocks/redstone.json | 6 + .../forge/tags/blocks/supports_beacon.json | 9 + .../forge/tags/blocks/supports_conduit.json | 9 + .../data/forge/tags/items/arrows.json | 8 + .../data/forge/tags/items/beacon_payment.json | 9 + .../data/forge/tags/items/bones.json | 6 + .../data/forge/tags/items/bookshelves.json | 6 + .../data/forge/tags/items/chests.json | 8 + .../data/forge/tags/items/chests/ender.json | 6 + .../data/forge/tags/items/chests/trapped.json | 6 + .../data/forge/tags/items/chests/wooden.json | 7 + .../data/forge/tags/items/cobblestone.json | 8 + .../data/forge/tags/items/crops.json | 10 + .../data/forge/tags/items/crops/beetroot.json | 6 + .../data/forge/tags/items/crops/carrot.json | 6 + .../forge/tags/items/crops/nether_wart.json | 6 + .../data/forge/tags/items/crops/potato.json | 6 + .../data/forge/tags/items/crops/wheat.json | 6 + .../data/forge/tags/items/dusts.json | 8 + .../forge/tags/items/dusts/glowstone.json | 6 + .../forge/tags/items/dusts/prismarine.json | 6 + .../data/forge/tags/items/dusts/redstone.json | 6 + .../resources/data/forge/tags/items/dyes.json | 21 ++ .../data/forge/tags/items/dyes/black.json | 6 + .../data/forge/tags/items/dyes/blue.json | 6 + .../data/forge/tags/items/dyes/brown.json | 6 + .../data/forge/tags/items/dyes/cyan.json | 6 + .../data/forge/tags/items/dyes/gray.json | 6 + .../data/forge/tags/items/dyes/green.json | 6 + .../forge/tags/items/dyes/light_blue.json | 6 + .../forge/tags/items/dyes/light_gray.json | 6 + .../data/forge/tags/items/dyes/lime.json | 6 + .../data/forge/tags/items/dyes/magenta.json | 6 + .../data/forge/tags/items/dyes/orange.json | 6 + .../data/forge/tags/items/dyes/pink.json | 6 + .../data/forge/tags/items/dyes/purple.json | 6 + .../data/forge/tags/items/dyes/red.json | 6 + .../data/forge/tags/items/dyes/white.json | 6 + .../data/forge/tags/items/dyes/yellow.json | 6 + .../resources/data/forge/tags/items/eggs.json | 6 + .../data/forge/tags/items/end_stones.json | 6 + .../data/forge/tags/items/ender_pearls.json | 6 + .../data/forge/tags/items/feathers.json | 6 + .../data/forge/tags/items/fence_gates.json | 6 + .../forge/tags/items/fence_gates/wooden.json | 11 + .../data/forge/tags/items/fences.json | 7 + .../forge/tags/items/fences/nether_brick.json | 6 + .../data/forge/tags/items/fences/wooden.json | 11 + .../resources/data/forge/tags/items/gems.json | 10 + .../data/forge/tags/items/gems/diamond.json | 6 + .../data/forge/tags/items/gems/emerald.json | 6 + .../data/forge/tags/items/gems/lapis.json | 6 + .../forge/tags/items/gems/prismarine.json | 6 + .../data/forge/tags/items/gems/quartz.json | 6 + .../data/forge/tags/items/glass.json | 7 + .../data/forge/tags/items/glass/black.json | 6 + .../data/forge/tags/items/glass/blue.json | 6 + .../data/forge/tags/items/glass/brown.json | 6 + .../forge/tags/items/glass/colorless.json | 6 + .../data/forge/tags/items/glass/cyan.json | 6 + .../data/forge/tags/items/glass/gray.json | 6 + .../data/forge/tags/items/glass/green.json | 6 + .../forge/tags/items/glass/light_blue.json | 6 + .../forge/tags/items/glass/light_gray.json | 6 + .../data/forge/tags/items/glass/lime.json | 6 + .../data/forge/tags/items/glass/magenta.json | 6 + .../data/forge/tags/items/glass/orange.json | 6 + .../data/forge/tags/items/glass/pink.json | 6 + .../data/forge/tags/items/glass/purple.json | 6 + .../data/forge/tags/items/glass/red.json | 6 + .../data/forge/tags/items/glass/white.json | 6 + .../data/forge/tags/items/glass/yellow.json | 6 + .../data/forge/tags/items/glass_panes.json | 7 + .../forge/tags/items/glass_panes/black.json | 6 + .../forge/tags/items/glass_panes/blue.json | 6 + .../forge/tags/items/glass_panes/brown.json | 6 + .../tags/items/glass_panes/colorless.json | 6 + .../forge/tags/items/glass_panes/cyan.json | 6 + .../forge/tags/items/glass_panes/gray.json | 6 + .../forge/tags/items/glass_panes/green.json | 6 + .../tags/items/glass_panes/light_blue.json | 6 + .../tags/items/glass_panes/light_gray.json | 6 + .../forge/tags/items/glass_panes/lime.json | 6 + .../forge/tags/items/glass_panes/magenta.json | 6 + .../forge/tags/items/glass_panes/orange.json | 6 + .../forge/tags/items/glass_panes/pink.json | 6 + .../forge/tags/items/glass_panes/purple.json | 6 + .../forge/tags/items/glass_panes/red.json | 6 + .../forge/tags/items/glass_panes/white.json | 6 + .../forge/tags/items/glass_panes/yellow.json | 6 + .../data/forge/tags/items/gravel.json | 6 + .../data/forge/tags/items/gunpowder.json | 6 + .../data/forge/tags/items/heads.json | 11 + .../data/forge/tags/items/ingots.json | 9 + .../data/forge/tags/items/ingots/brick.json | 6 + .../data/forge/tags/items/ingots/gold.json | 6 + .../data/forge/tags/items/ingots/iron.json | 6 + .../forge/tags/items/ingots/nether_brick.json | 6 + .../data/forge/tags/items/leather.json | 6 + .../data/forge/tags/items/mushrooms.json | 7 + .../data/forge/tags/items/music_discs.json | 17 ++ .../data/forge/tags/items/nether_stars.json | 6 + .../data/forge/tags/items/netherrack.json | 6 + .../data/forge/tags/items/nuggets.json | 7 + .../data/forge/tags/items/nuggets/gold.json | 6 + .../data/forge/tags/items/nuggets/iron.json | 6 + .../data/forge/tags/items/obsidian.json | 6 + .../resources/data/forge/tags/items/ores.json | 13 + .../data/forge/tags/items/ores/coal.json | 6 + .../data/forge/tags/items/ores/diamond.json | 6 + .../data/forge/tags/items/ores/emerald.json | 6 + .../data/forge/tags/items/ores/gold.json | 6 + .../data/forge/tags/items/ores/iron.json | 6 + .../data/forge/tags/items/ores/lapis.json | 6 + .../data/forge/tags/items/ores/quartz.json | 6 + .../data/forge/tags/items/ores/redstone.json | 6 + .../resources/data/forge/tags/items/rods.json | 7 + .../data/forge/tags/items/rods/blaze.json | 6 + .../data/forge/tags/items/rods/wooden.json | 6 + .../resources/data/forge/tags/items/sand.json | 7 + .../data/forge/tags/items/sand/colorless.json | 6 + .../data/forge/tags/items/sand/red.json | 6 + .../data/forge/tags/items/sandstone.json | 13 + .../data/forge/tags/items/seeds.json | 9 + .../data/forge/tags/items/seeds/beetroot.json | 6 + .../data/forge/tags/items/seeds/melon.json | 6 + .../data/forge/tags/items/seeds/pumpkin.json | 6 + .../data/forge/tags/items/seeds/wheat.json | 6 + .../data/forge/tags/items/slimeballs.json | 6 + .../data/forge/tags/items/stained_glass.json | 21 ++ .../forge/tags/items/stained_glass_panes.json | 21 ++ .../data/forge/tags/items/stone.json | 13 + .../data/forge/tags/items/storage_blocks.json | 13 + .../forge/tags/items/storage_blocks/coal.json | 6 + .../tags/items/storage_blocks/diamond.json | 6 + .../tags/items/storage_blocks/emerald.json | 6 + .../forge/tags/items/storage_blocks/gold.json | 6 + .../forge/tags/items/storage_blocks/iron.json | 6 + .../tags/items/storage_blocks/lapis.json | 6 + .../tags/items/storage_blocks/quartz.json | 6 + .../tags/items/storage_blocks/redstone.json | 6 + .../data/forge/tags/items/string.json | 6 + .../forge/tags/items/supports_beacon.json | 9 + .../forge/tags/items/supports_conduit.json | 9 + .../src/main/resources/fabric.mod.json | 24 ++ .../resources/patchwork-tags.accesswidener | 3 + settings.gradle | 1 + 225 files changed, 1842 insertions(+) create mode 100644 patchwork-tags/build.gradle create mode 100644 patchwork-tags/src/main/java/net/minecraftforge/common/Tags.java create mode 100644 patchwork-tags/src/main/resources/assets/patchwork-tags/icon.png create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/chests.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/ender.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/trapped.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/wooden.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/cobblestone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/dirt.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/end_stones.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/fence_gates.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/fence_gates/wooden.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/fences.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/fences/nether_brick.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/fences/wooden.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/black.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/brown.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/colorless.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/cyan.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/green.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/light_blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/light_gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/lime.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/magenta.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/orange.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/pink.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/purple.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/red.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/white.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/yellow.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/black.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/brown.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/colorless.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/cyan.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/green.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/light_blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/light_gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/lime.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/magenta.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/orange.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/pink.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/purple.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/red.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/white.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/yellow.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/gravel.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/netherrack.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/obsidian.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/coal.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/diamond.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/emerald.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/gold.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/iron.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/lapis.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/quartz.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/redstone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/sand.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/sand/colorless.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/sand/red.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/sandstone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/stained_glass.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/stained_glass_panes.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/stone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/coal.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/diamond.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/emerald.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/gold.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/iron.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/lapis.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/quartz.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/redstone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/supports_beacon.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/blocks/supports_conduit.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/arrows.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/beacon_payment.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/bones.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/bookshelves.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/chests.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/chests/ender.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/chests/trapped.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/chests/wooden.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/cobblestone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/crops.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/crops/beetroot.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/crops/carrot.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/crops/nether_wart.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/crops/potato.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/crops/wheat.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dusts.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dusts/glowstone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dusts/prismarine.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dusts/redstone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/black.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/brown.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/cyan.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/green.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/light_blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/light_gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/lime.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/magenta.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/orange.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/pink.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/purple.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/red.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/white.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/dyes/yellow.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/eggs.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/end_stones.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ender_pearls.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/feathers.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/fence_gates.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/fence_gates/wooden.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/fences.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/fences/nether_brick.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/fences/wooden.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/gems.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/gems/diamond.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/gems/emerald.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/gems/lapis.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/gems/prismarine.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/gems/quartz.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/black.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/brown.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/colorless.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/cyan.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/green.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/light_blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/light_gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/lime.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/magenta.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/orange.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/pink.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/purple.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/red.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/white.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass/yellow.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/black.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/brown.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/colorless.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/cyan.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/green.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/light_blue.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/light_gray.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/lime.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/magenta.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/orange.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/pink.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/purple.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/red.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/white.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/yellow.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/gravel.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/gunpowder.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/heads.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ingots.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ingots/brick.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ingots/gold.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ingots/iron.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ingots/nether_brick.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/leather.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/mushrooms.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/music_discs.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/nether_stars.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/netherrack.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/nuggets.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/nuggets/gold.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/nuggets/iron.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/obsidian.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores/coal.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores/diamond.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores/emerald.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores/gold.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores/iron.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores/lapis.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores/quartz.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/ores/redstone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/rods.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/rods/blaze.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/rods/wooden.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/sand.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/sand/colorless.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/sand/red.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/sandstone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/seeds.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/seeds/beetroot.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/seeds/melon.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/seeds/pumpkin.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/seeds/wheat.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/slimeballs.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/stained_glass.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/stained_glass_panes.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/stone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/coal.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/diamond.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/emerald.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/gold.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/iron.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/lapis.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/quartz.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/redstone.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/string.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/supports_beacon.json create mode 100644 patchwork-tags/src/main/resources/data/forge/tags/items/supports_conduit.json create mode 100644 patchwork-tags/src/main/resources/fabric.mod.json create mode 100644 patchwork-tags/src/main/resources/patchwork-tags.accesswidener diff --git a/patchwork-tags/build.gradle b/patchwork-tags/build.gradle new file mode 100644 index 00000000..808194bb --- /dev/null +++ b/patchwork-tags/build.gradle @@ -0,0 +1,6 @@ +archivesBaseName = "patchwork-tags" +version = getSubprojectVersion(project, "0.1.0") + +minecraft { + accessWidener "src/main/resources/patchwork-tags.accesswidener" +} diff --git a/patchwork-tags/src/main/java/net/minecraftforge/common/Tags.java b/patchwork-tags/src/main/java/net/minecraftforge/common/Tags.java new file mode 100644 index 00000000..23309457 --- /dev/null +++ b/patchwork-tags/src/main/java/net/minecraftforge/common/Tags.java @@ -0,0 +1,271 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.common; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.tag.BlockTags; +import net.minecraft.tag.ItemTags; +import net.minecraft.tag.Tag; +import net.minecraft.util.Identifier; + +// Yoinked directly from forge +public class Tags { + public static class Blocks { + public static final Tag CHESTS = tag("chests"); + public static final Tag CHESTS_ENDER = tag("chests/ender"); + public static final Tag CHESTS_TRAPPED = tag("chests/trapped"); + public static final Tag CHESTS_WOODEN = tag("chests/wooden"); + public static final Tag COBBLESTONE = tag("cobblestone"); + public static final Tag DIRT = tag("dirt"); + public static final Tag END_STONES = tag("end_stones"); + public static final Tag FENCE_GATES = tag("fence_gates"); + public static final Tag FENCE_GATES_WOODEN = tag("fence_gates/wooden"); + public static final Tag FENCES = tag("fences"); + public static final Tag FENCES_NETHER_BRICK = tag("fences/nether_brick"); + public static final Tag FENCES_WOODEN = tag("fences/wooden"); + + public static final Tag GLASS = tag("glass"); + public static final Tag GLASS_BLACK = tag("glass/black"); + public static final Tag GLASS_BLUE = tag("glass/blue"); + public static final Tag GLASS_BROWN = tag("glass/brown"); + public static final Tag GLASS_COLORLESS = tag("glass/colorless"); + public static final Tag GLASS_CYAN = tag("glass/cyan"); + public static final Tag GLASS_GRAY = tag("glass/gray"); + public static final Tag GLASS_GREEN = tag("glass/green"); + public static final Tag GLASS_LIGHT_BLUE = tag("glass/light_blue"); + public static final Tag GLASS_LIGHT_GRAY = tag("glass/light_gray"); + public static final Tag GLASS_LIME = tag("glass/lime"); + public static final Tag GLASS_MAGENTA = tag("glass/magenta"); + public static final Tag GLASS_ORANGE = tag("glass/orange"); + public static final Tag GLASS_PINK = tag("glass/pink"); + public static final Tag GLASS_PURPLE = tag("glass/purple"); + public static final Tag GLASS_RED = tag("glass/red"); + public static final Tag GLASS_WHITE = tag("glass/white"); + public static final Tag GLASS_YELLOW = tag("glass/yellow"); + + public static final Tag GLASS_PANES = tag("glass_panes"); + public static final Tag GLASS_PANES_BLACK = tag("glass_panes/black"); + public static final Tag GLASS_PANES_BLUE = tag("glass_panes/blue"); + public static final Tag GLASS_PANES_BROWN = tag("glass_panes/brown"); + public static final Tag GLASS_PANES_COLORLESS = tag("glass_panes/colorless"); + public static final Tag GLASS_PANES_CYAN = tag("glass_panes/cyan"); + public static final Tag GLASS_PANES_GRAY = tag("glass_panes/gray"); + public static final Tag GLASS_PANES_GREEN = tag("glass_panes/green"); + public static final Tag GLASS_PANES_LIGHT_BLUE = tag("glass_panes/light_blue"); + public static final Tag GLASS_PANES_LIGHT_GRAY = tag("glass_panes/light_gray"); + public static final Tag GLASS_PANES_LIME = tag("glass_panes/lime"); + public static final Tag GLASS_PANES_MAGENTA = tag("glass_panes/magenta"); + public static final Tag GLASS_PANES_ORANGE = tag("glass_panes/orange"); + public static final Tag GLASS_PANES_PINK = tag("glass_panes/pink"); + public static final Tag GLASS_PANES_PURPLE = tag("glass_panes/purple"); + public static final Tag GLASS_PANES_RED = tag("glass_panes/red"); + public static final Tag GLASS_PANES_WHITE = tag("glass_panes/white"); + public static final Tag GLASS_PANES_YELLOW = tag("glass_panes/yellow"); + + public static final Tag GRAVEL = tag("gravel"); + public static final Tag NETHERRACK = tag("netherrack"); + public static final Tag OBSIDIAN = tag("obsidian"); + public static final Tag ORES = tag("ores"); + public static final Tag ORES_COAL = tag("ores/coal"); + public static final Tag ORES_DIAMOND = tag("ores/diamond"); + public static final Tag ORES_EMERALD = tag("ores/emerald"); + public static final Tag ORES_GOLD = tag("ores/gold"); + public static final Tag ORES_IRON = tag("ores/iron"); + public static final Tag ORES_LAPIS = tag("ores/lapis"); + public static final Tag ORES_QUARTZ = tag("ores/quartz"); + public static final Tag ORES_REDSTONE = tag("ores/redstone"); + + public static final Tag SAND = tag("sand"); + public static final Tag SAND_COLORLESS = tag("sand/colorless"); + public static final Tag SAND_RED = tag("sand/red"); + + public static final Tag SANDSTONE = tag("sandstone"); + public static final Tag STAINED_GLASS = tag("stained_glass"); + public static final Tag STAINED_GLASS_PANES = tag("stained_glass_panes"); + public static final Tag STONE = tag("stone"); + public static final Tag STORAGE_BLOCKS = tag("storage_blocks"); + public static final Tag STORAGE_BLOCKS_COAL = tag("storage_blocks/coal"); + public static final Tag STORAGE_BLOCKS_DIAMOND = tag("storage_blocks/diamond"); + public static final Tag STORAGE_BLOCKS_EMERALD = tag("storage_blocks/emerald"); + public static final Tag STORAGE_BLOCKS_GOLD = tag("storage_blocks/gold"); + public static final Tag STORAGE_BLOCKS_IRON = tag("storage_blocks/iron"); + public static final Tag STORAGE_BLOCKS_LAPIS = tag("storage_blocks/lapis"); + public static final Tag STORAGE_BLOCKS_QUARTZ = tag("storage_blocks/quartz"); + public static final Tag STORAGE_BLOCKS_REDSTONE = tag("storage_blocks/redstone"); + + private static Tag tag(String name) { + return new BlockTags.CachingTag(new Identifier("forge", name)); + } + } + + public static class Items { + public static final Tag ARROWS = tag("arrows"); + public static final Tag BEACON_PAYMENT = tag("beacon_payment"); + public static final Tag BONES = tag("bones"); + public static final Tag BOOKSHELVES = tag("bookshelves"); + public static final Tag CHESTS = tag("chests"); + public static final Tag CHESTS_ENDER = tag("chests/ender"); + public static final Tag CHESTS_TRAPPED = tag("chests/trapped"); + public static final Tag CHESTS_WOODEN = tag("chests/wooden"); + public static final Tag COBBLESTONE = tag("cobblestone"); + public static final Tag CROPS = tag("crops"); + public static final Tag CROPS_BEETROOT = tag("crops/beetroot"); + public static final Tag CROPS_CARROT = tag("crops/carrot"); + public static final Tag CROPS_NETHER_WART = tag("crops/nether_wart"); + public static final Tag CROPS_POTATO = tag("crops/potato"); + public static final Tag CROPS_WHEAT = tag("crops/wheat"); + public static final Tag DUSTS = tag("dusts"); + public static final Tag DUSTS_PRISMARINE = tag("dusts/prismarine"); + public static final Tag DUSTS_REDSTONE = tag("dusts/redstone"); + public static final Tag DUSTS_GLOWSTONE = tag("dusts/glowstone"); + + public static final Tag DYES = tag("dyes"); + public static final Tag DYES_BLACK = tag("dyes/black"); + public static final Tag DYES_RED = tag("dyes/red"); + public static final Tag DYES_GREEN = tag("dyes/green"); + public static final Tag DYES_BROWN = tag("dyes/brown"); + public static final Tag DYES_BLUE = tag("dyes/blue"); + public static final Tag DYES_PURPLE = tag("dyes/purple"); + public static final Tag DYES_CYAN = tag("dyes/cyan"); + public static final Tag DYES_LIGHT_GRAY = tag("dyes/light_gray"); + public static final Tag DYES_GRAY = tag("dyes/gray"); + public static final Tag DYES_PINK = tag("dyes/pink"); + public static final Tag DYES_LIME = tag("dyes/lime"); + public static final Tag DYES_YELLOW = tag("dyes/yellow"); + public static final Tag DYES_LIGHT_BLUE = tag("dyes/light_blue"); + public static final Tag DYES_MAGENTA = tag("dyes/magenta"); + public static final Tag DYES_ORANGE = tag("dyes/orange"); + public static final Tag DYES_WHITE = tag("dyes/white"); + + public static final Tag EGGS = tag("eggs"); + public static final Tag END_STONES = tag("end_stones"); + public static final Tag ENDER_PEARLS = tag("ender_pearls"); + public static final Tag FEATHERS = tag("feathers"); + public static final Tag FENCE_GATES = tag("fence_gates"); + public static final Tag FENCE_GATES_WOODEN = tag("fence_gates/wooden"); + public static final Tag FENCES = tag("fences"); + public static final Tag FENCES_NETHER_BRICK = tag("fences/nether_brick"); + public static final Tag FENCES_WOODEN = tag("fences/wooden"); + public static final Tag GEMS = tag("gems"); + public static final Tag GEMS_DIAMOND = tag("gems/diamond"); + public static final Tag GEMS_EMERALD = tag("gems/emerald"); + public static final Tag GEMS_LAPIS = tag("gems/lapis"); + public static final Tag GEMS_PRISMARINE = tag("gems/prismarine"); + public static final Tag GEMS_QUARTZ = tag("gems/quartz"); + + public static final Tag GLASS = tag("glass"); + public static final Tag GLASS_BLACK = tag("glass/black"); + public static final Tag GLASS_BLUE = tag("glass/blue"); + public static final Tag GLASS_BROWN = tag("glass/brown"); + public static final Tag GLASS_COLORLESS = tag("glass/colorless"); + public static final Tag GLASS_CYAN = tag("glass/cyan"); + public static final Tag GLASS_GRAY = tag("glass/gray"); + public static final Tag GLASS_GREEN = tag("glass/green"); + public static final Tag GLASS_LIGHT_BLUE = tag("glass/light_blue"); + public static final Tag GLASS_LIGHT_GRAY = tag("glass/light_gray"); + public static final Tag GLASS_LIME = tag("glass/lime"); + public static final Tag GLASS_MAGENTA = tag("glass/magenta"); + public static final Tag GLASS_ORANGE = tag("glass/orange"); + public static final Tag GLASS_PINK = tag("glass/pink"); + public static final Tag GLASS_PURPLE = tag("glass/purple"); + public static final Tag GLASS_RED = tag("glass/red"); + public static final Tag GLASS_WHITE = tag("glass/white"); + public static final Tag GLASS_YELLOW = tag("glass/yellow"); + + public static final Tag GLASS_PANES = tag("glass_panes"); + public static final Tag GLASS_PANES_BLACK = tag("glass_panes/black"); + public static final Tag GLASS_PANES_BLUE = tag("glass_panes/blue"); + public static final Tag GLASS_PANES_BROWN = tag("glass_panes/brown"); + public static final Tag GLASS_PANES_COLORLESS = tag("glass_panes/colorless"); + public static final Tag GLASS_PANES_CYAN = tag("glass_panes/cyan"); + public static final Tag GLASS_PANES_GRAY = tag("glass_panes/gray"); + public static final Tag GLASS_PANES_GREEN = tag("glass_panes/green"); + public static final Tag GLASS_PANES_LIGHT_BLUE = tag("glass_panes/light_blue"); + public static final Tag GLASS_PANES_LIGHT_GRAY = tag("glass_panes/light_gray"); + public static final Tag GLASS_PANES_LIME = tag("glass_panes/lime"); + public static final Tag GLASS_PANES_MAGENTA = tag("glass_panes/magenta"); + public static final Tag GLASS_PANES_ORANGE = tag("glass_panes/orange"); + public static final Tag GLASS_PANES_PINK = tag("glass_panes/pink"); + public static final Tag GLASS_PANES_PURPLE = tag("glass_panes/purple"); + public static final Tag GLASS_PANES_RED = tag("glass_panes/red"); + public static final Tag GLASS_PANES_WHITE = tag("glass_panes/white"); + public static final Tag GLASS_PANES_YELLOW = tag("glass_panes/yellow"); + + public static final Tag GRAVEL = tag("gravel"); + public static final Tag GUNPOWDER = tag("gunpowder"); + public static final Tag HEADS = tag("heads"); + public static final Tag INGOTS = tag("ingots"); + public static final Tag INGOTS_BRICK = tag("ingots/brick"); + public static final Tag INGOTS_GOLD = tag("ingots/gold"); + public static final Tag INGOTS_IRON = tag("ingots/iron"); + public static final Tag INGOTS_NETHER_BRICK = tag("ingots/nether_brick"); + public static final Tag LEATHER = tag("leather"); + public static final Tag MUSHROOMS = tag("mushrooms"); + public static final Tag MUSIC_DISCS = tag("music_discs"); + public static final Tag NETHER_STARS = tag("nether_stars"); + public static final Tag NETHERRACK = tag("netherrack"); + public static final Tag NUGGETS = tag("nuggets"); + public static final Tag NUGGETS_GOLD = tag("nuggets/gold"); + public static final Tag NUGGETS_IRON = tag("nuggets/iron"); + public static final Tag OBSIDIAN = tag("obsidian"); + public static final Tag ORES = tag("ores"); + public static final Tag ORES_COAL = tag("ores/coal"); + public static final Tag ORES_DIAMOND = tag("ores/diamond"); + public static final Tag ORES_EMERALD = tag("ores/emerald"); + public static final Tag ORES_GOLD = tag("ores/gold"); + public static final Tag ORES_IRON = tag("ores/iron"); + public static final Tag ORES_LAPIS = tag("ores/lapis"); + public static final Tag ORES_QUARTZ = tag("ores/quartz"); + public static final Tag ORES_REDSTONE = tag("ores/redstone"); + public static final Tag RODS = tag("rods"); + public static final Tag RODS_BLAZE = tag("rods/blaze"); + public static final Tag RODS_WOODEN = tag("rods/wooden"); + + public static final Tag SAND = tag("sand"); + public static final Tag SAND_COLORLESS = tag("sand/colorless"); + public static final Tag SAND_RED = tag("sand/red"); + + public static final Tag SANDSTONE = tag("sandstone"); + public static final Tag SEEDS = tag("seeds"); + public static final Tag SEEDS_BEETROOT = tag("seeds/beetroot"); + public static final Tag SEEDS_MELON = tag("seeds/melon"); + public static final Tag SEEDS_PUMPKIN = tag("seeds/pumpkin"); + public static final Tag SEEDS_WHEAT = tag("seeds/wheat"); + public static final Tag SLIMEBALLS = tag("slimeballs"); + public static final Tag STAINED_GLASS = tag("stained_glass"); + public static final Tag STAINED_GLASS_PANES = tag("stained_glass_panes"); + public static final Tag STONE = tag("stone"); + public static final Tag STORAGE_BLOCKS = tag("storage_blocks"); + public static final Tag STORAGE_BLOCKS_COAL = tag("storage_blocks/coal"); + public static final Tag STORAGE_BLOCKS_DIAMOND = tag("storage_blocks/diamond"); + public static final Tag STORAGE_BLOCKS_EMERALD = tag("storage_blocks/emerald"); + public static final Tag STORAGE_BLOCKS_GOLD = tag("storage_blocks/gold"); + public static final Tag STORAGE_BLOCKS_IRON = tag("storage_blocks/iron"); + public static final Tag STORAGE_BLOCKS_LAPIS = tag("storage_blocks/lapis"); + public static final Tag STORAGE_BLOCKS_QUARTZ = tag("storage_blocks/quartz"); + public static final Tag STORAGE_BLOCKS_REDSTONE = tag("storage_blocks/redstone"); + public static final Tag STRING = tag("string"); + + private static Tag tag(String name) { + return new ItemTags.CachingTag(new Identifier("forge", name)); + } + } +} diff --git a/patchwork-tags/src/main/resources/assets/patchwork-tags/icon.png b/patchwork-tags/src/main/resources/assets/patchwork-tags/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests.json new file mode 100644 index 00000000..5b2186a2 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "#forge:chests/ender", + "#forge:chests/trapped", + "#forge:chests/wooden" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/ender.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/ender.json new file mode 100644 index 00000000..d7a16e96 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/ender.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:ender_chest" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/trapped.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/trapped.json new file mode 100644 index 00000000..55c7aec1 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/trapped.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:trapped_chest" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/wooden.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/wooden.json new file mode 100644 index 00000000..46ff16fc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/chests/wooden.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "minecraft:chest", + "minecraft:trapped_chest" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/cobblestone.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/cobblestone.json new file mode 100644 index 00000000..a5c96d86 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/cobblestone.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "minecraft:cobblestone", + "minecraft:infested_cobblestone", + "minecraft:mossy_cobblestone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/dirt.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/dirt.json new file mode 100644 index 00000000..0e471849 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/dirt.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "minecraft:dirt", + "minecraft:coarse_dirt", + "minecraft:podzol" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/end_stones.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/end_stones.json new file mode 100644 index 00000000..6ed8faad --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/end_stones.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:end_stone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/fence_gates.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fence_gates.json new file mode 100644 index 00000000..4fc8670f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fence_gates.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#forge:fence_gates/wooden" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/fence_gates/wooden.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fence_gates/wooden.json new file mode 100644 index 00000000..7b803077 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fence_gates/wooden.json @@ -0,0 +1,11 @@ +{ + "replace": false, + "values": [ + "minecraft:oak_fence_gate", + "minecraft:spruce_fence_gate", + "minecraft:birch_fence_gate", + "minecraft:jungle_fence_gate", + "minecraft:acacia_fence_gate", + "minecraft:dark_oak_fence_gate" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences.json new file mode 100644 index 00000000..a7e4edcd --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:fences/nether_brick", + "#forge:fences/wooden" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences/nether_brick.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences/nether_brick.json new file mode 100644 index 00000000..49884116 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences/nether_brick.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:nether_brick_fence" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences/wooden.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences/wooden.json new file mode 100644 index 00000000..af77edde --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/fences/wooden.json @@ -0,0 +1,11 @@ +{ + "replace": false, + "values": [ + "minecraft:oak_fence", + "minecraft:spruce_fence", + "minecraft:birch_fence", + "minecraft:jungle_fence", + "minecraft:acacia_fence", + "minecraft:dark_oak_fence" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass.json new file mode 100644 index 00000000..6df0a8cb --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:glass/colorless", + "#forge:stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/black.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/black.json new file mode 100644 index 00000000..38eddb25 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/black.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:black_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/blue.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/blue.json new file mode 100644 index 00000000..5e20981a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:blue_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/brown.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/brown.json new file mode 100644 index 00000000..760da354 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/brown.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:brown_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/colorless.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/colorless.json new file mode 100644 index 00000000..8e580743 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/colorless.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/cyan.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/cyan.json new file mode 100644 index 00000000..75159cfc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/cyan.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:cyan_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/gray.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/gray.json new file mode 100644 index 00000000..7da37999 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gray_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/green.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/green.json new file mode 100644 index 00000000..88560a1b --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/green.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:green_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/light_blue.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/light_blue.json new file mode 100644 index 00000000..0cad485f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/light_blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_blue_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/light_gray.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/light_gray.json new file mode 100644 index 00000000..155b462b --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/light_gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_gray_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/lime.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/lime.json new file mode 100644 index 00000000..83f297e0 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/lime.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lime_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/magenta.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/magenta.json new file mode 100644 index 00000000..1a05a1a4 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/magenta.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:magenta_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/orange.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/orange.json new file mode 100644 index 00000000..dce95254 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/orange.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:orange_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/pink.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/pink.json new file mode 100644 index 00000000..736709fb --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/pink.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:pink_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/purple.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/purple.json new file mode 100644 index 00000000..25891652 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/purple.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:purple_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/red.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/red.json new file mode 100644 index 00000000..5b4e58b0 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/red.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:red_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/white.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/white.json new file mode 100644 index 00000000..7da94883 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/white.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:white_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/yellow.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/yellow.json new file mode 100644 index 00000000..45bb137b --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass/yellow.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:yellow_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes.json new file mode 100644 index 00000000..175f6a66 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:glass_panes/colorless", + "#forge:stained_glass_panes" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/black.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/black.json new file mode 100644 index 00000000..ab7ea540 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/black.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:black_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/blue.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/blue.json new file mode 100644 index 00000000..3e454494 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:blue_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/brown.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/brown.json new file mode 100644 index 00000000..b0fc36bb --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/brown.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:brown_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/colorless.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/colorless.json new file mode 100644 index 00000000..e312863d --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/colorless.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/cyan.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/cyan.json new file mode 100644 index 00000000..a50053ff --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/cyan.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:cyan_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/gray.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/gray.json new file mode 100644 index 00000000..4469029f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gray_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/green.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/green.json new file mode 100644 index 00000000..4a7ed223 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/green.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:green_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/light_blue.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/light_blue.json new file mode 100644 index 00000000..82605a7d --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/light_blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_blue_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/light_gray.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/light_gray.json new file mode 100644 index 00000000..267d4e6a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/light_gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_gray_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/lime.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/lime.json new file mode 100644 index 00000000..54389292 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/lime.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lime_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/magenta.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/magenta.json new file mode 100644 index 00000000..94c5d119 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/magenta.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:magenta_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/orange.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/orange.json new file mode 100644 index 00000000..c51a3f3e --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/orange.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:orange_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/pink.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/pink.json new file mode 100644 index 00000000..34085961 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/pink.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:pink_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/purple.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/purple.json new file mode 100644 index 00000000..5c9fe059 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/purple.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:purple_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/red.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/red.json new file mode 100644 index 00000000..11bca5b1 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/red.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:red_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/white.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/white.json new file mode 100644 index 00000000..9a2f1c27 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/white.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:white_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/yellow.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/yellow.json new file mode 100644 index 00000000..7fe639cc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/glass_panes/yellow.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:yellow_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/gravel.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/gravel.json new file mode 100644 index 00000000..47a682ab --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/gravel.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gravel" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/netherrack.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/netherrack.json new file mode 100644 index 00000000..9d430375 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/netherrack.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:netherrack" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/obsidian.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/obsidian.json new file mode 100644 index 00000000..129433a5 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/obsidian.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:obsidian" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores.json new file mode 100644 index 00000000..bc2cb711 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "#forge:ores/coal", + "#forge:ores/diamond", + "#forge:ores/emerald", + "#forge:ores/gold", + "#forge:ores/iron", + "#forge:ores/lapis", + "#forge:ores/redstone", + "#forge:ores/quartz" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/coal.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/coal.json new file mode 100644 index 00000000..7c71d780 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/coal.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:coal_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/diamond.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/diamond.json new file mode 100644 index 00000000..072563e4 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/diamond.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:diamond_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/emerald.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/emerald.json new file mode 100644 index 00000000..3972c84a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/emerald.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:emerald_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/gold.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/gold.json new file mode 100644 index 00000000..ebbc8168 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/gold.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gold_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/iron.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/iron.json new file mode 100644 index 00000000..dd2164d9 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/iron.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:iron_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/lapis.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/lapis.json new file mode 100644 index 00000000..68d1a961 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/lapis.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lapis_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/quartz.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/quartz.json new file mode 100644 index 00000000..46ba0451 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/quartz.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:nether_quartz_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/redstone.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/redstone.json new file mode 100644 index 00000000..c88b6802 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/ores/redstone.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:redstone_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand.json new file mode 100644 index 00000000..a011fb45 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:sand/colorless", + "#forge:sand/red" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand/colorless.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand/colorless.json new file mode 100644 index 00000000..78337d59 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand/colorless.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:sand" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand/red.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand/red.json new file mode 100644 index 00000000..5b5bbef0 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/sand/red.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:red_sand" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/sandstone.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/sandstone.json new file mode 100644 index 00000000..b497d97f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/sandstone.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "minecraft:sandstone", + "minecraft:cut_sandstone", + "minecraft:chiseled_sandstone", + "minecraft:smooth_sandstone", + "minecraft:red_sandstone", + "minecraft:cut_red_sandstone", + "minecraft:chiseled_red_sandstone", + "minecraft:smooth_red_sandstone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/stained_glass.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/stained_glass.json new file mode 100644 index 00000000..a36fc9bc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/stained_glass.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "minecraft:white_stained_glass", + "minecraft:orange_stained_glass", + "minecraft:magenta_stained_glass", + "minecraft:light_blue_stained_glass", + "minecraft:yellow_stained_glass", + "minecraft:lime_stained_glass", + "minecraft:pink_stained_glass", + "minecraft:gray_stained_glass", + "minecraft:light_gray_stained_glass", + "minecraft:cyan_stained_glass", + "minecraft:purple_stained_glass", + "minecraft:blue_stained_glass", + "minecraft:brown_stained_glass", + "minecraft:green_stained_glass", + "minecraft:red_stained_glass", + "minecraft:black_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/stained_glass_panes.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/stained_glass_panes.json new file mode 100644 index 00000000..3ae1826a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/stained_glass_panes.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "minecraft:white_stained_glass_pane", + "minecraft:orange_stained_glass_pane", + "minecraft:magenta_stained_glass_pane", + "minecraft:light_blue_stained_glass_pane", + "minecraft:yellow_stained_glass_pane", + "minecraft:lime_stained_glass_pane", + "minecraft:pink_stained_glass_pane", + "minecraft:gray_stained_glass_pane", + "minecraft:light_gray_stained_glass_pane", + "minecraft:cyan_stained_glass_pane", + "minecraft:purple_stained_glass_pane", + "minecraft:blue_stained_glass_pane", + "minecraft:brown_stained_glass_pane", + "minecraft:green_stained_glass_pane", + "minecraft:red_stained_glass_pane", + "minecraft:black_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/stone.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/stone.json new file mode 100644 index 00000000..108b95dc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/stone.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "minecraft:andesite", + "minecraft:diorite", + "minecraft:granite", + "minecraft:infested_stone", + "minecraft:stone", + "minecraft:polished_andesite", + "minecraft:polished_diorite", + "minecraft:polished_granite" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks.json new file mode 100644 index 00000000..e3658b35 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "#forge:storage_blocks/coal", + "#forge:storage_blocks/diamond", + "#forge:storage_blocks/emerald", + "#forge:storage_blocks/gold", + "#forge:storage_blocks/iron", + "#forge:storage_blocks/lapis", + "#forge:storage_blocks/quartz", + "#forge:storage_blocks/redstone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/coal.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/coal.json new file mode 100644 index 00000000..8654a02c --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/coal.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:coal_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/diamond.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/diamond.json new file mode 100644 index 00000000..34d42073 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/diamond.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:diamond_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/emerald.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/emerald.json new file mode 100644 index 00000000..e7cca299 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/emerald.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:emerald_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/gold.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/gold.json new file mode 100644 index 00000000..5cde185e --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/gold.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gold_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/iron.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/iron.json new file mode 100644 index 00000000..7b50a707 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/iron.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:iron_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/lapis.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/lapis.json new file mode 100644 index 00000000..b3e7a3e2 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/lapis.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lapis_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/quartz.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/quartz.json new file mode 100644 index 00000000..2bf357b8 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/quartz.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:quartz_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/redstone.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/redstone.json new file mode 100644 index 00000000..4b3277bc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/storage_blocks/redstone.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:redstone_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/supports_beacon.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/supports_beacon.json new file mode 100644 index 00000000..e58d0693 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/supports_beacon.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "values": [ + "minecraft:emerald_block", + "minecraft:gold_block", + "minecraft:diamond_block", + "minecraft:iron_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/blocks/supports_conduit.json b/patchwork-tags/src/main/resources/data/forge/tags/blocks/supports_conduit.json new file mode 100644 index 00000000..81680e19 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/blocks/supports_conduit.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "values": [ + "minecraft:prismarine", + "minecraft:prismarine_bricks", + "minecraft:sea_lantern", + "minecraft:dark_prismarine" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/arrows.json b/patchwork-tags/src/main/resources/data/forge/tags/items/arrows.json new file mode 100644 index 00000000..03afe251 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/arrows.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "minecraft:arrow", + "minecraft:tipped_arrow", + "minecraft:spectral_arrow" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/beacon_payment.json b/patchwork-tags/src/main/resources/data/forge/tags/items/beacon_payment.json new file mode 100644 index 00000000..ecee95be --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/beacon_payment.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "values": [ + "minecraft:emerald", + "minecraft:diamond", + "minecraft:gold_ingot", + "minecraft:iron_ingot" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/bones.json b/patchwork-tags/src/main/resources/data/forge/tags/items/bones.json new file mode 100644 index 00000000..db42b75b --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/bones.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:bone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/bookshelves.json b/patchwork-tags/src/main/resources/data/forge/tags/items/bookshelves.json new file mode 100644 index 00000000..8e94bbbc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/bookshelves.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:bookshelf" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/chests.json b/patchwork-tags/src/main/resources/data/forge/tags/items/chests.json new file mode 100644 index 00000000..5b2186a2 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/chests.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "#forge:chests/ender", + "#forge:chests/trapped", + "#forge:chests/wooden" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/chests/ender.json b/patchwork-tags/src/main/resources/data/forge/tags/items/chests/ender.json new file mode 100644 index 00000000..d7a16e96 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/chests/ender.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:ender_chest" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/chests/trapped.json b/patchwork-tags/src/main/resources/data/forge/tags/items/chests/trapped.json new file mode 100644 index 00000000..55c7aec1 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/chests/trapped.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:trapped_chest" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/chests/wooden.json b/patchwork-tags/src/main/resources/data/forge/tags/items/chests/wooden.json new file mode 100644 index 00000000..46ff16fc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/chests/wooden.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "minecraft:chest", + "minecraft:trapped_chest" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/cobblestone.json b/patchwork-tags/src/main/resources/data/forge/tags/items/cobblestone.json new file mode 100644 index 00000000..a5c96d86 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/cobblestone.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "minecraft:cobblestone", + "minecraft:infested_cobblestone", + "minecraft:mossy_cobblestone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/crops.json b/patchwork-tags/src/main/resources/data/forge/tags/items/crops.json new file mode 100644 index 00000000..b1c3220a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/crops.json @@ -0,0 +1,10 @@ +{ + "replace": false, + "values": [ + "#forge:crops/beetroot", + "#forge:crops/carrot", + "#forge:crops/nether_wart", + "#forge:crops/potato", + "#forge:crops/wheat" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/crops/beetroot.json b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/beetroot.json new file mode 100644 index 00000000..a3617f9e --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/beetroot.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:beetroot" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/crops/carrot.json b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/carrot.json new file mode 100644 index 00000000..efe5accf --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/carrot.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:carrot" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/crops/nether_wart.json b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/nether_wart.json new file mode 100644 index 00000000..74d9d420 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/nether_wart.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:nether_wart" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/crops/potato.json b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/potato.json new file mode 100644 index 00000000..0cf13c6c --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/potato.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:potato" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/crops/wheat.json b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/wheat.json new file mode 100644 index 00000000..6be645cd --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/crops/wheat.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:wheat" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dusts.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dusts.json new file mode 100644 index 00000000..512397df --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dusts.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "#forge:dusts/glowstone", + "#forge:dusts/prismarine", + "#forge:dusts/redstone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/glowstone.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/glowstone.json new file mode 100644 index 00000000..826dbd18 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/glowstone.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:glowstone_dust" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/prismarine.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/prismarine.json new file mode 100644 index 00000000..6ba76b04 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/prismarine.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:prismarine_shard" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/redstone.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/redstone.json new file mode 100644 index 00000000..ffe4ba88 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dusts/redstone.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:redstone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes.json new file mode 100644 index 00000000..ac203933 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "minecraft:white_dye", + "minecraft:orange_dye", + "minecraft:magenta_dye", + "minecraft:light_blue_dye", + "minecraft:yellow_dye", + "minecraft:lime_dye", + "minecraft:pink_dye", + "minecraft:gray_dye", + "minecraft:light_gray_dye", + "minecraft:cyan_dye", + "minecraft:purple_dye", + "minecraft:blue_dye", + "minecraft:brown_dye", + "minecraft:green_dye", + "minecraft:red_dye", + "minecraft:black_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/black.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/black.json new file mode 100644 index 00000000..e4172681 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/black.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:black_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/blue.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/blue.json new file mode 100644 index 00000000..854f2bb5 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:blue_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/brown.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/brown.json new file mode 100644 index 00000000..59550676 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/brown.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:brown_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/cyan.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/cyan.json new file mode 100644 index 00000000..06215afb --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/cyan.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:cyan_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/gray.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/gray.json new file mode 100644 index 00000000..8c6e48e8 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gray_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/green.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/green.json new file mode 100644 index 00000000..f2072a97 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/green.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:green_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/light_blue.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/light_blue.json new file mode 100644 index 00000000..b483f2ad --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/light_blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_blue_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/light_gray.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/light_gray.json new file mode 100644 index 00000000..811c46a8 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/light_gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_gray_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/lime.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/lime.json new file mode 100644 index 00000000..e7916df3 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/lime.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lime_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/magenta.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/magenta.json new file mode 100644 index 00000000..2c7129d2 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/magenta.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:magenta_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/orange.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/orange.json new file mode 100644 index 00000000..390bdfc7 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/orange.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:orange_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/pink.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/pink.json new file mode 100644 index 00000000..bc35aa76 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/pink.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:pink_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/purple.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/purple.json new file mode 100644 index 00000000..0a95460a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/purple.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:purple_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/red.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/red.json new file mode 100644 index 00000000..3e8be73f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/red.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:red_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/white.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/white.json new file mode 100644 index 00000000..59b63da2 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/white.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:white_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/yellow.json b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/yellow.json new file mode 100644 index 00000000..04e067b6 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/dyes/yellow.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:yellow_dye" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/eggs.json b/patchwork-tags/src/main/resources/data/forge/tags/items/eggs.json new file mode 100644 index 00000000..3c471673 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/eggs.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:egg" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/end_stones.json b/patchwork-tags/src/main/resources/data/forge/tags/items/end_stones.json new file mode 100644 index 00000000..6ed8faad --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/end_stones.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:end_stone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ender_pearls.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ender_pearls.json new file mode 100644 index 00000000..4863a360 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ender_pearls.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:ender_pearl" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/feathers.json b/patchwork-tags/src/main/resources/data/forge/tags/items/feathers.json new file mode 100644 index 00000000..015b7099 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/feathers.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:feather" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/fence_gates.json b/patchwork-tags/src/main/resources/data/forge/tags/items/fence_gates.json new file mode 100644 index 00000000..4fc8670f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/fence_gates.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#forge:fence_gates/wooden" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/fence_gates/wooden.json b/patchwork-tags/src/main/resources/data/forge/tags/items/fence_gates/wooden.json new file mode 100644 index 00000000..7b803077 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/fence_gates/wooden.json @@ -0,0 +1,11 @@ +{ + "replace": false, + "values": [ + "minecraft:oak_fence_gate", + "minecraft:spruce_fence_gate", + "minecraft:birch_fence_gate", + "minecraft:jungle_fence_gate", + "minecraft:acacia_fence_gate", + "minecraft:dark_oak_fence_gate" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/fences.json b/patchwork-tags/src/main/resources/data/forge/tags/items/fences.json new file mode 100644 index 00000000..a7e4edcd --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/fences.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:fences/nether_brick", + "#forge:fences/wooden" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/fences/nether_brick.json b/patchwork-tags/src/main/resources/data/forge/tags/items/fences/nether_brick.json new file mode 100644 index 00000000..49884116 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/fences/nether_brick.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:nether_brick_fence" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/fences/wooden.json b/patchwork-tags/src/main/resources/data/forge/tags/items/fences/wooden.json new file mode 100644 index 00000000..af77edde --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/fences/wooden.json @@ -0,0 +1,11 @@ +{ + "replace": false, + "values": [ + "minecraft:oak_fence", + "minecraft:spruce_fence", + "minecraft:birch_fence", + "minecraft:jungle_fence", + "minecraft:acacia_fence", + "minecraft:dark_oak_fence" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/gems.json b/patchwork-tags/src/main/resources/data/forge/tags/items/gems.json new file mode 100644 index 00000000..8c554ef4 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/gems.json @@ -0,0 +1,10 @@ +{ + "replace": false, + "values": [ + "#forge:gems/diamond", + "#forge:gems/emerald", + "#forge:gems/lapis", + "#forge:gems/prismarine", + "#forge:gems/quartz" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/gems/diamond.json b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/diamond.json new file mode 100644 index 00000000..0b7f5224 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/diamond.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:diamond" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/gems/emerald.json b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/emerald.json new file mode 100644 index 00000000..0f3bdf92 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/emerald.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:emerald" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/gems/lapis.json b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/lapis.json new file mode 100644 index 00000000..d0146f68 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/lapis.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lapis_lazuli" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/gems/prismarine.json b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/prismarine.json new file mode 100644 index 00000000..965cd0ab --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/prismarine.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:prismarine_crystals" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/gems/quartz.json b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/quartz.json new file mode 100644 index 00000000..585fa559 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/gems/quartz.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:quartz" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass.json new file mode 100644 index 00000000..6df0a8cb --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:glass/colorless", + "#forge:stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/black.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/black.json new file mode 100644 index 00000000..38eddb25 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/black.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:black_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/blue.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/blue.json new file mode 100644 index 00000000..5e20981a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:blue_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/brown.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/brown.json new file mode 100644 index 00000000..760da354 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/brown.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:brown_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/colorless.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/colorless.json new file mode 100644 index 00000000..8e580743 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/colorless.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/cyan.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/cyan.json new file mode 100644 index 00000000..75159cfc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/cyan.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:cyan_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/gray.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/gray.json new file mode 100644 index 00000000..7da37999 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gray_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/green.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/green.json new file mode 100644 index 00000000..88560a1b --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/green.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:green_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/light_blue.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/light_blue.json new file mode 100644 index 00000000..0cad485f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/light_blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_blue_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/light_gray.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/light_gray.json new file mode 100644 index 00000000..155b462b --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/light_gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_gray_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/lime.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/lime.json new file mode 100644 index 00000000..83f297e0 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/lime.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lime_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/magenta.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/magenta.json new file mode 100644 index 00000000..1a05a1a4 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/magenta.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:magenta_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/orange.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/orange.json new file mode 100644 index 00000000..dce95254 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/orange.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:orange_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/pink.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/pink.json new file mode 100644 index 00000000..736709fb --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/pink.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:pink_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/purple.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/purple.json new file mode 100644 index 00000000..25891652 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/purple.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:purple_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/red.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/red.json new file mode 100644 index 00000000..5b4e58b0 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/red.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:red_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/white.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/white.json new file mode 100644 index 00000000..7da94883 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/white.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:white_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass/yellow.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/yellow.json new file mode 100644 index 00000000..45bb137b --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass/yellow.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:yellow_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes.json new file mode 100644 index 00000000..175f6a66 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:glass_panes/colorless", + "#forge:stained_glass_panes" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/black.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/black.json new file mode 100644 index 00000000..ab7ea540 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/black.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:black_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/blue.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/blue.json new file mode 100644 index 00000000..3e454494 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:blue_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/brown.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/brown.json new file mode 100644 index 00000000..b0fc36bb --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/brown.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:brown_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/colorless.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/colorless.json new file mode 100644 index 00000000..e312863d --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/colorless.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/cyan.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/cyan.json new file mode 100644 index 00000000..a50053ff --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/cyan.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:cyan_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/gray.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/gray.json new file mode 100644 index 00000000..4469029f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gray_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/green.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/green.json new file mode 100644 index 00000000..4a7ed223 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/green.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:green_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/light_blue.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/light_blue.json new file mode 100644 index 00000000..82605a7d --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/light_blue.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_blue_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/light_gray.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/light_gray.json new file mode 100644 index 00000000..267d4e6a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/light_gray.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:light_gray_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/lime.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/lime.json new file mode 100644 index 00000000..54389292 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/lime.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lime_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/magenta.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/magenta.json new file mode 100644 index 00000000..94c5d119 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/magenta.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:magenta_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/orange.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/orange.json new file mode 100644 index 00000000..c51a3f3e --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/orange.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:orange_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/pink.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/pink.json new file mode 100644 index 00000000..34085961 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/pink.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:pink_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/purple.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/purple.json new file mode 100644 index 00000000..5c9fe059 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/purple.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:purple_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/red.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/red.json new file mode 100644 index 00000000..11bca5b1 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/red.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:red_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/white.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/white.json new file mode 100644 index 00000000..9a2f1c27 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/white.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:white_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/yellow.json b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/yellow.json new file mode 100644 index 00000000..7fe639cc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/glass_panes/yellow.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:yellow_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/gravel.json b/patchwork-tags/src/main/resources/data/forge/tags/items/gravel.json new file mode 100644 index 00000000..47a682ab --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/gravel.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gravel" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/gunpowder.json b/patchwork-tags/src/main/resources/data/forge/tags/items/gunpowder.json new file mode 100644 index 00000000..8b45ecf5 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/gunpowder.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gunpowder" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/heads.json b/patchwork-tags/src/main/resources/data/forge/tags/items/heads.json new file mode 100644 index 00000000..0ce68d9e --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/heads.json @@ -0,0 +1,11 @@ +{ + "replace": false, + "values": [ + "minecraft:creeper_head", + "minecraft:dragon_head", + "minecraft:player_head", + "minecraft:skeleton_skull", + "minecraft:wither_skeleton_skull", + "minecraft:zombie_head" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ingots.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots.json new file mode 100644 index 00000000..00914e8a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "values": [ + "#forge:ingots/iron", + "#forge:ingots/gold", + "#forge:ingots/brick", + "#forge:ingots/nether_brick" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/brick.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/brick.json new file mode 100644 index 00000000..5bca236a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/brick.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:brick" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/gold.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/gold.json new file mode 100644 index 00000000..74a63e9c --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/gold.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gold_ingot" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/iron.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/iron.json new file mode 100644 index 00000000..5e89bbc7 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/iron.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:iron_ingot" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/nether_brick.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/nether_brick.json new file mode 100644 index 00000000..d13b0207 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ingots/nether_brick.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:nether_brick" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/leather.json b/patchwork-tags/src/main/resources/data/forge/tags/items/leather.json new file mode 100644 index 00000000..118f5c9e --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/leather.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:leather" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/mushrooms.json b/patchwork-tags/src/main/resources/data/forge/tags/items/mushrooms.json new file mode 100644 index 00000000..bbb4511c --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/mushrooms.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "minecraft:brown_mushroom", + "minecraft:red_mushroom" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/music_discs.json b/patchwork-tags/src/main/resources/data/forge/tags/items/music_discs.json new file mode 100644 index 00000000..03bdf1c0 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/music_discs.json @@ -0,0 +1,17 @@ +{ + "replace": false, + "values": [ + "minecraft:music_disc_13", + "minecraft:music_disc_cat", + "minecraft:music_disc_blocks", + "minecraft:music_disc_chirp", + "minecraft:music_disc_far", + "minecraft:music_disc_mall", + "minecraft:music_disc_mellohi", + "minecraft:music_disc_stal", + "minecraft:music_disc_strad", + "minecraft:music_disc_ward", + "minecraft:music_disc_11", + "minecraft:music_disc_wait" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/nether_stars.json b/patchwork-tags/src/main/resources/data/forge/tags/items/nether_stars.json new file mode 100644 index 00000000..d29efd42 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/nether_stars.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:nether_star" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/netherrack.json b/patchwork-tags/src/main/resources/data/forge/tags/items/netherrack.json new file mode 100644 index 00000000..9d430375 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/netherrack.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:netherrack" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets.json b/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets.json new file mode 100644 index 00000000..66a7ecba --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:nuggets/iron", + "#forge:nuggets/gold" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets/gold.json b/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets/gold.json new file mode 100644 index 00000000..3c978eae --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets/gold.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gold_nugget" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets/iron.json b/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets/iron.json new file mode 100644 index 00000000..2e6bd5ff --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/nuggets/iron.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:iron_nugget" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/obsidian.json b/patchwork-tags/src/main/resources/data/forge/tags/items/obsidian.json new file mode 100644 index 00000000..129433a5 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/obsidian.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:obsidian" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores.json new file mode 100644 index 00000000..bc2cb711 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "#forge:ores/coal", + "#forge:ores/diamond", + "#forge:ores/emerald", + "#forge:ores/gold", + "#forge:ores/iron", + "#forge:ores/lapis", + "#forge:ores/redstone", + "#forge:ores/quartz" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores/coal.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/coal.json new file mode 100644 index 00000000..7c71d780 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/coal.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:coal_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores/diamond.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/diamond.json new file mode 100644 index 00000000..072563e4 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/diamond.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:diamond_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores/emerald.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/emerald.json new file mode 100644 index 00000000..3972c84a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/emerald.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:emerald_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores/gold.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/gold.json new file mode 100644 index 00000000..ebbc8168 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/gold.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gold_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores/iron.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/iron.json new file mode 100644 index 00000000..dd2164d9 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/iron.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:iron_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores/lapis.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/lapis.json new file mode 100644 index 00000000..68d1a961 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/lapis.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lapis_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores/quartz.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/quartz.json new file mode 100644 index 00000000..46ba0451 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/quartz.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:nether_quartz_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/ores/redstone.json b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/redstone.json new file mode 100644 index 00000000..c88b6802 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/ores/redstone.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:redstone_ore" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/rods.json b/patchwork-tags/src/main/resources/data/forge/tags/items/rods.json new file mode 100644 index 00000000..ddd4ad92 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/rods.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:rods/blaze", + "#forge:rods/wooden" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/rods/blaze.json b/patchwork-tags/src/main/resources/data/forge/tags/items/rods/blaze.json new file mode 100644 index 00000000..96bb55e9 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/rods/blaze.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:blaze_rod" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/rods/wooden.json b/patchwork-tags/src/main/resources/data/forge/tags/items/rods/wooden.json new file mode 100644 index 00000000..90f5f079 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/rods/wooden.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:stick" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/sand.json b/patchwork-tags/src/main/resources/data/forge/tags/items/sand.json new file mode 100644 index 00000000..a011fb45 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/sand.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "#forge:sand/colorless", + "#forge:sand/red" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/sand/colorless.json b/patchwork-tags/src/main/resources/data/forge/tags/items/sand/colorless.json new file mode 100644 index 00000000..78337d59 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/sand/colorless.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:sand" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/sand/red.json b/patchwork-tags/src/main/resources/data/forge/tags/items/sand/red.json new file mode 100644 index 00000000..5b5bbef0 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/sand/red.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:red_sand" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/sandstone.json b/patchwork-tags/src/main/resources/data/forge/tags/items/sandstone.json new file mode 100644 index 00000000..b497d97f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/sandstone.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "minecraft:sandstone", + "minecraft:cut_sandstone", + "minecraft:chiseled_sandstone", + "minecraft:smooth_sandstone", + "minecraft:red_sandstone", + "minecraft:cut_red_sandstone", + "minecraft:chiseled_red_sandstone", + "minecraft:smooth_red_sandstone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/seeds.json b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds.json new file mode 100644 index 00000000..163853da --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "values": [ + "#forge:seeds/beetroot", + "#forge:seeds/melon", + "#forge:seeds/pumpkin", + "#forge:seeds/wheat" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/beetroot.json b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/beetroot.json new file mode 100644 index 00000000..a95a5c2d --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/beetroot.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:beetroot_seeds" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/melon.json b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/melon.json new file mode 100644 index 00000000..17bd6c8f --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/melon.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:melon_seeds" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/pumpkin.json b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/pumpkin.json new file mode 100644 index 00000000..2ec15eb1 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/pumpkin.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:pumpkin_seeds" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/wheat.json b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/wheat.json new file mode 100644 index 00000000..fa806cac --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/seeds/wheat.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:wheat_seeds" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/slimeballs.json b/patchwork-tags/src/main/resources/data/forge/tags/items/slimeballs.json new file mode 100644 index 00000000..e471d6fe --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/slimeballs.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:slime_ball" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/stained_glass.json b/patchwork-tags/src/main/resources/data/forge/tags/items/stained_glass.json new file mode 100644 index 00000000..a36fc9bc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/stained_glass.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "minecraft:white_stained_glass", + "minecraft:orange_stained_glass", + "minecraft:magenta_stained_glass", + "minecraft:light_blue_stained_glass", + "minecraft:yellow_stained_glass", + "minecraft:lime_stained_glass", + "minecraft:pink_stained_glass", + "minecraft:gray_stained_glass", + "minecraft:light_gray_stained_glass", + "minecraft:cyan_stained_glass", + "minecraft:purple_stained_glass", + "minecraft:blue_stained_glass", + "minecraft:brown_stained_glass", + "minecraft:green_stained_glass", + "minecraft:red_stained_glass", + "minecraft:black_stained_glass" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/stained_glass_panes.json b/patchwork-tags/src/main/resources/data/forge/tags/items/stained_glass_panes.json new file mode 100644 index 00000000..3ae1826a --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/stained_glass_panes.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "minecraft:white_stained_glass_pane", + "minecraft:orange_stained_glass_pane", + "minecraft:magenta_stained_glass_pane", + "minecraft:light_blue_stained_glass_pane", + "minecraft:yellow_stained_glass_pane", + "minecraft:lime_stained_glass_pane", + "minecraft:pink_stained_glass_pane", + "minecraft:gray_stained_glass_pane", + "minecraft:light_gray_stained_glass_pane", + "minecraft:cyan_stained_glass_pane", + "minecraft:purple_stained_glass_pane", + "minecraft:blue_stained_glass_pane", + "minecraft:brown_stained_glass_pane", + "minecraft:green_stained_glass_pane", + "minecraft:red_stained_glass_pane", + "minecraft:black_stained_glass_pane" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/stone.json b/patchwork-tags/src/main/resources/data/forge/tags/items/stone.json new file mode 100644 index 00000000..108b95dc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/stone.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "minecraft:andesite", + "minecraft:diorite", + "minecraft:granite", + "minecraft:infested_stone", + "minecraft:stone", + "minecraft:polished_andesite", + "minecraft:polished_diorite", + "minecraft:polished_granite" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks.json new file mode 100644 index 00000000..e3658b35 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "#forge:storage_blocks/coal", + "#forge:storage_blocks/diamond", + "#forge:storage_blocks/emerald", + "#forge:storage_blocks/gold", + "#forge:storage_blocks/iron", + "#forge:storage_blocks/lapis", + "#forge:storage_blocks/quartz", + "#forge:storage_blocks/redstone" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/coal.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/coal.json new file mode 100644 index 00000000..8654a02c --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/coal.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:coal_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/diamond.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/diamond.json new file mode 100644 index 00000000..34d42073 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/diamond.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:diamond_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/emerald.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/emerald.json new file mode 100644 index 00000000..e7cca299 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/emerald.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:emerald_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/gold.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/gold.json new file mode 100644 index 00000000..5cde185e --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/gold.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:gold_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/iron.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/iron.json new file mode 100644 index 00000000..7b50a707 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/iron.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:iron_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/lapis.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/lapis.json new file mode 100644 index 00000000..b3e7a3e2 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/lapis.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:lapis_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/quartz.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/quartz.json new file mode 100644 index 00000000..2bf357b8 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/quartz.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:quartz_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/redstone.json b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/redstone.json new file mode 100644 index 00000000..4b3277bc --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/storage_blocks/redstone.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:redstone_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/string.json b/patchwork-tags/src/main/resources/data/forge/tags/items/string.json new file mode 100644 index 00000000..88fcd5dd --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/string.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "minecraft:string" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/supports_beacon.json b/patchwork-tags/src/main/resources/data/forge/tags/items/supports_beacon.json new file mode 100644 index 00000000..e58d0693 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/supports_beacon.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "values": [ + "minecraft:emerald_block", + "minecraft:gold_block", + "minecraft:diamond_block", + "minecraft:iron_block" + ] +} diff --git a/patchwork-tags/src/main/resources/data/forge/tags/items/supports_conduit.json b/patchwork-tags/src/main/resources/data/forge/tags/items/supports_conduit.json new file mode 100644 index 00000000..81680e19 --- /dev/null +++ b/patchwork-tags/src/main/resources/data/forge/tags/items/supports_conduit.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "values": [ + "minecraft:prismarine", + "minecraft:prismarine_bricks", + "minecraft:sea_lantern", + "minecraft:dark_prismarine" + ] +} diff --git a/patchwork-tags/src/main/resources/fabric.mod.json b/patchwork-tags/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..23be96f8 --- /dev/null +++ b/patchwork-tags/src/main/resources/fabric.mod.json @@ -0,0 +1,24 @@ +{ + "schemaVersion": 1, + "id": "patchwork-tags", + "name": "Patchwork Tags", + "version": "${version}", + "license": "LGPL-2.1-only", + "icon": "assets/patchwork-tags/icon.png", + "contact": { + "issues": "https://github.com/PatchworkMC/patchwork-api/issues", + "sources": "https://github.com/PatchworkMC/patchwork-api" + }, + "authors": [ + "PatchworkMC" + ], + "accessWidener": "patchwork-tags.accesswidener", + "depends": { + "fabricloader": ">=0.8.4" + }, + "description": "Implementation of the Forge Tags API.", + "custom": { + "modmenu:api": true, + "modmenu:parent": "patchwork" + } +} diff --git a/patchwork-tags/src/main/resources/patchwork-tags.accesswidener b/patchwork-tags/src/main/resources/patchwork-tags.accesswidener new file mode 100644 index 00000000..0a65a94e --- /dev/null +++ b/patchwork-tags/src/main/resources/patchwork-tags.accesswidener @@ -0,0 +1,3 @@ +accessWidener v1 named + +accessible class net/minecraft/tag/BlockTags$CachingTag diff --git a/settings.gradle b/settings.gradle index 56e3d173..93f1e690 100644 --- a/settings.gradle +++ b/settings.gradle @@ -37,6 +37,7 @@ include 'patchwork-networking-messages' include 'patchwork-recipes' include 'patchwork-registries' include 'patchwork-resource' +include 'patchwork-tags' include 'patchwork-tooltype' include 'patchwork-vanilla-patches' From 5ce6d98b10f238873d47a25a8553d2cdc4135a40 Mon Sep 17 00:00:00 2001 From: Kitlith Date: Sun, 26 Jul 2020 14:11:27 -0700 Subject: [PATCH 16/73] Implement ChunkWatchEvent.UnWatch (#143) * Implement ChunkWatchEvent.UnWatch NOTE: This implementation follows upstream 1.14.4 Forge, not the commit we're tracking which doesn't implement it at all. * fix error Co-authored-by: Glitch --- .../minecraftforge/event/world/ChunkWatchEvent.java | 4 ++-- .../patchworkmc/impl/event/world/WorldEvents.java | 12 ++++++++++++ .../event/world/MixinThreadedAnvilChunkStorage.java | 10 ++++------ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/ChunkWatchEvent.java b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/ChunkWatchEvent.java index eb9233a2..61796d1d 100644 --- a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/ChunkWatchEvent.java +++ b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/ChunkWatchEvent.java @@ -91,9 +91,9 @@ public Watch(ServerPlayerEntity player, ChunkPos pos, ServerWorld world) { * *

This event is fired on the {@link net.minecraftforge.common.MinecraftForge#EVENT_BUS}.

*/ - /* TODO public static class UnWatch extends ChunkWatchEvent { + public static class UnWatch extends ChunkWatchEvent { public UnWatch(ServerPlayerEntity player, ChunkPos pos, ServerWorld world) { super(player, pos, world); } - }*/ + } } diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index 19b8d250..5e2adfac 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -23,10 +23,14 @@ import java.util.List; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkWatchEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraft.entity.EntityCategory; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; import net.minecraft.world.dimension.DimensionType; @@ -62,6 +66,14 @@ public static void onWorldSave(IWorld world) { MinecraftForge.EVENT_BUS.post(new WorldEvent.Save(world)); } + public static void fireChunkWatch(boolean watch, ServerPlayerEntity entity, ChunkPos chunkpos, ServerWorld world) { + if (watch) { + MinecraftForge.EVENT_BUS.post(new ChunkWatchEvent.Watch(entity, chunkpos, world)); + } else { + MinecraftForge.EVENT_BUS.post(new ChunkWatchEvent.UnWatch(entity, chunkpos, world)); + } + } + @Override public void onInitialize() { ServerWorldEvents.LOAD.register((server, world) -> { diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java index 90eabae8..91e2404b 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java @@ -19,8 +19,6 @@ package net.patchworkmc.mixin.event.world; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.world.ChunkWatchEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -33,6 +31,8 @@ import net.minecraft.server.world.ThreadedAnvilChunkStorage; import net.minecraft.util.math.ChunkPos; +import net.patchworkmc.impl.event.world.WorldEvents; + @Mixin(ThreadedAnvilChunkStorage.class) public class MixinThreadedAnvilChunkStorage { @Shadow @@ -40,10 +40,8 @@ public class MixinThreadedAnvilChunkStorage { @Inject(method = "sendWatchPackets", at = @At("HEAD")) private void fireWatchEvents(ServerPlayerEntity player, ChunkPos pos, Packet[] packets, boolean withinMaxWatchDistance, boolean withinViewDistance, CallbackInfo callback) { - if (withinViewDistance && !withinMaxWatchDistance) { - ChunkWatchEvent.Watch event = new ChunkWatchEvent.Watch(player, pos, world); - - MinecraftForge.EVENT_BUS.post(event); + if (this.world == player.world && withinMaxWatchDistance != withinViewDistance) { + WorldEvents.fireChunkWatch(withinViewDistance, player, pos, this.world); } } } From 7d7600f94dcbebc1735432ad3e68ba59d2618798 Mon Sep 17 00:00:00 2001 From: Kitlith Date: Sun, 26 Jul 2020 14:12:00 -0700 Subject: [PATCH 17/73] Dispatch to InputEvents from patchwork-god-classes (#130) * Move InputEvent firing to a new class, InputEvents * Dispatch from ForgeHooksClient to InputEvents * Fixup! mixin didn't actually implement interface. --- .../net/patchworkmc/api/input/ForgeMouse.java | 26 +++++++++ .../impl/event/input/InputEvents.java | 48 +++++++++++++++++ .../mixin/event/input/MixinKeyboard.java | 8 +-- .../mixin/event/input/MixinMouse.java | 54 +++++++++++-------- patchwork-god-classes/build.gradle | 1 + .../client/ForgeHooksClient.java | 18 +++++++ .../src/main/resources/fabric.mod.json | 1 + 7 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 patchwork-events-input/src/main/java/net/patchworkmc/api/input/ForgeMouse.java create mode 100644 patchwork-events-input/src/main/java/net/patchworkmc/impl/event/input/InputEvents.java diff --git a/patchwork-events-input/src/main/java/net/patchworkmc/api/input/ForgeMouse.java b/patchwork-events-input/src/main/java/net/patchworkmc/api/input/ForgeMouse.java new file mode 100644 index 00000000..364e019f --- /dev/null +++ b/patchwork-events-input/src/main/java/net/patchworkmc/api/input/ForgeMouse.java @@ -0,0 +1,26 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.api.input; + +public interface ForgeMouse { + boolean isMiddleDown(); + double getXVelocity(); + double getYVelocity(); +} diff --git a/patchwork-events-input/src/main/java/net/patchworkmc/impl/event/input/InputEvents.java b/patchwork-events-input/src/main/java/net/patchworkmc/impl/event/input/InputEvents.java new file mode 100644 index 00000000..65a2951b --- /dev/null +++ b/patchwork-events-input/src/main/java/net/patchworkmc/impl/event/input/InputEvents.java @@ -0,0 +1,48 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.event.input; + +import net.minecraftforge.client.event.InputEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Event; + +import net.minecraft.client.Mouse; + +import net.patchworkmc.api.input.ForgeMouse; + +public class InputEvents { + public static void fireMouseInput(int button, int action, int mods) { + MinecraftForge.EVENT_BUS.post(new InputEvent.MouseInputEvent(button, action, mods)); + } + + public static void fireKeyInput(int key, int scanCode, int action, int modifiers) { + MinecraftForge.EVENT_BUS.post(new InputEvent.KeyInputEvent(key, scanCode, action, modifiers)); + } + + public static boolean onMouseScroll(Mouse mouseHelper, double scrollDelta) { + final Event event = new InputEvent.MouseScrollEvent(scrollDelta, mouseHelper.wasLeftButtonClicked(), ((ForgeMouse) mouseHelper).isMiddleDown(), mouseHelper.wasRightButtonClicked(), mouseHelper.getX(), mouseHelper.getY()); + + return MinecraftForge.EVENT_BUS.post(event); + } + + public static boolean onRawMouseClicked(int button, int action, int mods) { + return MinecraftForge.EVENT_BUS.post(new InputEvent.RawMouseEvent(button, action, mods)); + } +} diff --git a/patchwork-events-input/src/main/java/net/patchworkmc/mixin/event/input/MixinKeyboard.java b/patchwork-events-input/src/main/java/net/patchworkmc/mixin/event/input/MixinKeyboard.java index 70d1d82b..0891efb3 100644 --- a/patchwork-events-input/src/main/java/net/patchworkmc/mixin/event/input/MixinKeyboard.java +++ b/patchwork-events-input/src/main/java/net/patchworkmc/mixin/event/input/MixinKeyboard.java @@ -19,8 +19,6 @@ package net.patchworkmc.mixin.event.input; -import net.minecraftforge.client.event.InputEvent; -import net.minecraftforge.common.MinecraftForge; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -30,15 +28,17 @@ import net.minecraft.client.Keyboard; import net.minecraft.client.MinecraftClient; +import net.patchworkmc.impl.event.input.InputEvents; + @Mixin(Keyboard.class) public abstract class MixinKeyboard { @Shadow MinecraftClient client; @Inject(method = "onKey", at = @At("RETURN")) - private void fireKeyInput(long window, int key, int scancode, int i, int j, CallbackInfo info) { + private void fireKeyInput(long window, int key, int scancode, int action, int modifiers, CallbackInfo info) { if (window == this.client.window.getHandle()) { - MinecraftForge.EVENT_BUS.post(new InputEvent.KeyInputEvent(key, scancode, i, j)); + InputEvents.fireKeyInput(key, scancode, action, modifiers); } } } diff --git a/patchwork-events-input/src/main/java/net/patchworkmc/mixin/event/input/MixinMouse.java b/patchwork-events-input/src/main/java/net/patchworkmc/mixin/event/input/MixinMouse.java index 06827afb..37d3d483 100644 --- a/patchwork-events-input/src/main/java/net/patchworkmc/mixin/event/input/MixinMouse.java +++ b/patchwork-events-input/src/main/java/net/patchworkmc/mixin/event/input/MixinMouse.java @@ -19,9 +19,6 @@ package net.patchworkmc.mixin.event.input; -import net.minecraftforge.client.event.InputEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.Event; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -32,37 +29,52 @@ import net.minecraft.client.Mouse; -@Mixin(Mouse.class) -public abstract class MixinMouse { - @Shadow - boolean middleButtonClicked; - @Shadow - abstract boolean wasLeftButtonClicked(); - @Shadow - abstract boolean wasRightButtonClicked(); - @Shadow - abstract double getX(); - @Shadow - abstract double getY(); +import net.patchworkmc.api.input.ForgeMouse; +import net.patchworkmc.impl.event.input.InputEvents; +@Mixin(Mouse.class) +public abstract class MixinMouse implements ForgeMouse { @Inject(method = "onMouseButton", at = @At("RETURN"), cancellable = true) private void fireMouseInput(long window, int button, int action, int mods, CallbackInfo info) { - MinecraftForge.EVENT_BUS.post(new InputEvent.MouseInputEvent(button, action, mods)); + InputEvents.fireMouseInput(button, action, mods); } @Inject(method = "onMouseButton", at = @At(value = "FIELD", ordinal = 3, target = "Lnet/minecraft/client/Mouse;client:Lnet/minecraft/client/MinecraftClient;", shift = Shift.BEFORE), cancellable = true) private void onRawMouseClicked(long window, int button, int action, int mods, CallbackInfo info) { - if (MinecraftForge.EVENT_BUS.post(new InputEvent.RawMouseEvent(button, action, mods))) { + if (InputEvents.onRawMouseClicked(button, action, mods)) { info.cancel(); } } @Inject(method = "onMouseScroll", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSpectator()Z", shift = Shift.BEFORE), cancellable = true) - private void onMouseScroll(long window, double d, double e, CallbackInfo info, double f, float i) { - final Event event = new InputEvent.MouseScrollEvent(f, wasLeftButtonClicked(), middleButtonClicked, wasRightButtonClicked(), getX(), getY()); - - if (MinecraftForge.EVENT_BUS.post(event)) { + private void onMouseScroll(long window, double d, double e, CallbackInfo info, double scrollDelta, float i) { + if (InputEvents.onMouseScroll((Mouse) (Object) this, scrollDelta)) { info.cancel(); } } + + // Methods added by forge + @Shadow + boolean middleButtonClicked; + + @Shadow + double cursorDeltaX; + + @Shadow + double cursorDeltaY; + + @Override + public boolean isMiddleDown() { + return middleButtonClicked; + } + + @Override + public double getXVelocity() { + return cursorDeltaX; + } + + @Override + public double getYVelocity() { + return cursorDeltaY; + } } diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index ad0f0d6a..1b5d076f 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -5,6 +5,7 @@ dependencies { compile project(path: ':patchwork-fml', configuration: 'dev') compile project(path: ':patchwork-capabilities', configuration: 'dev') compile project(path: ':patchwork-events-entity', configuration: 'dev') + compile project(path: ':patchwork-events-input', configuration: 'dev') compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') compile project(path: ':patchwork-events-rendering', configuration: 'dev') compile project(path: ':patchwork-loot', configuration: 'dev') diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index 9a369e8e..2c48048d 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -25,7 +25,9 @@ import net.minecraft.client.color.item.ItemColors; import net.minecraft.client.texture.SpriteAtlasTexture; import net.minecraft.util.Identifier; +import net.minecraft.client.Mouse; +import net.patchworkmc.impl.event.input.InputEvents; import net.patchworkmc.impl.event.render.RenderEvents; /* @@ -33,6 +35,22 @@ * Do not keep implementation details here, methods should be thin wrappers around methods in other modules. */ public class ForgeHooksClient { + public static void fireMouseInput(int button, int action, int mods) { + InputEvents.fireMouseInput(button, action, mods); + } + + public static void fireKeyInput(int key, int scanCode, int action, int modifiers) { + InputEvents.fireKeyInput(key, scanCode, action, modifiers); + } + + public static boolean onMouseScroll(Mouse mouseHelper, double scrollDelta) { + return InputEvents.onMouseScroll(mouseHelper, scrollDelta); + } + + public static boolean onRawMouseClicked(int button, int action, int mods) { + return InputEvents.onRawMouseClicked(button, action, mods); + } + public static void onBlockColorsInit(BlockColors blockColors) { RenderEvents.onBlockColorsInit(blockColors); } diff --git a/patchwork-god-classes/src/main/resources/fabric.mod.json b/patchwork-god-classes/src/main/resources/fabric.mod.json index 388b9196..b14cf7e8 100644 --- a/patchwork-god-classes/src/main/resources/fabric.mod.json +++ b/patchwork-god-classes/src/main/resources/fabric.mod.json @@ -18,6 +18,7 @@ "fabricloader": ">=0.8.4", "patchwork-fml": "*", "patchwork-capabilities": "*", + "patchwork-events-input": "*", "patchwork-events-lifecycle": "*", "patchwork-events-rendering": "*", "patchwork-loot": "*" From 2ffa876d4e265f81c1bd44357dda8abc6cb35266 Mon Sep 17 00:00:00 2001 From: Gamma Whiskey <20158146+GammaWhiskey@users.noreply.github.com> Date: Sun, 26 Jul 2020 17:51:03 -0400 Subject: [PATCH 18/73] Fix style --- .../main/java/net/patchworkmc/impl/event/world/WorldEvents.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index 807435d6..4b33e3a3 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -79,7 +79,7 @@ public static float fireBlockHarvesting(DefaultedList drops, World wo return event.getDropChance(); } - public static void fireChunkWatch(boolean watch, ServerPlayerEntity entity, ChunkPos chunkpos, ServerWorld world) { + public static void fireChunkWatch(boolean watch, ServerPlayerEntity entity, ChunkPos chunkpos, ServerWorld world) { if (watch) { MinecraftForge.EVENT_BUS.post(new ChunkWatchEvent.Watch(entity, chunkpos, world)); } else { From 82ca90f4041b01c6dcad337bc59feec564a367a0 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Sun, 26 Jul 2020 18:31:02 -0500 Subject: [PATCH 19/73] Fix FAPI not being fully updated, giving IDEA a heart attack --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8896a885..f250a02f 100644 --- a/build.gradle +++ b/build.gradle @@ -239,7 +239,7 @@ dependencies { minecraft "com.mojang:minecraft:$Globals.mcVersion" mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}:v2" modCompile "net.fabricmc:fabric-loader:0.8.4+build.198" - modCompile "net.fabricmc.fabric-api:fabric-api:0.4.2+build.246-1.14" + modCompile "net.fabricmc.fabric-api:fabric-api:0.15.1+build.260-1.14" implementation 'com.electronwill.night-config:toml:3.6.2' include 'com.electronwill.night-config:core:3.6.2' From f9a1d2aea0009fbdd45423fe111e248f4b288995 Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Mon, 27 Jul 2020 17:44:49 -0400 Subject: [PATCH 20/73] Implement DeferredRegister and RegistryObject (#140) --- .../minecraftforge/fml/RegistryObject.java | 296 ++++++++++++++++++ .../registries/DeferredRegister.java | 104 ++++++ 2 files changed, 400 insertions(+) create mode 100644 patchwork-registries/src/main/java/net/minecraftforge/fml/RegistryObject.java create mode 100644 patchwork-registries/src/main/java/net/minecraftforge/registries/DeferredRegister.java diff --git a/patchwork-registries/src/main/java/net/minecraftforge/fml/RegistryObject.java b/patchwork-registries/src/main/java/net/minecraftforge/fml/RegistryObject.java new file mode 100644 index 00000000..9024333b --- /dev/null +++ b/patchwork-registries/src/main/java/net/minecraftforge/fml/RegistryObject.java @@ -0,0 +1,296 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import javax.annotation.Nullable; + +import net.minecraftforge.registries.IForgeRegistry; +import net.minecraftforge.registries.IForgeRegistryEntry; +import net.minecraftforge.registries.RegistryManager; + +import net.minecraft.util.Identifier; + +import net.patchworkmc.api.registries.ObjectHolderRegistry; + +public final class RegistryObject> implements Supplier { + private static RegistryObject EMPTY = new RegistryObject<>(); + private final Identifier name; + @Nullable + private T value; + + private RegistryObject() { + this.name = null; + } + + private > RegistryObject(Identifier name, Supplier> registryType) { + this(name, RegistryManager.ACTIVE.getRegistry(registryType.get())); + } + + @SuppressWarnings("unchecked") + private > RegistryObject(Identifier name, IForgeRegistry registry) { + if (registry == null) { + throw new IllegalArgumentException("Invalid registry argument, must not be null"); + } + + this.name = name; + ObjectHolderRegistry.INSTANCE.register(registry.getRegistrySuperType(), name.getNamespace(), name.getPath(), value -> { + this.value = (T) value; + }); + } + + @Deprecated + public static , U extends T> RegistryObject of(final String name, Supplier> registryType) { + return of(new Identifier(name), registryType); + } + + public static , U extends T> RegistryObject of(final Identifier name, Supplier> registryType) { + return new RegistryObject<>(name, registryType); + } + + @Deprecated + public static , U extends T> RegistryObject of(final String name, IForgeRegistry registry) { + return of(new Identifier(name), registry); + } + + public static , U extends T> RegistryObject of(final Identifier name, IForgeRegistry registry) { + return new RegistryObject<>(name, registry); + } + + private static > RegistryObject empty() { + @SuppressWarnings("unchecked") + RegistryObject t = (RegistryObject) EMPTY; + return t; + } + + /** + * Directly retrieves the wrapped Registry Object. This value will automatically be updated when the backing registry is updated. + */ + @Nullable + @Override + public T get() { + return this.value; + } + + public void updateReference(IForgeRegistry registry) { + this.value = registry.getValue(getId()); + } + + public Identifier getId() { + return this.name; + } + + /** + * @deprecated Prefer {@link #getId()} + */ + @Deprecated + public String getName() { + return getId().toString(); + } + + public Stream stream() { + return isPresent() ? Stream.of(get()) : Stream.of(); + } + + /** + * Return {@code true} if there is a mod object present, otherwise {@code false}. + * + * @return {@code true} if there is a mod object present, otherwise {@code false} + */ + public boolean isPresent() { + return get() != null; + } + + /** + * If a mod object is present, invoke the specified consumer with the object, + * otherwise do nothing. + * + * @param consumer block to be executed if a mod object is present + * @throws NullPointerException if mod object is present and {@code consumer} is + * null + */ + public void ifPresent(Consumer consumer) { + if (get() != null) { + consumer.accept(get()); + } + } + + /** + * If a mod object is present, and the mod object matches the given predicate, + * return an {@code RegistryObject} describing the value, otherwise return an + * empty {@code RegistryObject}. + * + * @param predicate a predicate to apply to the mod object, if present + * @return an {@code RegistryObject} describing the value of this {@code RegistryObject} + * if a mod object is present and the mod object matches the given predicate, + * otherwise an empty {@code RegistryObject} + * @throws NullPointerException if the predicate is null + */ + public RegistryObject filter(Predicate predicate) { + Objects.requireNonNull(predicate); + + if (!isPresent()) { + return this; + } else { + return predicate.test(get()) ? this : empty(); + } + } + + /** + * If a mod object is present, apply the provided mapping function to it, + * and if the result is non-null, return an {@code Optional} describing the + * result. Otherwise return an empty {@code Optional}. + * + * @param The type of the result of the mapping function + * @param mapper a mapping function to apply to the mod object, if present + * @return an {@code Optional} describing the result of applying a mapping + * function to the mod object of this {@code RegistryObject}, if a mod object is present, + * otherwise an empty {@code Optional} + * @throws NullPointerException if the mapping function is null + * @apiNote This method supports post-processing on optional values, without + * the need to explicitly check for a return status. + */ + public Optional map(Function mapper) { + Objects.requireNonNull(mapper); + + if (!isPresent()) { + return Optional.empty(); + } else { + return Optional.ofNullable(mapper.apply(get())); + } + } + + /** + * If a value is present, apply the provided {@code Optional}-bearing + * mapping function to it, return that result, otherwise return an empty + * {@code Optional}. This method is similar to {@link #map(Function)}, + * but the provided mapper is one whose result is already an {@code Optional}, + * and if invoked, {@code flatMap} does not wrap it with an additional + * {@code Optional}. + * + * @param The type parameter to the {@code Optional} returned by + * @param mapper a mapping function to apply to the mod object, if present + * the mapping function + * @return the result of applying an {@code Optional}-bearing mapping + * function to the value of this {@code Optional}, if a value is present, + * otherwise an empty {@code Optional} + * @throws NullPointerException if the mapping function is null or returns + * a null result + */ + public Optional flatMap(Function> mapper) { + Objects.requireNonNull(mapper); + + if (!isPresent()) { + return Optional.empty(); + } else { + return Objects.requireNonNull(mapper.apply(get())); + } + } + + /** + * If a mod object is present, lazily apply the provided mapping function to it, + * returning a supplier for the transformed result. If this object is empty, or the + * mapping function returns {@code null}, the supplier will return {@code null}. + * + * @param The type of the result of the mapping function + * @param mapper A mapping function to apply to the mod object, if present + * @return A {@code Supplier} lazily providing the result of applying a mapping + * function to the mod object of this {@code RegistryObject}, if a mod object is present, + * otherwise a supplier returning {@code null} + * @throws NullPointerException if the mapping function is {@code null} + * @apiNote This method supports post-processing on optional values, without + * the need to explicitly check for a return status. + */ + public Supplier lazyMap(Function mapper) { + Objects.requireNonNull(mapper); + return () -> isPresent() ? mapper.apply(get()) : null; + } + + /** + * Return the mod object if present, otherwise return {@code other}. + * + * @param other the mod object to be returned if there is no mod object present, may + * be null + * @return the mod object, if present, otherwise {@code other} + */ + public T orElse(T other) { + return isPresent() ? get() : other; + } + + /** + * Return the mod object if present, otherwise invoke {@code other} and return + * the result of that invocation. + * + * @param other a {@code Supplier} whose result is returned if no mod object + * is present + * @return the mod object if present otherwise the result of {@code other.get()} + * @throws NullPointerException if mod object is not present and {@code other} is + * null + */ + public T orElseGet(Supplier other) { + return isPresent() ? get() : other.get(); + } + + /** + * Return the contained mod object, if present, otherwise throw an exception + * to be created by the provided supplier. + * + * @param Type of the exception to be thrown + * @param exceptionSupplier The supplier which will return the exception to + * be thrown + * @return the present mod object + * @throws X if there is no mod object present + * @throws NullPointerException if no mod object is present and + * {@code exceptionSupplier} is null + * @apiNote A method reference to the exception constructor with an empty + * argument list can be used as the supplier. For example, + * {@code IllegalStateException::new} + */ + public T orElseThrow(Supplier exceptionSupplier) throws X { + if (get() != null) { + return get(); + } else { + throw exceptionSupplier.get(); + } + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + + if (obj instanceof RegistryObject) { + return Objects.equals(((RegistryObject) obj).name, name); + } + + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } +} diff --git a/patchwork-registries/src/main/java/net/minecraftforge/registries/DeferredRegister.java b/patchwork-registries/src/main/java/net/minecraftforge/registries/DeferredRegister.java new file mode 100644 index 00000000..73a9eda0 --- /dev/null +++ b/patchwork-registries/src/main/java/net/minecraftforge/registries/DeferredRegister.java @@ -0,0 +1,104 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.registries; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.function.Supplier; + +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.RegistryObject; + +import net.minecraft.util.Identifier; + +/** + * Utility class to help with managing registry entries. + * Maintains a list of all suppliers for entries and registers them during the proper Register event. + * Suppliers should return NEW instances every time. + * + * @param The base registry type, must be a concrete base class, do not use subclasses or wild cards. + */ +public class DeferredRegister> { + private final IForgeRegistry type; + private final String modid; + private final Map, Supplier> entries = new LinkedHashMap<>(); + private final Set> entriesView = Collections.unmodifiableSet(entries.keySet()); + + public DeferredRegister(IForgeRegistry reg, String modid) { + this.type = reg; + this.modid = modid; + } + + /** + * Adds a new supplier to the list of entries to be registered, and returns a RegistryObject that will be populated with the created entry automatically. + * + * @param name The new entry's name, it will automatically have the modid prefixed. + * @param sup A factory for the new entry, it should return a new instance every time it is called. + * @return A RegistryObject that will be updated with when the entries in the registry change. + */ + @SuppressWarnings("unchecked") + public RegistryObject register(final String name, final Supplier sup) { + Objects.requireNonNull(name); + Objects.requireNonNull(sup); + final Identifier key = new Identifier(modid, name); + RegistryObject ret = RegistryObject.of(key, this.type); + + if (entries.putIfAbsent((RegistryObject) ret, () -> (T) sup.get().setRegistryName(key)) != null) { + throw new IllegalArgumentException("Duplicate registration " + name); + } + + return ret; + } + + /** + * Adds our event handler to the specified event bus, this MUST be called in order for this class to function. + * See the example usage. + * + * @param bus The Mod Specific event bus. + */ + public void register(IEventBus bus) { + bus.addListener(this::addEntries); + } + + /** + * @return The unmodifiable view of registered entries. Useful for bulk operations on all values. + */ + public Collection> getEntries() { + return entriesView; + } + + private void addEntries(RegistryEvent.Register event) { + if (event.getGenericType() == this.type.getRegistrySuperType()) { + @SuppressWarnings("unchecked") + IForgeRegistry reg = (IForgeRegistry) event.getRegistry(); + + for (Entry, Supplier> e : entries.entrySet()) { + reg.register(e.getValue().get()); + e.getKey().updateReference(reg); + } + } + } +} From 73765745a38273928f59a21c4a2076c8058d24ce Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Mon, 27 Jul 2020 18:22:02 -0400 Subject: [PATCH 21/73] Implement AnimalTameEvent (#152) * Implement AnimalTameEvent * Missed MCP -> Yarn names in a JavaDoc * HorseBoneWithPlayerGoal -> HorseBondWithPlayerGoal * Make event cancelable. * Remove unneeded ISE Co-authored-by: Glitch --- .../event/entity/living/AnimalTameEvent.java | 58 +++++++++++++++++++ .../impl/event/entity/EntityEvents.java | 6 ++ .../entity/MixinHorseBondWithPlayerGoal.java | 55 ++++++++++++++++++ .../mixin/event/entity/MixinOcelotEntity.java | 53 +++++++++++++++++ .../entity/MixinTameableEntitySubclass.java | 51 ++++++++++++++++ .../patchwork-events-entity.mixins.json | 5 +- .../event/ForgeEventFactory.java | 5 ++ 7 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java new file mode 100644 index 00000000..297ddbed --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java @@ -0,0 +1,58 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.living; + +import net.minecraftforge.common.MinecraftForge; + +import net.minecraft.entity.passive.AnimalEntity; +import net.minecraft.entity.player.PlayerEntity; + +/** + * This event is fired when an {@link AnimalEntity} is tamed. + * + *

It is fired via ForgeEventFactory#onAnimalTame(AnimalEntity, PlayerEntity). + * Forge fires this event for applicable vanilla animals, mods need to fire it themselves. + * This event is cancellable. If canceled, taming the animal will fail. + * This event is fired on the {@link MinecraftForge#EVENT_BUS}. + */ + +public class AnimalTameEvent extends LivingEvent { + private final AnimalEntity animal; + private final PlayerEntity tamer; + + public AnimalTameEvent(AnimalEntity animal, PlayerEntity tamer) { + super(animal); + this.animal = animal; + this.tamer = tamer; + } + + public AnimalEntity getAnimal() { + return animal; + } + + public PlayerEntity getTamer() { + return tamer; + } + + @Override + public boolean isCancelable() { + return true; + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index 73cf8679..1fd753cb 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -26,6 +26,7 @@ import net.minecraftforge.common.extensions.IForgeItem; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.living.AnimalTameEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingDamageEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; @@ -54,6 +55,7 @@ import net.minecraft.entity.SpawnType; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -196,6 +198,10 @@ public static void onItemTooltip(ItemStack itemStack, PlayerEntity entityPlayer, MinecraftForge.EVENT_BUS.post(new ItemTooltipEvent(itemStack, entityPlayer, list, flags)); } + public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { + return MinecraftForge.EVENT_BUS.post(new AnimalTameEvent(animal, tamer)); + } + @Override public void onInitialize() { UseItemCallback.EVENT.register((player, world, hand) -> { diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java new file mode 100644 index 00000000..2b1487ab --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java @@ -0,0 +1,55 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import java.util.Random; + +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.Redirect; + +import net.minecraft.entity.ai.goal.HorseBondWithPlayerGoal; +import net.minecraft.entity.passive.HorseBaseEntity; +import net.minecraft.entity.player.PlayerEntity; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(HorseBondWithPlayerGoal.class) +public class MixinHorseBondWithPlayerGoal { + @Shadow + @Final + private HorseBaseEntity horse; + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Ljava/util/Random;nextInt(I)I", ordinal = 1)) + private int redirectHorseBondWithPlayerCheck(Random random, int bound) { + int temper = horse.getTemper(); + int nextInt = random.nextInt(bound); + + if (nextInt < temper) { + if (EntityEvents.onAnimalTame(horse, (PlayerEntity) horse.getPassengerList().get(0))) { + return Integer.MAX_VALUE; // Force nextInt > temper + } + } + + return nextInt; + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java new file mode 100644 index 00000000..63d8a693 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java @@ -0,0 +1,53 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +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.entity.passive.AnimalEntity; +import net.minecraft.entity.passive.OcelotEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Hand; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(OcelotEntity.class) +public abstract class MixinOcelotEntity extends AnimalEntity { + @Shadow + protected abstract void showEmoteParticle(boolean positive); + + protected MixinOcelotEntity() { + //noinspection ConstantConditions + super(null, null); + } + + @Inject(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/OcelotEntity;setTrusting(Z)V"), cancellable = true) + private void onOcelotTrusting(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { + if (EntityEvents.onAnimalTame(this, player)) { + this.showEmoteParticle(false); + this.world.sendEntityStatus(this, (byte) 40); + cir.setReturnValue(true); + } + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java new file mode 100644 index 00000000..ee000af1 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java @@ -0,0 +1,51 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.passive.ParrotEntity; +import net.minecraft.entity.passive.TameableEntity; +import net.minecraft.entity.passive.WolfEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Hand; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +// CatEntity is intentionally omitted. See MinecraftForge/#7171 +@Mixin({ParrotEntity.class, WolfEntity.class}) +public abstract class MixinTameableEntitySubclass extends TameableEntity { + protected MixinTameableEntitySubclass() { + //noinspection ConstantConditions + super(null, null); + } + + @Inject(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/TameableEntity;setOwner(Lnet/minecraft/entity/player/PlayerEntity;)V"), cancellable = true) + private void onTamedMob(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { + if (EntityEvents.onAnimalTame(this, player)) { + this.showEmoteParticle(false); + this.world.sendEntityStatus(this, (byte) 6); + cir.setReturnValue(true); + } + } +} diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 081b587e..45e8b13b 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -7,19 +7,22 @@ "MixinEntityTrackerEntry", "MixinEntityType", "MixinExperienceOrbEntity", + "MixinHorseBondWithPlayerGoal", "MixinLivingEntity", "MixinMobEntity", "MixinMobSpawnerLogic", + "MixinOcelotEntity", "MixinPlayerEntity", "MixinPlayerManager", "MixinServerPlayerEntity", "MixinServerWorld", "MixinSpawnHelper", + "MixinTameableEntitySubclass", "MixinWorldChunk" ], "client": [ - "MixinClientWorld", "MixinClientPlayerEntity", + "MixinClientWorld", "MixinItemStack", "MixinOtherClientPlayerEntity" ], diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 8709d6b5..779dc74a 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -27,6 +27,7 @@ import net.minecraft.entity.SpawnType; import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.loot.LootManager; import net.minecraft.loot.LootTable; @@ -82,4 +83,8 @@ public static LootTable loadLootTable(Identifier name, LootTable table, LootMana public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { return WorldEvents.fireBlockHarvesting(drops, world, pos, state, fortune, dropChance, silkTouch, player); } + + public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { + return EntityEvents.onAnimalTame(animal, tamer); + } } From f7fc388b3f0497e59459328e24b71236396c9b9f Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Mon, 27 Jul 2020 21:15:29 -0500 Subject: [PATCH 22/73] Revert "Implement AnimalTameEvent (#152)" This reverts commit 73765745 --- .../event/entity/living/AnimalTameEvent.java | 58 ------------------- .../impl/event/entity/EntityEvents.java | 6 -- .../entity/MixinHorseBondWithPlayerGoal.java | 55 ------------------ .../mixin/event/entity/MixinOcelotEntity.java | 53 ----------------- .../entity/MixinTameableEntitySubclass.java | 51 ---------------- .../patchwork-events-entity.mixins.json | 5 +- .../event/ForgeEventFactory.java | 5 -- 7 files changed, 1 insertion(+), 232 deletions(-) delete mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java delete mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java delete mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java delete mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java deleted file mode 100644 index 297ddbed..00000000 --- a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.event.entity.living; - -import net.minecraftforge.common.MinecraftForge; - -import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.entity.player.PlayerEntity; - -/** - * This event is fired when an {@link AnimalEntity} is tamed. - * - *

It is fired via ForgeEventFactory#onAnimalTame(AnimalEntity, PlayerEntity). - * Forge fires this event for applicable vanilla animals, mods need to fire it themselves. - * This event is cancellable. If canceled, taming the animal will fail. - * This event is fired on the {@link MinecraftForge#EVENT_BUS}. - */ - -public class AnimalTameEvent extends LivingEvent { - private final AnimalEntity animal; - private final PlayerEntity tamer; - - public AnimalTameEvent(AnimalEntity animal, PlayerEntity tamer) { - super(animal); - this.animal = animal; - this.tamer = tamer; - } - - public AnimalEntity getAnimal() { - return animal; - } - - public PlayerEntity getTamer() { - return tamer; - } - - @Override - public boolean isCancelable() { - return true; - } -} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index 1fd753cb..73cf8679 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -26,7 +26,6 @@ import net.minecraftforge.common.extensions.IForgeItem; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; -import net.minecraftforge.event.entity.living.AnimalTameEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingDamageEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; @@ -55,7 +54,6 @@ import net.minecraft.entity.SpawnType; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.mob.MobEntity; -import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -198,10 +196,6 @@ public static void onItemTooltip(ItemStack itemStack, PlayerEntity entityPlayer, MinecraftForge.EVENT_BUS.post(new ItemTooltipEvent(itemStack, entityPlayer, list, flags)); } - public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { - return MinecraftForge.EVENT_BUS.post(new AnimalTameEvent(animal, tamer)); - } - @Override public void onInitialize() { UseItemCallback.EVENT.register((player, world, hand) -> { diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java deleted file mode 100644 index 2b1487ab..00000000 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.event.entity; - -import java.util.Random; - -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.Redirect; - -import net.minecraft.entity.ai.goal.HorseBondWithPlayerGoal; -import net.minecraft.entity.passive.HorseBaseEntity; -import net.minecraft.entity.player.PlayerEntity; - -import net.patchworkmc.impl.event.entity.EntityEvents; - -@Mixin(HorseBondWithPlayerGoal.class) -public class MixinHorseBondWithPlayerGoal { - @Shadow - @Final - private HorseBaseEntity horse; - - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Ljava/util/Random;nextInt(I)I", ordinal = 1)) - private int redirectHorseBondWithPlayerCheck(Random random, int bound) { - int temper = horse.getTemper(); - int nextInt = random.nextInt(bound); - - if (nextInt < temper) { - if (EntityEvents.onAnimalTame(horse, (PlayerEntity) horse.getPassengerList().get(0))) { - return Integer.MAX_VALUE; // Force nextInt > temper - } - } - - return nextInt; - } -} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java deleted file mode 100644 index 63d8a693..00000000 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.event.entity; - -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.entity.passive.AnimalEntity; -import net.minecraft.entity.passive.OcelotEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Hand; - -import net.patchworkmc.impl.event.entity.EntityEvents; - -@Mixin(OcelotEntity.class) -public abstract class MixinOcelotEntity extends AnimalEntity { - @Shadow - protected abstract void showEmoteParticle(boolean positive); - - protected MixinOcelotEntity() { - //noinspection ConstantConditions - super(null, null); - } - - @Inject(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/OcelotEntity;setTrusting(Z)V"), cancellable = true) - private void onOcelotTrusting(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { - if (EntityEvents.onAnimalTame(this, player)) { - this.showEmoteParticle(false); - this.world.sendEntityStatus(this, (byte) 40); - cir.setReturnValue(true); - } - } -} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java deleted file mode 100644 index ee000af1..00000000 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.event.entity; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import net.minecraft.entity.passive.ParrotEntity; -import net.minecraft.entity.passive.TameableEntity; -import net.minecraft.entity.passive.WolfEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Hand; - -import net.patchworkmc.impl.event.entity.EntityEvents; - -// CatEntity is intentionally omitted. See MinecraftForge/#7171 -@Mixin({ParrotEntity.class, WolfEntity.class}) -public abstract class MixinTameableEntitySubclass extends TameableEntity { - protected MixinTameableEntitySubclass() { - //noinspection ConstantConditions - super(null, null); - } - - @Inject(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/TameableEntity;setOwner(Lnet/minecraft/entity/player/PlayerEntity;)V"), cancellable = true) - private void onTamedMob(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { - if (EntityEvents.onAnimalTame(this, player)) { - this.showEmoteParticle(false); - this.world.sendEntityStatus(this, (byte) 6); - cir.setReturnValue(true); - } - } -} diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 45e8b13b..081b587e 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -7,22 +7,19 @@ "MixinEntityTrackerEntry", "MixinEntityType", "MixinExperienceOrbEntity", - "MixinHorseBondWithPlayerGoal", "MixinLivingEntity", "MixinMobEntity", "MixinMobSpawnerLogic", - "MixinOcelotEntity", "MixinPlayerEntity", "MixinPlayerManager", "MixinServerPlayerEntity", "MixinServerWorld", "MixinSpawnHelper", - "MixinTameableEntitySubclass", "MixinWorldChunk" ], "client": [ - "MixinClientPlayerEntity", "MixinClientWorld", + "MixinClientPlayerEntity", "MixinItemStack", "MixinOtherClientPlayerEntity" ], diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 779dc74a..8709d6b5 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -27,7 +27,6 @@ import net.minecraft.entity.SpawnType; import net.minecraft.entity.mob.MobEntity; -import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.loot.LootManager; import net.minecraft.loot.LootTable; @@ -83,8 +82,4 @@ public static LootTable loadLootTable(Identifier name, LootTable table, LootMana public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { return WorldEvents.fireBlockHarvesting(drops, world, pos, state, fortune, dropChance, silkTouch, player); } - - public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { - return EntityEvents.onAnimalTame(animal, tamer); - } } From 35cf663d430476558caa65703da8d17d0782c364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Thu, 30 Jul 2020 06:05:31 +1000 Subject: [PATCH 23/73] Impl PlayerChangedDimensionEvent, PlayerRespawnEvent and PlayerLoggedOutEvent (#118) * Impl PlayerChangedDimensionEvent, PlayerRespawnEvent and PlayerLoggedOutEvent * Impl ItemPickupEvent, ItemCraftedEvent, ItemSmeltedEvent in PlayerEvent * Add methods to the god class * Apply leo60228's suggestion --- .../event/entity/player/PlayerEvent.java | 138 +++++++++++++++--- .../impl/event/entity/EntityEvents.java | 6 - .../impl/event/entity/PlayerEvents.java | 59 ++++++++ .../event/entity/MixinCraftingResultSlot.java | 58 ++++++++ .../event/entity/MixinFurnaceOutputSlot.java | 47 ++++++ .../mixin/event/entity/MixinItemEntity.java | 47 ++++++ .../event/entity/MixinPlayerManager.java | 16 +- .../event/entity/MixinServerPlayerEntity.java | 57 ++++++++ .../patchwork-events-entity.mixins.json | 3 + .../fml/hooks/BasicEventHooks.java | 38 ++++- 10 files changed, 442 insertions(+), 27 deletions(-) create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinCraftingResultSlot.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFurnaceOutputSlot.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java index 4a0e47c9..42860d11 100644 --- a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java @@ -19,10 +19,16 @@ package net.minecraftforge.event.entity.player; +import javax.annotation.Nonnull; + import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.world.dimension.DimensionType; import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; /** * PlayerEvent is fired whenever an event involving Living entities occurs. @@ -57,16 +63,6 @@ public PlayerEntity getPlayer() { return playerEntity; } - /** - * Called on the server at the end of {@link net.minecraft.server.PlayerManager#onPlayerConnect(net.minecraft.network.ClientConnection, net.minecraft.server.network.ServerPlayerEntity)} - * when the player has finished logging in. - */ - public static class PlayerLoggedInEvent extends PlayerEvent { - public PlayerLoggedInEvent(PlayerEntity player) { - super(player); - } - } - /** * Fired when an Entity is started to be "tracked" by this player (the player receives updates about this entity, e.g. motion). */ @@ -131,17 +127,125 @@ public boolean isWasDeath() { } } + public static class ItemPickupEvent extends PlayerEvent { + /** + * Original EntityItem with current remaining stack size. + */ + private final ItemEntity originalEntity; + /** + * Clone item stack, containing the item and amount picked up. + */ + private final ItemStack stack; + + public ItemPickupEvent(PlayerEntity player, ItemEntity entPickedUp, ItemStack stack) { + super(player); + this.originalEntity = entPickedUp; + this.stack = stack; + } + + public ItemStack getStack() { + return stack; + } + + public ItemEntity getOriginalEntity() { + return originalEntity; + } + } + + public static class ItemCraftedEvent extends PlayerEvent { + @Nonnull + private final ItemStack crafting; + private final Inventory craftMatrix; + + public ItemCraftedEvent(PlayerEntity player, @Nonnull ItemStack crafting, Inventory craftMatrix) { + super(player); + this.crafting = crafting; + this.craftMatrix = craftMatrix; + } + + @Nonnull + public ItemStack getCrafting() { + return this.crafting; + } + + public Inventory getInventory() { + return this.craftMatrix; + } + } + + public static class ItemSmeltedEvent extends PlayerEvent { + @Nonnull + private final ItemStack smelting; + + public ItemSmeltedEvent(PlayerEntity player, @Nonnull ItemStack crafting) { + super(player); + this.smelting = crafting; + } + + @Nonnull + public ItemStack getSmelting() { + return this.smelting; + } + } + + /** + * Called on the server at the end of {@link net.minecraft.server.PlayerManager#onPlayerConnect(net.minecraft.network.ClientConnection, net.minecraft.server.network.ServerPlayerEntity)} + * when the player has finished logging in. + */ + public static class PlayerLoggedInEvent extends PlayerEvent { + public PlayerLoggedInEvent(PlayerEntity player) { + super(player); + } + } + + public static class PlayerLoggedOutEvent extends PlayerEvent { + public PlayerLoggedOutEvent(PlayerEntity player) { + super(player); + } + } + + public static class PlayerRespawnEvent extends PlayerEvent { + private final boolean alive; + + public PlayerRespawnEvent(PlayerEntity player, boolean alive) { + super(player); + this.alive = alive; + } + + /** + * Did this respawn event come from the player conquering the end? + * TODO: Forge should name this to isAlive. + * @return if this respawn was because the player conquered the end + */ + public boolean isEndConquered() { + return this.alive; + } + } + + public static class PlayerChangedDimensionEvent extends PlayerEvent { + private final DimensionType fromDim; + private final DimensionType toDim; + + public PlayerChangedDimensionEvent(PlayerEntity player, DimensionType fromDim, DimensionType toDim) { + super(player); + this.fromDim = fromDim; + this.toDim = toDim; + } + + public DimensionType getFrom() { + return this.fromDim; + } + + public DimensionType getTo() { + return this.toDim; + } + } + /*TODO Events: HarvestCheck BreakSpeed NameFormat LoadFromFile SaveToFile - Visibility - ItemPickupEvent - ItemCraftedEvent - ItemSmeltedEvent - PlayerLoggedOutEvent - PlayerRespawnEvent - PlayerChangedDimensionEvent*/ + Visibility called by ForgeHooks.getPlayerVisibilityDistance, but latter is not called elsewhere*/ } diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index 73cf8679..5f6e2c70 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -37,7 +37,6 @@ import net.minecraftforge.event.entity.living.LivingSpawnEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; import net.minecraftforge.event.entity.player.ItemTooltipEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerFlyableFallEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.Event; @@ -98,11 +97,6 @@ public static void onEnteringChunk(Entity entity, int newChunkX, int newChunkZ, MinecraftForge.EVENT_BUS.post(new EntityEvent.EnteringChunk(entity, newChunkX, newChunkZ, oldChunkX, oldChunkZ)); } - // PlayerEvents - public static void onPlayerLoggedIn(PlayerEntity playerEntity) { - MinecraftForge.EVENT_BUS.post(new PlayerEvent.PlayerLoggedInEvent(playerEntity)); - } - public static boolean onLivingAttack(LivingEntity entity, DamageSource src, float damage) { return MinecraftForge.EVENT_BUS.post(new LivingAttackEvent(entity, src, damage)); } diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java new file mode 100644 index 00000000..2ae93f40 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java @@ -0,0 +1,59 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.event.entity; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.PlayerEvent; + +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.world.dimension.DimensionType; + +public class PlayerEvents { + public static void firePlayerChangedDimensionEvent(PlayerEntity player, DimensionType fromDim, DimensionType toDim) { + MinecraftForge.EVENT_BUS.post(new PlayerEvent.PlayerChangedDimensionEvent(player, fromDim, toDim)); + } + + public static void firePlayerLoggedIn(PlayerEntity player) { + MinecraftForge.EVENT_BUS.post(new PlayerEvent.PlayerLoggedInEvent(player)); + } + + public static void firePlayerLoggedOut(PlayerEntity player) { + MinecraftForge.EVENT_BUS.post(new PlayerEvent.PlayerLoggedOutEvent(player)); + } + + public static void firePlayerRespawnEvent(PlayerEntity player, boolean alive) { + MinecraftForge.EVENT_BUS.post(new PlayerEvent.PlayerRespawnEvent(player, alive)); + } + + public static void firePlayerItemPickupEvent(PlayerEntity player, ItemEntity item, ItemStack clone) { + MinecraftForge.EVENT_BUS.post(new PlayerEvent.ItemPickupEvent(player, item, clone)); + } + + public static void firePlayerCraftingEvent(PlayerEntity player, ItemStack crafted, Inventory craftMatrix) { + MinecraftForge.EVENT_BUS.post(new PlayerEvent.ItemCraftedEvent(player, crafted, craftMatrix)); + } + + public static void firePlayerSmeltedEvent(PlayerEntity player, ItemStack smelted) { + MinecraftForge.EVENT_BUS.post(new PlayerEvent.ItemSmeltedEvent(player, smelted)); + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinCraftingResultSlot.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinCraftingResultSlot.java new file mode 100644 index 00000000..560c80cb --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinCraftingResultSlot.java @@ -0,0 +1,58 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +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.CallbackInfo; +import org.spongepowered.asm.mixin.injection.At.Shift; + +import net.minecraft.container.CraftingResultSlot; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.item.ItemStack; + +import net.patchworkmc.impl.event.entity.PlayerEvents; + +@Mixin(CraftingResultSlot.class) +public abstract class MixinCraftingResultSlot { + @Shadow + @Final + private PlayerEntity player; + + @Shadow + @Final + private CraftingInventory craftingInv; + + @Inject(method = "onCrafted(Lnet/minecraft/item/ItemStack;)V", + at = @At( + value = "INVOKE", + shift = Shift.AFTER, + ordinal = 0, + target = "net/minecraft/item/ItemStack.onCraft(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;I)V" + ) + ) + private void onStackCrafted(ItemStack stack, CallbackInfo ci) { + PlayerEvents.firePlayerCraftingEvent(player, stack, craftingInv); + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFurnaceOutputSlot.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFurnaceOutputSlot.java new file mode 100644 index 00000000..b79e43c2 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFurnaceOutputSlot.java @@ -0,0 +1,47 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +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.CallbackInfo; + +import net.minecraft.container.FurnaceOutputSlot; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; + +import net.patchworkmc.impl.event.entity.PlayerEvents; + +@Mixin(FurnaceOutputSlot.class) +public abstract class MixinFurnaceOutputSlot { + @Shadow + @Final + private PlayerEntity player; + + @Inject(method = "onCrafted(Lnet/minecraft/item/ItemStack;)V", + at = @At("RETURN") + ) + private void onCraftingFinished(ItemStack stack, CallbackInfo ci) { + PlayerEvents.firePlayerSmeltedEvent(player, stack); + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java new file mode 100644 index 00000000..5f1fccc4 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java @@ -0,0 +1,47 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +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 org.spongepowered.asm.mixin.injection.At.Shift; + +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; + +import net.patchworkmc.impl.event.entity.PlayerEvents; + +@Mixin(ItemEntity.class) +public abstract class MixinItemEntity { + @Inject(method = "onPlayerCollision", + at = @At( + value = "INVOKE", + shift = Shift.BEFORE, + ordinal = 0, + target = "net/minecraft/item/ItemStack.isEmpty()Z" + ) + ) + private void onPlayerPickUpItemEntity(PlayerEntity player, CallbackInfo ci) { + ItemEntity me = (ItemEntity) (Object) this; + PlayerEvents.firePlayerItemPickupEvent(player, me, me.getStack().copy()); + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinPlayerManager.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinPlayerManager.java index afe509d9..3669c9ff 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinPlayerManager.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinPlayerManager.java @@ -23,17 +23,29 @@ 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.network.ClientConnection; import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.world.dimension.DimensionType; -import net.patchworkmc.impl.event.entity.EntityEvents; +import net.patchworkmc.impl.event.entity.PlayerEvents; @Mixin(PlayerManager.class) public class MixinPlayerManager { @Inject(method = "onPlayerConnect", at = @At("RETURN")) private void hookPlayerLogin(ClientConnection connection, ServerPlayerEntity player, CallbackInfo callback) { - EntityEvents.onPlayerLoggedIn(player); + PlayerEvents.firePlayerLoggedIn(player); + } + + @Inject(method = "remove", at = @At("HEAD")) + private void hookPlayerLogout(ServerPlayerEntity player, CallbackInfo callback) { + PlayerEvents.firePlayerLoggedOut(player); + } + + @Inject(method = "respawnPlayer", at = @At("RETURN")) + private void hookPlayerRespawn(ServerPlayerEntity player, DimensionType dimension, boolean alive, CallbackInfoReturnable callback) { + PlayerEvents.firePlayerRespawnEvent(player, alive); } } diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java index 90bfc860..64585ce5 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java @@ -22,15 +22,24 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.PlayerEvent; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.level.LevelProperties; import net.patchworkmc.impl.event.entity.EntityEvents; +import net.patchworkmc.impl.event.entity.PlayerEvents; @Mixin(ServerPlayerEntity.class) public class MixinServerPlayerEntity { @@ -49,4 +58,52 @@ private void hookCopyFromForCloneEvent(ServerPlayerEntity oldPlayer, boolean ali ServerPlayerEntity speThis = (ServerPlayerEntity) (Object) this; MinecraftForge.EVENT_BUS.post(new PlayerEvent.Clone(speThis, oldPlayer, !alive)); } + + //////////////////////////////////// + // PlayerChangedDimensionEvent + //////////////////////////////////// + @Inject(method = "teleport", + at = @At( + value = "INVOKE", + shift = Shift.AFTER, + ordinal = 0, + target = "net/minecraft/server/PlayerManager.method_14594(Lnet/minecraft/server/network/ServerPlayerEntity;)V" + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) // PlayerManager.method_14594 -> sendInventory + private void teleport_sendInventory(ServerWorld targetWorld, double x, double y, double z, float yaw, float pitch, CallbackInfo info, ServerWorld serverWorld, LevelProperties levelProperties) { + ServerPlayerEntity me = (ServerPlayerEntity) (Object) this; + PlayerEvents.firePlayerChangedDimensionEvent(me, serverWorld.dimension.getType(), me.dimension); + } + + @Unique + private static final ThreadLocal changeDimension_from = new ThreadLocal<>(); + + @Inject(method = "changeDimension", + at = @At( + value = "INVOKE", + shift = Shift.AFTER, + ordinal = 0, + target = "net/minecraft/server/MinecraftServer.getWorld(Lnet/minecraft/world/dimension/DimensionType;)Lnet/minecraft/server/world/ServerWorld;" + ) + ) + private void changeDimension_getWorld(DimensionType newDimension, CallbackInfoReturnable info) { + ServerPlayerEntity me = (ServerPlayerEntity) (Object) this; + changeDimension_from.set(me.dimension); + } + + @Inject(method = "changeDimension", + at = @At( + value = "FIELD", + shift = Shift.AFTER, + ordinal = 0, + target = "net/minecraft/server/network/ServerPlayerEntity.field_13979:I" + ) + ) // ServerPlayerEntity.field_13979 -> lastFoodLevel + private void changeDimension_lastFoodLevel(DimensionType newDimension, CallbackInfoReturnable info) { + ServerPlayerEntity me = (ServerPlayerEntity) (Object) this; + DimensionType from = changeDimension_from.get(); + changeDimension_from.set(null); + PlayerEvents.firePlayerChangedDimensionEvent(me, from, newDimension); + } } diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 081b587e..5150404c 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -3,10 +3,13 @@ "package": "net.patchworkmc.mixin.event.entity", "compatibilityLevel": "JAVA_8", "mixins": [ + "MixinCraftingResultSlot", "MixinEntity", "MixinEntityTrackerEntry", "MixinEntityType", "MixinExperienceOrbEntity", + "MixinFurnaceOutputSlot", + "MixinItemEntity", "MixinLivingEntity", "MixinMobEntity", "MixinMobSpawnerLogic", diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java index ca968de2..b843dac4 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java @@ -21,10 +21,14 @@ import net.minecraftforge.event.TickEvent; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; -import net.patchworkmc.impl.event.entity.EntityEvents; +import net.patchworkmc.impl.event.entity.PlayerEvents; import net.patchworkmc.impl.event.lifecycle.LifecycleEvents; /* @@ -32,10 +36,37 @@ * Do not keep implementation details here, methods should be thin wrappers around methods in other modules. */ public class BasicEventHooks { + public static void firePlayerChangedDimensionEvent(PlayerEntity player, DimensionType fromDim, DimensionType toDim) { + PlayerEvents.firePlayerChangedDimensionEvent(player, fromDim, toDim); + } + public static void firePlayerLoggedIn(PlayerEntity player) { - EntityEvents.onPlayerLoggedIn(player); + PlayerEvents.firePlayerLoggedIn(player); + } + + public static void firePlayerLoggedOut(PlayerEntity player) { + PlayerEvents.firePlayerLoggedOut(player); + } + + public static void firePlayerRespawnEvent(PlayerEntity player, boolean endConquered) { + PlayerEvents.firePlayerRespawnEvent(player, endConquered); + } + + public static void firePlayerItemPickupEvent(PlayerEntity player, ItemEntity item, ItemStack clone) { + PlayerEvents.firePlayerItemPickupEvent(player, item, clone); + } + + public static void firePlayerCraftingEvent(PlayerEntity player, ItemStack crafted, Inventory craftMatrix) { + PlayerEvents.firePlayerCraftingEvent(player, crafted, craftMatrix); } + public static void firePlayerSmeltedEvent(PlayerEntity player, ItemStack smelted) { + PlayerEvents.firePlayerSmeltedEvent(player, smelted); + } + + // TODO: onRenderTickStart + // TODO: onRenderTickEnd + public static void onPlayerPreTick(PlayerEntity player) { LifecycleEvents.firePlayerTickEvent(TickEvent.Phase.START, player); } @@ -59,4 +90,7 @@ public static void onPreClientTick() { public static void onPostClientTick() { LifecycleEvents.fireClientTickEvent(TickEvent.Phase.END); } + + // TODO: onPreServerTick + // TODO: onPostServerTick } From cc2cdddf56c93ac6a330efeb73ce26707d725df0 Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Wed, 29 Jul 2020 17:48:56 -0400 Subject: [PATCH 24/73] Implement ItemFishedEvent (#147) * Implement ItemFishedEvent * Make event cancelable * Actually use the event's rod damage *

nit Co-authored-by: TheGlitch76 --- .../event/entity/player/ItemFishedEvent.java | 92 +++++++++++++++++++ .../entity/MixinFishingBobberEntity.java | 72 +++++++++++++++ .../patchwork-events-entity.mixins.json | 1 + 3 files changed, 165 insertions(+) create mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/ItemFishedEvent.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFishingBobberEntity.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/ItemFishedEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/ItemFishedEvent.java new file mode 100644 index 00000000..166ad91f --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/ItemFishedEvent.java @@ -0,0 +1,92 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.player; + +import java.util.List; + +import javax.annotation.Nonnegative; + +import com.google.common.base.Preconditions; + +import net.minecraft.entity.projectile.FishingBobberEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DefaultedList; + +/** + * This event is called when a player fishes an item. + * + *

This event is cancellable. + * Canceling the event will cause the player to receive no items at all. + * The hook will still take the damage specified

+ */ + +public class ItemFishedEvent extends PlayerEvent { + private final DefaultedList stacks = DefaultedList.of(); + private final FishingBobberEntity hook; + private int rodDamage; + + public ItemFishedEvent(List stacks, int rodDamage, FishingBobberEntity hook) { + super(hook.getOwner()); + this.stacks.addAll(stacks); + this.rodDamage = rodDamage; + this.hook = hook; + } + + /** + * Get the damage the rod will take. + * + * @return The damage the rod will take + */ + public int getRodDamage() { + return rodDamage; + } + + /** + * Specifies the amount of damage that the fishing rod should take. + * This is not added to the pre-existing damage to be taken. + * + * @param rodDamage The damage the rod will take. Must be nonnegative + */ + public void damageRodBy(@Nonnegative int rodDamage) { + Preconditions.checkArgument(rodDamage >= 0); + this.rodDamage = rodDamage; + } + + /** + * Use this to get the items the player will receive. + * You cannot use this to modify the drops the player will get. + * If you want to affect the loot, you should use LootTables. + */ + public DefaultedList getDrops() { + return stacks; + } + + /** + * Use this to stuff related to the hook itself, like the position of the bobber. + */ + public FishingBobberEntity getHookEntity() { + return hook; + } + + @Override + public boolean isCancelable() { + return true; + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFishingBobberEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFishingBobberEntity.java new file mode 100644 index 00000000..24731ac2 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFishingBobberEntity.java @@ -0,0 +1,72 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import java.util.List; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.ItemFishedEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import net.minecraft.entity.projectile.FishingBobberEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.LootTable; +import net.minecraft.loot.context.LootContext; + +@Mixin(FishingBobberEntity.class) +public abstract class MixinFishingBobberEntity { + @Shadow + private boolean field_7176; // is stuck to block + + @Shadow + public abstract void remove(); + + @Unique + private final ThreadLocal rodDamage = ThreadLocal.withInitial(() -> -1); + + @Inject(method = "method_6957", at = @At(value = "INVOKE", target = "Lnet/minecraft/advancement/criterion/FishingRodHookedCriterion;trigger(Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/projectile/FishingBobberEntity;Ljava/util/Collection;)V", ordinal = 1), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) + private void onReeledIn(ItemStack itemStack, CallbackInfoReturnable cir, int i, LootContext.Builder builder, LootTable lootTable, List list) { + ItemFishedEvent event = new ItemFishedEvent(list, this.field_7176 ? 2 : 1, (FishingBobberEntity) (Object) this); + MinecraftForge.EVENT_BUS.post(event); + + if (event.isCanceled()) { + this.remove(); + cir.setReturnValue(event.getRodDamage()); + } else { + rodDamage.set(event.getRodDamage()); + } + } + + @Inject(method = "method_6957", at = @At("RETURN"), cancellable = true) + private void onRodDamage(ItemStack itemStack, CallbackInfoReturnable cir) { + Integer damage = rodDamage.get(); + + if (damage != -1) { + cir.setReturnValue(damage); + rodDamage.set(-1); + } + } +} diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 5150404c..090fec9e 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -8,6 +8,7 @@ "MixinEntityTrackerEntry", "MixinEntityType", "MixinExperienceOrbEntity", + "MixinFishingBobberEntity", "MixinFurnaceOutputSlot", "MixinItemEntity", "MixinLivingEntity", From 9d5cca02880a82cdcaff632de6c3b2b2c13bb794 Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Wed, 29 Jul 2020 17:57:34 -0400 Subject: [PATCH 25/73] AnimalTameEvent 2: Electric Boogaloo (#156) * Implement AnimalTameEvent * Missed MCP -> Yarn names in a JavaDoc * HorseBoneWithPlayerGoal -> HorseBondWithPlayerGoal * Make event cancelable. * Remove unneeded ISE * Replace cursed Inject with less cursed Redirect * Remove trailing whitespace Co-authored-by: Glitch --- .../event/entity/living/AnimalTameEvent.java | 58 +++++++++++++++++++ .../impl/event/entity/EntityEvents.java | 6 ++ .../entity/MixinHorseBondWithPlayerGoal.java | 55 ++++++++++++++++++ .../mixin/event/entity/MixinOcelotEntity.java | 53 +++++++++++++++++ .../entity/MixinTameableEntitySubclass.java | 54 +++++++++++++++++ .../patchwork-events-entity.mixins.json | 1 + .../event/ForgeEventFactory.java | 5 ++ 7 files changed, 232 insertions(+) create mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java new file mode 100644 index 00000000..297ddbed --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/living/AnimalTameEvent.java @@ -0,0 +1,58 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.living; + +import net.minecraftforge.common.MinecraftForge; + +import net.minecraft.entity.passive.AnimalEntity; +import net.minecraft.entity.player.PlayerEntity; + +/** + * This event is fired when an {@link AnimalEntity} is tamed. + * + *

It is fired via ForgeEventFactory#onAnimalTame(AnimalEntity, PlayerEntity). + * Forge fires this event for applicable vanilla animals, mods need to fire it themselves. + * This event is cancellable. If canceled, taming the animal will fail. + * This event is fired on the {@link MinecraftForge#EVENT_BUS}. + */ + +public class AnimalTameEvent extends LivingEvent { + private final AnimalEntity animal; + private final PlayerEntity tamer; + + public AnimalTameEvent(AnimalEntity animal, PlayerEntity tamer) { + super(animal); + this.animal = animal; + this.tamer = tamer; + } + + public AnimalEntity getAnimal() { + return animal; + } + + public PlayerEntity getTamer() { + return tamer; + } + + @Override + public boolean isCancelable() { + return true; + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index 5f6e2c70..96f57705 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -26,6 +26,7 @@ import net.minecraftforge.common.extensions.IForgeItem; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.living.AnimalTameEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingDamageEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; @@ -53,6 +54,7 @@ import net.minecraft.entity.SpawnType; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -190,6 +192,10 @@ public static void onItemTooltip(ItemStack itemStack, PlayerEntity entityPlayer, MinecraftForge.EVENT_BUS.post(new ItemTooltipEvent(itemStack, entityPlayer, list, flags)); } + public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { + return MinecraftForge.EVENT_BUS.post(new AnimalTameEvent(animal, tamer)); + } + @Override public void onInitialize() { UseItemCallback.EVENT.register((player, world, hand) -> { diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java new file mode 100644 index 00000000..2b1487ab --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinHorseBondWithPlayerGoal.java @@ -0,0 +1,55 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import java.util.Random; + +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.Redirect; + +import net.minecraft.entity.ai.goal.HorseBondWithPlayerGoal; +import net.minecraft.entity.passive.HorseBaseEntity; +import net.minecraft.entity.player.PlayerEntity; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(HorseBondWithPlayerGoal.class) +public class MixinHorseBondWithPlayerGoal { + @Shadow + @Final + private HorseBaseEntity horse; + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Ljava/util/Random;nextInt(I)I", ordinal = 1)) + private int redirectHorseBondWithPlayerCheck(Random random, int bound) { + int temper = horse.getTemper(); + int nextInt = random.nextInt(bound); + + if (nextInt < temper) { + if (EntityEvents.onAnimalTame(horse, (PlayerEntity) horse.getPassengerList().get(0))) { + return Integer.MAX_VALUE; // Force nextInt > temper + } + } + + return nextInt; + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java new file mode 100644 index 00000000..63d8a693 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinOcelotEntity.java @@ -0,0 +1,53 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +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.entity.passive.AnimalEntity; +import net.minecraft.entity.passive.OcelotEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Hand; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(OcelotEntity.class) +public abstract class MixinOcelotEntity extends AnimalEntity { + @Shadow + protected abstract void showEmoteParticle(boolean positive); + + protected MixinOcelotEntity() { + //noinspection ConstantConditions + super(null, null); + } + + @Inject(method = "interactMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/OcelotEntity;setTrusting(Z)V"), cancellable = true) + private void onOcelotTrusting(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { + if (EntityEvents.onAnimalTame(this, player)) { + this.showEmoteParticle(false); + this.world.sendEntityStatus(this, (byte) 40); + cir.setReturnValue(true); + } + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java new file mode 100644 index 00000000..3151c730 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinTameableEntitySubclass.java @@ -0,0 +1,54 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import java.util.Random; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.entity.passive.ParrotEntity; +import net.minecraft.entity.passive.TameableEntity; +import net.minecraft.entity.passive.WolfEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Hand; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +// CatEntity is intentionally omitted. See MinecraftForge/#7171 +@Mixin({ParrotEntity.class, WolfEntity.class}) +public abstract class MixinTameableEntitySubclass extends TameableEntity { + protected MixinTameableEntitySubclass() { + //noinspection ConstantConditions + super(null, null); + } + + @Redirect(method = "interactMob", at = @At(value = "INVOKE", target = "Ljava/util/Random;nextInt(I)I")) + private int redirectTameCheck(Random random, int bound, PlayerEntity player, Hand hand) { + int i = random.nextInt(bound); + + if (i != 0 || EntityEvents.onAnimalTame(this, player)) { + return -1; // Check failed + } + + return 0; // Check succeeds + } +} diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 090fec9e..7c76cbce 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -10,6 +10,7 @@ "MixinExperienceOrbEntity", "MixinFishingBobberEntity", "MixinFurnaceOutputSlot", + "MixinHorseBondWithPlayerGoal", "MixinItemEntity", "MixinLivingEntity", "MixinMobEntity", diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 8709d6b5..779dc74a 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -27,6 +27,7 @@ import net.minecraft.entity.SpawnType; import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.loot.LootManager; import net.minecraft.loot.LootTable; @@ -82,4 +83,8 @@ public static LootTable loadLootTable(Identifier name, LootTable table, LootMana public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { return WorldEvents.fireBlockHarvesting(drops, world, pos, state, fortune, dropChance, silkTouch, player); } + + public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { + return EntityEvents.onAnimalTame(animal, tamer); + } } From 5cb31ac45f03df5ae24cfcaa0e87c6dbe58cb74f Mon Sep 17 00:00:00 2001 From: Snakefangox Date: Thu, 30 Jul 2020 12:16:17 +1200 Subject: [PATCH 26/73] Add support for keybindings (#154) * Added patchwork-key-bindings * Added patchwork keybinding for Patcher Cleaning up remaining absolute imports * Fix missing import * Fix archive base name * Fix folders, paths and project names * Fix KeyBinding names and add @Unique * Should probably respect keybind context * Remove now incorrect comment Co-authored-by: Glitch Co-authored-by: Glitch --- patchwork-key-bindings/build.gradle | 2 + .../client/extensions/IForgeKeybinding.java | 69 ++++++++ .../client/settings/IKeyConflictContext.java | 37 +++++ .../client/settings/KeyConflictContext.java | 70 ++++++++ .../client/settings/KeyModifier.java | 150 ++++++++++++++++++ .../keybindings/ForgeKeyBindingConstruct.java | 27 ++++ .../impl/keybindings/PatchworkKeybinding.java | 61 +++++++ .../mixin/keybindings/MixinKeyBinding.java | 103 ++++++++++++ .../assets/patchwork-key-bindings/icon.png | Bin 0 -> 22738 bytes .../src/main/resources/fabric.mod.json | 26 +++ .../patchwork-key-bindings.mixins.json | 11 ++ settings.gradle | 1 + 12 files changed, 557 insertions(+) create mode 100644 patchwork-key-bindings/build.gradle create mode 100644 patchwork-key-bindings/src/main/java/net/minecraftforge/client/extensions/IForgeKeybinding.java create mode 100644 patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/IKeyConflictContext.java create mode 100644 patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/KeyConflictContext.java create mode 100644 patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/KeyModifier.java create mode 100644 patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/ForgeKeyBindingConstruct.java create mode 100644 patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/PatchworkKeybinding.java create mode 100644 patchwork-key-bindings/src/main/java/net/patchworkmc/mixin/keybindings/MixinKeyBinding.java create mode 100644 patchwork-key-bindings/src/main/resources/assets/patchwork-key-bindings/icon.png create mode 100644 patchwork-key-bindings/src/main/resources/fabric.mod.json create mode 100644 patchwork-key-bindings/src/main/resources/patchwork-key-bindings.mixins.json diff --git a/patchwork-key-bindings/build.gradle b/patchwork-key-bindings/build.gradle new file mode 100644 index 00000000..65673173 --- /dev/null +++ b/patchwork-key-bindings/build.gradle @@ -0,0 +1,2 @@ +archivesBaseName = "patchwork-key-bindings" +version = getSubprojectVersion(project, "0.1.0") diff --git a/patchwork-key-bindings/src/main/java/net/minecraftforge/client/extensions/IForgeKeybinding.java b/patchwork-key-bindings/src/main/java/net/minecraftforge/client/extensions/IForgeKeybinding.java new file mode 100644 index 00000000..ee2384ac --- /dev/null +++ b/patchwork-key-bindings/src/main/java/net/minecraftforge/client/extensions/IForgeKeybinding.java @@ -0,0 +1,69 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.extensions; + +import javax.annotation.Nonnull; + +import net.minecraftforge.client.settings.IKeyConflictContext; +import net.minecraftforge.client.settings.KeyModifier; + +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.InputUtil; + +public interface IForgeKeybinding { + default KeyBinding getKeyBinding() { + return (KeyBinding) this; + } + + @Nonnull + InputUtil.KeyCode getKey(); + + /** + * Checks that the key conflict context and modifier are active, and that the keyCode matches this binding. + */ + default boolean isActiveAndMatches(InputUtil.KeyCode keyCode) { + return keyCode.getKeyCode() != 0 && keyCode.equals(getKey()) && getKeyConflictContext().isActive() && getKeyModifier().isActive(getKeyConflictContext()); + } + + default void setToDefault() { + setKeyModifierAndCode(getKeyModifierDefault(), getKeyBinding().getDefaultKeyCode()); + } + + IKeyConflictContext getKeyConflictContext(); + + void setKeyConflictContext(IKeyConflictContext keyConflictContext); + + KeyModifier getKeyModifierDefault(); + + KeyModifier getKeyModifier(); + + void setKeyModifierAndCode(KeyModifier keyModifier, InputUtil.KeyCode keyCode); + + /** + * Returns true when one of the bindings' key codes conflicts with the other's modifier. + */ + default boolean hasKeyCodeModifierConflict(KeyBinding other) { + if (getKeyConflictContext().conflicts(((IForgeKeybinding) other).getKeyConflictContext()) || ((IForgeKeybinding) other).getKeyConflictContext().conflicts(getKeyConflictContext())) { + return getKeyModifier().matches(((IForgeKeybinding) other).getKey()) || ((IForgeKeybinding) other).getKeyModifier().matches(getKey()); + } + + return false; + } +} diff --git a/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/IKeyConflictContext.java b/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/IKeyConflictContext.java new file mode 100644 index 00000000..78515753 --- /dev/null +++ b/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/IKeyConflictContext.java @@ -0,0 +1,37 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.settings; + +/** + * Defines the context that a {@link KeyBinding} is used. + * Key conflicts occur when a {@link KeyBinding} has the same {@link IKeyConflictContext} and has conflicting modifiers and keyCodes. + */ +public interface IKeyConflictContext { + /** + * @return true if conditions are met to activate {@link KeyBinding}s with this context + */ + boolean isActive(); + + /** + * @return true if the other context can have {@link KeyBinding} conflicts with this one. + * This will be called on both contexts to check for conflicts. + */ + boolean conflicts(IKeyConflictContext other); +} diff --git a/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/KeyConflictContext.java b/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/KeyConflictContext.java new file mode 100644 index 00000000..b0ae3034 --- /dev/null +++ b/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/KeyConflictContext.java @@ -0,0 +1,70 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.settings; + +import net.minecraft.client.MinecraftClient; + +public enum KeyConflictContext implements IKeyConflictContext { + /** + * Universal key bindings are used in every context and will conflict with any other context. + * Key Bindings are universal by default. + */ + UNIVERSAL { + @Override + public boolean isActive() { + return true; + } + + @Override + public boolean conflicts(IKeyConflictContext other) { + return true; + } + }, + + /** + * Gui key bindings are only used when a {@link GuiScreen} is open. + */ + GUI { + @Override + public boolean isActive() { + return MinecraftClient.getInstance().currentScreen != null; + } + + @Override + public boolean conflicts(IKeyConflictContext other) { + return this == other; + } + }, + + /** + * In-game key bindings are only used when a {@link GuiScreen} is not open. + */ + IN_GAME { + @Override + public boolean isActive() { + return !GUI.isActive(); + } + + @Override + public boolean conflicts(IKeyConflictContext other) { + return this == other; + } + } +} diff --git a/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/KeyModifier.java b/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/KeyModifier.java new file mode 100644 index 00000000..22cb1165 --- /dev/null +++ b/patchwork-key-bindings/src/main/java/net/minecraftforge/client/settings/KeyModifier.java @@ -0,0 +1,150 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.settings; + +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import org.lwjgl.glfw.GLFW; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.client.util.InputUtil; + +public enum KeyModifier { + CONTROL { + @Override + public boolean matches(InputUtil.KeyCode key) { + int keyCode = key.getKeyCode(); + + if (MinecraftClient.IS_SYSTEM_MAC) { + return keyCode == GLFW.GLFW_KEY_LEFT_ALT || keyCode == GLFW.GLFW_KEY_RIGHT_ALT; + } else { + return keyCode == GLFW.GLFW_KEY_LEFT_CONTROL || keyCode == GLFW.GLFW_KEY_RIGHT_CONTROL; + } + } + + @Override + public boolean isActive(@Nullable IKeyConflictContext conflictContext) { + return Screen.hasControlDown(); + } + + @Override + public String getLocalizedComboName(InputUtil.KeyCode key, Supplier defaultLogic) { + String keyName = defaultLogic.get(); + String localizationFormatKey = MinecraftClient.IS_SYSTEM_MAC ? "forge.controlsgui.control.mac" : "forge.controlsgui.control"; + return I18n.translate(localizationFormatKey, keyName); + } + }, + SHIFT { + @Override + public boolean matches(InputUtil.KeyCode key) { + return key.getKeyCode() == GLFW.GLFW_KEY_LEFT_SHIFT || key.getKeyCode() == GLFW.GLFW_KEY_RIGHT_SHIFT; + } + + @Override + public boolean isActive(@Nullable IKeyConflictContext conflictContext) { + return Screen.hasShiftDown(); + } + + @Override + public String getLocalizedComboName(InputUtil.KeyCode key, Supplier defaultLogic) { + return I18n.translate("forge.controlsgui.shift", defaultLogic.get()); + } + }, + ALT { + @Override + public boolean matches(InputUtil.KeyCode key) { + return key.getKeyCode() == GLFW.GLFW_KEY_LEFT_ALT || key.getKeyCode() == GLFW.GLFW_KEY_RIGHT_ALT; + } + + @Override + public boolean isActive(@Nullable IKeyConflictContext conflictContext) { + return Screen.hasAltDown(); + } + + @Override + public String getLocalizedComboName(InputUtil.KeyCode keyCode, Supplier defaultLogic) { + return I18n.translate("forge.controlsgui.alt", defaultLogic.get()); + } + }, + NONE { + @Override + public boolean matches(InputUtil.KeyCode key) { + return false; + } + + @Override + public boolean isActive(@Nullable IKeyConflictContext conflictContext) { + if (conflictContext != null && !conflictContext.conflicts(KeyConflictContext.IN_GAME)) { + for (KeyModifier keyModifier : MODIFIER_VALUES) { + if (keyModifier.isActive(conflictContext)) { + return false; + } + } + } + + return true; + } + + @Override + public String getLocalizedComboName(InputUtil.KeyCode key, Supplier defaultLogic) { + return defaultLogic.get(); + } + }; + + public static final KeyModifier[] MODIFIER_VALUES = {SHIFT, CONTROL, ALT}; + + public static KeyModifier getActiveModifier() { + for (KeyModifier keyModifier : MODIFIER_VALUES) { + if (keyModifier.isActive(null)) { + return keyModifier; + } + } + + return NONE; + } + + public static boolean isKeyCodeModifier(InputUtil.KeyCode key) { + for (KeyModifier keyModifier : MODIFIER_VALUES) { + if (keyModifier.matches(key)) { + return true; + } + } + + return false; + } + + public static KeyModifier valueFromString(String stringValue) { + try { + return valueOf(stringValue); + } catch (NullPointerException | IllegalArgumentException ignored) { + return NONE; + } + } + + public abstract boolean matches(InputUtil.KeyCode key); + + public abstract boolean isActive(@Nullable IKeyConflictContext conflictContext); + + public abstract String getLocalizedComboName(InputUtil.KeyCode key, Supplier defaultLogic); +} diff --git a/patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/ForgeKeyBindingConstruct.java b/patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/ForgeKeyBindingConstruct.java new file mode 100644 index 00000000..29217348 --- /dev/null +++ b/patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/ForgeKeyBindingConstruct.java @@ -0,0 +1,27 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.keybindings; + +import net.minecraftforge.client.settings.IKeyConflictContext; +import net.minecraftforge.client.settings.KeyModifier; + +public interface ForgeKeyBindingConstruct { + void patchwork$constructForgeKeyBindingOptions(IKeyConflictContext keyConflictContext, KeyModifier keyModifier); +} diff --git a/patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/PatchworkKeybinding.java b/patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/PatchworkKeybinding.java new file mode 100644 index 00000000..a4aef14c --- /dev/null +++ b/patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/PatchworkKeybinding.java @@ -0,0 +1,61 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.keybindings; + +import net.minecraftforge.client.extensions.IForgeKeybinding; +import net.minecraftforge.client.settings.IKeyConflictContext; +import net.minecraftforge.client.settings.KeyModifier; + +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.InputUtil; + +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; + +public class PatchworkKeybinding extends KeyBinding { + public PatchworkKeybinding(String id, int keyCode, String category) { + super(id, keyCode, category); + KeyBindingHelper.registerKeyBinding(this); + } + + public PatchworkKeybinding(String id, InputUtil.Type type, int code, String category) { + super(id, type, code, category); + KeyBindingHelper.registerKeyBinding(this); + } + + public PatchworkKeybinding(String id, IKeyConflictContext keyConflictContext, final InputUtil.Type inputType, final int keyCode, String category) { + this(id, keyConflictContext, inputType.createFromCode(keyCode), category); + } + + public PatchworkKeybinding(String id, IKeyConflictContext keyConflictContext, InputUtil.KeyCode keyCode, String category) { + this(id, keyConflictContext, KeyModifier.NONE, keyCode, category); + } + + public PatchworkKeybinding(String id, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, final InputUtil.Type inputType, final int keyCode, String category) { + this(id, keyConflictContext, keyModifier, inputType.createFromCode(keyCode), category); + } + + public PatchworkKeybinding(String id, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, InputUtil.KeyCode keyCode, String category) { + super(id, keyCode.getCategory(), keyCode.getKeyCode(), category); + ((IForgeKeybinding) this).setKeyConflictContext(keyConflictContext); + ((IForgeKeybinding) this).setKeyModifierAndCode(keyModifier, keyCode); + ((ForgeKeyBindingConstruct) this).patchwork$constructForgeKeyBindingOptions(keyConflictContext, keyModifier.matches(keyCode) ? KeyModifier.NONE : keyModifier); + KeyBindingHelper.registerKeyBinding(this); + } +} diff --git a/patchwork-key-bindings/src/main/java/net/patchworkmc/mixin/keybindings/MixinKeyBinding.java b/patchwork-key-bindings/src/main/java/net/patchworkmc/mixin/keybindings/MixinKeyBinding.java new file mode 100644 index 00000000..ad2bcff2 --- /dev/null +++ b/patchwork-key-bindings/src/main/java/net/patchworkmc/mixin/keybindings/MixinKeyBinding.java @@ -0,0 +1,103 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.keybindings; + +import net.minecraftforge.client.extensions.IForgeKeybinding; +import net.minecraftforge.client.settings.IKeyConflictContext; +import net.minecraftforge.client.settings.KeyConflictContext; +import net.minecraftforge.client.settings.KeyModifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.InputUtil; + +import net.patchworkmc.impl.keybindings.ForgeKeyBindingConstruct; + +@Mixin(KeyBinding.class) +public abstract class MixinKeyBinding implements Comparable, IForgeKeybinding, ForgeKeyBindingConstruct { + @Shadow + private InputUtil.KeyCode keyCode; + + // These exist in forge to allow modifiers and conflicting keys to work, this is not implemented + // but these remain to avoid stubbing the methods + @Unique + private KeyModifier keyModifierDefault = KeyModifier.NONE; + @Unique + private KeyModifier keyModifier = KeyModifier.NONE; + @Unique + private IKeyConflictContext keyConflictContext = KeyConflictContext.UNIVERSAL; + + @Inject(method = "isPressed()Z", at = @At("HEAD")) + public void isPressed(CallbackInfoReturnable info) { + if (!getKeyConflictContext().isActive()) { + info.setReturnValue(false); + info.cancel(); + } + } + + @Override + public InputUtil.KeyCode getKey() { + return this.keyCode; + } + + @Override + public IKeyConflictContext getKeyConflictContext() { + return keyConflictContext; + } + + @Override + public void setKeyConflictContext(IKeyConflictContext keyConflictContext) { + this.keyConflictContext = keyConflictContext; + } + + @Override + public KeyModifier getKeyModifierDefault() { + return keyModifierDefault; + } + + @Override + public KeyModifier getKeyModifier() { + return keyModifier; + } + + @Override + public void setKeyModifierAndCode(KeyModifier keyModifier, InputUtil.KeyCode keyCode) { + this.keyCode = keyCode; + + if (keyModifier.matches(keyCode)) { + keyModifier = KeyModifier.NONE; + } + + this.keyModifier = keyModifier; + KeyBinding.updateKeysByCode(); + } + + @Override + public void patchwork$constructForgeKeyBindingOptions(IKeyConflictContext keyConflictContext, KeyModifier keyModifier) { + this.keyModifier = keyModifier; + this.keyModifierDefault = keyModifier; + this.keyConflictContext = keyConflictContext; + } +} diff --git a/patchwork-key-bindings/src/main/resources/assets/patchwork-key-bindings/icon.png b/patchwork-key-bindings/src/main/resources/assets/patchwork-key-bindings/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-key-bindings/src/main/resources/fabric.mod.json b/patchwork-key-bindings/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..237e9f94 --- /dev/null +++ b/patchwork-key-bindings/src/main/resources/fabric.mod.json @@ -0,0 +1,26 @@ +{ + "schemaVersion": 1, + "id": "patchwork-key-bindings", + "name": "Patchwork Keybindings", + "version": "${version}", + "license": "LGPL-2.1-only", + "icon": "assets/patchwork-key-bindings/icon.png", + "contact": { + "issues": "https://github.com/PatchworkMC/patchwork-api/issues", + "sources": "https://github.com/PatchworkMC/patchwork-api" + }, + "authors": [ + "PatchworkMC" + ], + "depends": { + "fabricloader": ">=0.8.4" + }, + "mixins": [ + "patchwork-key-bindings.mixins.json" + ], + "description": "Implementation of the Forge Keybinding system.", + "custom": { + "modmenu:api": true, + "modmenu:parent": "patchwork" + } +} diff --git a/patchwork-key-bindings/src/main/resources/patchwork-key-bindings.mixins.json b/patchwork-key-bindings/src/main/resources/patchwork-key-bindings.mixins.json new file mode 100644 index 00000000..98f3d6ad --- /dev/null +++ b/patchwork-key-bindings/src/main/resources/patchwork-key-bindings.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.keybindings", + "compatibilityLevel": "JAVA_8", + "client": [ + "MixinKeyBinding" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/settings.gradle b/settings.gradle index 93f1e690..9cd4535f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,6 +29,7 @@ include 'patchwork-extensions-shearing' include 'patchwork-fml' include 'patchwork-god-classes' include 'patchwork-gui' +include 'patchwork-key-bindings' include 'patchwork-level-generators' include 'patchwork-loot' include 'patchwork-model-loader' From f76e5dbd1a72fcbcecd549d1f09f63c0123f8db4 Mon Sep 17 00:00:00 2001 From: Gamma <20158146+GammaWhiskey@users.noreply.github.com> Date: Wed, 29 Jul 2020 22:24:25 -0400 Subject: [PATCH 27/73] Impl ServerTickEvent and RenderTickEvent (#158) * Impl TickEvent.ServerTickEvent with FAPI Lifecycle Events V1 * Impl TickEvent.RenderTickEvent * Add ServerTick and RenderTick events to BasicEventHooks * Fix style * Shift hookRenderTickEnd to match Forge * Fix style after merge conflict resolution * Reduce ordinal on hookRenderTickEvent with slice --- .../net/minecraftforge/event/TickEvent.java | 8 ++--- .../impl/event/lifecycle/LifecycleEvents.java | 13 ++++++++ .../event/lifecycle/MixinMinecraftClient.java | 33 +++++++++++++++++++ .../src/main/resources/fabric.mod.json | 1 + .../fml/hooks/BasicEventHooks.java | 17 ++++++++-- 5 files changed, 66 insertions(+), 6 deletions(-) diff --git a/patchwork-events-lifecycle/src/main/java/net/minecraftforge/event/TickEvent.java b/patchwork-events-lifecycle/src/main/java/net/minecraftforge/event/TickEvent.java index b05ac040..16e4ac59 100644 --- a/patchwork-events-lifecycle/src/main/java/net/minecraftforge/event/TickEvent.java +++ b/patchwork-events-lifecycle/src/main/java/net/minecraftforge/event/TickEvent.java @@ -45,11 +45,11 @@ public enum Phase { START, END; } - /* TODO public static class ServerTickEvent extends TickEvent { + public static class ServerTickEvent extends TickEvent { public ServerTickEvent(Phase phase) { super(Type.SERVER, LogicalSide.SERVER, phase); } - }*/ + } public static class ClientTickEvent extends TickEvent { public ClientTickEvent(Phase phase) { @@ -77,12 +77,12 @@ public PlayerTickEvent(Phase phase, PlayerEntity player) { } } - /* TODO public static class RenderTickEvent extends TickEvent { + public static class RenderTickEvent extends TickEvent { public final float renderTickTime; public RenderTickEvent(Phase phase, float renderTickTime) { super(Type.RENDER, LogicalSide.CLIENT, phase); this.renderTickTime = renderTickTime; } - }*/ + } } diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java index 5dd0e083..1e4646f4 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java @@ -42,6 +42,7 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.server.ServerStartCallback; import net.fabricmc.fabric.api.event.world.WorldTickCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; public class LifecycleEvents implements ModInitializer { private static Runnable loadCompleteCallback; @@ -57,6 +58,15 @@ public static void fireClientTickEvent(TickEvent.Phase phase) { MinecraftForge.EVENT_BUS.post(new TickEvent.ClientTickEvent(phase)); } + public static void fireRenderTickEvent(TickEvent.Phase phase, float renderTickTime) { + // TODO - Call net.minecraftforge.client.model.animation.Animation#setClientPartialTickTime on start phase + MinecraftForge.EVENT_BUS.post(new TickEvent.RenderTickEvent(phase, renderTickTime)); + } + + public static void fireServerTickEvent(TickEvent.Phase phase) { + MinecraftForge.EVENT_BUS.post(new TickEvent.ServerTickEvent(phase)); + } + public static void firePlayerTickEvent(TickEvent.Phase phase, PlayerEntity player) { MinecraftForge.EVENT_BUS.post(new TickEvent.PlayerTickEvent(phase, player)); } @@ -126,5 +136,8 @@ public void onInitialize() { throw new UnsupportedOperationException("A mod tried to set the server's motd during handling FMLServerStartedEvent, this isn't implemented yet."); } }); + + ServerTickEvents.START_SERVER_TICK.register(server -> fireServerTickEvent(TickEvent.Phase.START)); + ServerTickEvents.END_SERVER_TICK.register(server -> fireServerTickEvent(TickEvent.Phase.END)); } } diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftClient.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftClient.java index d1e5d76d..8e51e2f6 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftClient.java +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftClient.java @@ -19,14 +19,18 @@ package net.patchworkmc.mixin.event.lifecycle; +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.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.objectweb.asm.Opcodes; import net.minecraftforge.event.TickEvent; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.RenderTickCounter; import net.patchworkmc.impl.event.lifecycle.LifecycleEvents; @@ -51,4 +55,33 @@ private void hookClientTickEnd(CallbackInfo info) { private void hookClientInit(CallbackInfo ci) { LifecycleEvents.handleLoadComplete(); } + + @Shadow + @Final + private RenderTickCounter renderTickCounter; + + // Note: for some reason, ordinal does not consider ldc, which means ldc is completely useless here. + // It's kept here for the sake of reference/readability only. + @Inject(method = "render", at = @At( + value = "INVOKE_STRING", + target = "net/minecraft/util/profiler/DisableableProfiler.swap(Ljava/lang/String;)V", + args = "ldc=gameRenderer", + ordinal = 1)) + private void hookRenderTickStart(CallbackInfo ci) { + LifecycleEvents.fireRenderTickEvent(TickEvent.Phase.START, this.renderTickCounter.tickDelta); + } + + @Inject(method = "render", + slice = @Slice(from = @At( + value = "INVOKE_STRING", + target = "net/minecraft/util/profiler/DisableableProfiler.swap(Ljava/lang/String;)V", + args = "ldc=toasts")), + at = @At( + value = "INVOKE", + target = "net/minecraft/util/profiler/DisableableProfiler.pop()V", + shift = At.Shift.AFTER, + ordinal = 0)) + private void hookRenderTickEnd(CallbackInfo ci) { + LifecycleEvents.fireRenderTickEvent(TickEvent.Phase.END, this.renderTickCounter.tickDelta); + } } diff --git a/patchwork-events-lifecycle/src/main/resources/fabric.mod.json b/patchwork-events-lifecycle/src/main/resources/fabric.mod.json index 5b3f6691..8b984aa3 100644 --- a/patchwork-events-lifecycle/src/main/resources/fabric.mod.json +++ b/patchwork-events-lifecycle/src/main/resources/fabric.mod.json @@ -14,6 +14,7 @@ ], "depends": { "fabricloader": ">=0.8.4", + "fabric": ">=0.15.0", "patchwork-fml": "*" }, "entrypoints": { diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java index b843dac4..8dce0091 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java @@ -91,6 +91,19 @@ public static void onPostClientTick() { LifecycleEvents.fireClientTickEvent(TickEvent.Phase.END); } - // TODO: onPreServerTick - // TODO: onPostServerTick + public static void onPreServerTick() { + LifecycleEvents.fireServerTickEvent(TickEvent.Phase.START); + } + + public static void onPostServerTick() { + LifecycleEvents.fireServerTickEvent(TickEvent.Phase.END); + } + + public static void onRenderTickStart(float timer) { + LifecycleEvents.fireRenderTickEvent(TickEvent.Phase.START, timer); + } + + public static void onRenderTickEnd(float timer) { + LifecycleEvents.fireRenderTickEvent(TickEvent.Phase.END, timer); + } } From 2d2cc76d66bd9fb800a6e255f3bbae89e06cca4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Fri, 31 Jul 2020 02:33:31 +1000 Subject: [PATCH 28/73] Add classes and fields to ForgeHooks, which might be use by hacky mods (#161) --- .../java/net/minecraftforge/common/ForgeHooks.java | 10 ++++++++++ .../main/java/net/patchworkmc/impl/loot/LootHooks.java | 10 +++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java index 65e86ca0..b2e22539 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -105,6 +105,16 @@ public static boolean onPlayerAttackTarget(PlayerEntity player, Entity target) { return EntityEvents.attackEntity(player, target); } + @SuppressWarnings({ "rawtypes", "unused" }) + private static ThreadLocal lootContext = LootHooks.lootContext; + + // Need to have the class here to make some mod hacks work + public static class LootTableContext extends LootHooks.LootTableContext { + private LootTableContext(Identifier name, boolean custom) { + super(name, custom); + } + } + @Nullable public static LootTable loadLootTable(Gson gson, Identifier name, JsonObject data, boolean custom, LootManager lootTableManager) { return LootHooks.loadLootTable(gson, name, data, custom, lootTableManager); diff --git a/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/LootHooks.java b/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/LootHooks.java index 93492205..88a5d840 100644 --- a/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/LootHooks.java +++ b/patchwork-loot/src/main/java/net/patchworkmc/impl/loot/LootHooks.java @@ -30,7 +30,6 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import org.spongepowered.asm.mixin.Unique; import net.minecraft.loot.LootManager; import net.minecraft.loot.LootTable; @@ -41,8 +40,8 @@ // NOTE: this class is more or less a direct copy of parts of Forge's ForgeHooks. public class LootHooks { - @Unique - private static ThreadLocal> lootContext = new ThreadLocal>(); + // Made public for Patchwork's own use + public static ThreadLocal> lootContext = new ThreadLocal>(); public static LootTable loadLootTable(Gson gson, Identifier name, JsonElement data, boolean custom, LootManager lootTableManager) { Deque que = lootContext.get(); @@ -105,7 +104,8 @@ public static String readPoolName(JsonObject json) { return ctx.poolCount == 1 ? "main" : "pool" + (ctx.poolCount - 1); } - private static class LootTableContext { + // Made public for Patchwork's own use + public static class LootTableContext { public final Identifier name; public final boolean custom; private final boolean vanilla; @@ -113,7 +113,7 @@ private static class LootTableContext { public int entryCount = 0; private HashSet entryNames = Sets.newHashSet(); - private LootTableContext(Identifier name, boolean custom) { + protected LootTableContext(Identifier name, boolean custom) { this.name = name; this.custom = custom; this.vanilla = "minecraft".equals(this.name.getNamespace()); From 37e35c3f54d2330de309493e5b5f12e39a4a9465 Mon Sep 17 00:00:00 2001 From: Glitch Date: Thu, 30 Jul 2020 16:05:04 -0500 Subject: [PATCH 29/73] Create patchwork-api-base (#157) * Create patchwork-api-base * Keybindings, mirror dependencies in top-level jar due to Loader/201 * spaces bad --- build.gradle | 8 +++--- patchwork-api-base/build.gradle | 2 ++ .../assets/patchwork-api-base}/icon.png | Bin .../src/main/resources/fabric.mod.json | 25 ++++++++++++++++++ patchwork-biomes/build.gradle | 4 +++ .../src/main/resources/fabric.mod.json | 3 +-- patchwork-capabilities/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 4 +-- patchwork-data-generators/build.gradle | 5 ++-- .../src/main/resources/fabric.mod.json | 2 +- patchwork-dispatcher/build.gradle | 11 ++++---- .../assets/patchwork-dispatcher}/icon.png | Bin .../src/main/resources/fabric.mod.json | 3 +-- patchwork-enum-hacks/build.gradle | 4 +++ .../src/main/resources/fabric.mod.json | 2 +- patchwork-events-entity/build.gradle | 7 ++--- .../src/main/resources/fabric.mod.json | 5 ++-- patchwork-events-input/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 2 +- patchwork-events-lifecycle/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 3 +-- patchwork-events-rendering/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 2 +- patchwork-events-world/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 3 +-- patchwork-extensions-block/build.gradle | 5 ++-- .../src/main/resources/fabric.mod.json | 6 +++-- patchwork-extensions-item/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 3 +-- patchwork-extensions-shearing/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 2 +- patchwork-extensions/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 2 +- patchwork-fml/build.gradle | 2 ++ .../src/main/resources/fabric.mod.json | 2 +- patchwork-god-classes/build.gradle | 17 ++++++------ .../assets/patchwork-god-classes/icon.png | Bin 0 -> 22738 bytes .../src/main/resources/fabric.mod.json | 2 +- patchwork-gui/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 2 +- patchwork-key-bindings/build.gradle | 4 +++ .../src/main/resources/fabric.mod.json | 2 +- patchwork-level-generators/build.gradle | 5 ++-- .../src/main/resources/fabric.mod.json | 2 +- patchwork-loot/build.gradle | 3 ++- .../resources/assets/patchwork-loot/icon.png | Bin 0 -> 22738 bytes .../src/main/resources/fabric.mod.json | 2 +- patchwork-model-loader/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 2 +- patchwork-networking-messages/build.gradle | 5 ++-- .../patchwork-networking-messages/icon.png | Bin 0 -> 22738 bytes .../src/main/resources/fabric.mod.json | 3 +-- patchwork-networking/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 3 +-- patchwork-recipes/build.gradle | 4 +++ .../src/main/resources/fabric.mod.json | 2 +- patchwork-registries/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 2 +- patchwork-resource/{readme.md => README.md} | 0 patchwork-resource/build.gradle | 6 ++++- .../src/main/resources/fabric.mod.json | 2 +- patchwork-tags/build.gradle | 4 +++ .../src/main/resources/fabric.mod.json | 2 +- patchwork-tooltype/build.gradle | 3 +++ .../src/main/resources/fabric.mod.json | 3 +-- patchwork-vanilla-patches/build.gradle | 4 +++ .../src/main/resources/fabric.mod.json | 2 +- settings.gradle | 1 + src/main/resources/fabric.mod.json | 5 +++- 69 files changed, 161 insertions(+), 84 deletions(-) create mode 100644 patchwork-api-base/build.gradle rename {patchwork-god-classes/src/main/resources/assets.patchwork-god-classes => patchwork-api-base/src/main/resources/assets/patchwork-api-base}/icon.png (100%) create mode 100644 patchwork-api-base/src/main/resources/fabric.mod.json rename {patchwork-loot/src/main/resources/patchwork-loot => patchwork-dispatcher/src/main/resources/assets/patchwork-dispatcher}/icon.png (100%) create mode 100644 patchwork-god-classes/src/main/resources/assets/patchwork-god-classes/icon.png create mode 100644 patchwork-loot/src/main/resources/assets/patchwork-loot/icon.png create mode 100644 patchwork-networking-messages/src/main/resources/assets/patchwork-networking-messages/icon.png rename patchwork-resource/{readme.md => README.md} (100%) diff --git a/build.gradle b/build.gradle index f250a02f..4c91f2f8 100644 --- a/build.gradle +++ b/build.gradle @@ -55,8 +55,8 @@ allprojects { dependencies { minecraft "com.mojang:minecraft:$Globals.mcVersion" mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}:v2" - modCompile "net.fabricmc:fabric-loader:0.8.4+build.198" - modCompile "net.fabricmc.fabric-api:fabric-api:0.15.1+build.260-1.14" + modImplementation "net.fabricmc:fabric-loader:0.8.4+build.198" + modImplementation "net.fabricmc.fabric-api:fabric-api:0.15.1+build.260-1.14" implementation 'net.patchworkmc:patchwork-eventbus:2.0.1:all' implementation 'com.google.code.findbugs:jsr305:3.0.2' @@ -238,8 +238,8 @@ dependencies { minecraft "com.mojang:minecraft:$Globals.mcVersion" mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}:v2" - modCompile "net.fabricmc:fabric-loader:0.8.4+build.198" - modCompile "net.fabricmc.fabric-api:fabric-api:0.15.1+build.260-1.14" + modImplementation "net.fabricmc:fabric-loader:0.8.4+build.198" + modImplementation "net.fabricmc.fabric-api:fabric-api:0.15.1+build.260-1.14" implementation 'com.electronwill.night-config:toml:3.6.2' include 'com.electronwill.night-config:core:3.6.2' diff --git a/patchwork-api-base/build.gradle b/patchwork-api-base/build.gradle new file mode 100644 index 00000000..6cb03206 --- /dev/null +++ b/patchwork-api-base/build.gradle @@ -0,0 +1,2 @@ +archivesBaseName = "patchwork-api-base" +version = getSubprojectVersion(project, "0.1.0") diff --git a/patchwork-god-classes/src/main/resources/assets.patchwork-god-classes/icon.png b/patchwork-api-base/src/main/resources/assets/patchwork-api-base/icon.png similarity index 100% rename from patchwork-god-classes/src/main/resources/assets.patchwork-god-classes/icon.png rename to patchwork-api-base/src/main/resources/assets/patchwork-api-base/icon.png diff --git a/patchwork-api-base/src/main/resources/fabric.mod.json b/patchwork-api-base/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..1b530f19 --- /dev/null +++ b/patchwork-api-base/src/main/resources/fabric.mod.json @@ -0,0 +1,25 @@ +{ + "schemaVersion": 1, + "id": "patchwork-api-base", + "name": "Patchwork API Base", + "version": "${version}", + "license": "LGPL-2.1-only", + "icon": "assets/patchwork-api-base/icon.png", + "contact": { + "issues": "https://github.com/PatchworkMC/patchwork-api/issues", + "sources": "https://github.com/PatchworkMC/patchwork-api" + }, + "authors": [ + "PatchworkMC" + ], + "depends": { + // This is mirrored in the top-level project because of a Loader issue + "fabricloader": ">=0.8.4", + "fabric": ">=0.15.1" + }, + "description": "Common zero-overhead classes used across Patchwork modules", + "custom": { + "modmenu:api": true, + "modmenu:parent": "patchwork" + } +} diff --git a/patchwork-biomes/build.gradle b/patchwork-biomes/build.gradle index 4c73edc9..3d61c99f 100644 --- a/patchwork-biomes/build.gradle +++ b/patchwork-biomes/build.gradle @@ -1,2 +1,6 @@ archivesBaseName = "patchwork-biomes" version = getSubprojectVersion(project, "0.2.0") + +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} diff --git a/patchwork-biomes/src/main/resources/fabric.mod.json b/patchwork-biomes/src/main/resources/fabric.mod.json index 538e1337..b083e6ef 100644 --- a/patchwork-biomes/src/main/resources/fabric.mod.json +++ b/patchwork-biomes/src/main/resources/fabric.mod.json @@ -13,8 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", - "patchwork-fml": "*" + "patchwork-api-base": "*" }, "description": "Implementation of the Forge Biomes API.", "entrypoints": { diff --git a/patchwork-capabilities/build.gradle b/patchwork-capabilities/build.gradle index a18cc291..b9d2c928 100644 --- a/patchwork-capabilities/build.gradle +++ b/patchwork-capabilities/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-capabilities" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-capabilities/src/main/resources/fabric.mod.json b/patchwork-capabilities/src/main/resources/fabric.mod.json index 94f7d084..7b20ca58 100644 --- a/patchwork-capabilities/src/main/resources/fabric.mod.json +++ b/patchwork-capabilities/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "patchwork-capabilities", - "name": "Patchwork Capabilities support", + "name": "Patchwork Capabilities", "version": "${version}", "license": "LGPL-2.1-only", "icon": "assets/patchwork-capabilities/icon.png", @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-data-generators/build.gradle b/patchwork-data-generators/build.gradle index f92c9094..0b2809a9 100644 --- a/patchwork-data-generators/build.gradle +++ b/patchwork-data-generators/build.gradle @@ -2,6 +2,7 @@ archivesBaseName = "patchwork-data-generators" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-events-lifecycle', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-data-generators/src/main/resources/fabric.mod.json b/patchwork-data-generators/src/main/resources/fabric.mod.json index 3750849e..16c6dfc2 100644 --- a/patchwork-data-generators/src/main/resources/fabric.mod.json +++ b/patchwork-data-generators/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*" }, "mixins": [ ], diff --git a/patchwork-dispatcher/build.gradle b/patchwork-dispatcher/build.gradle index 6f243688..bbc88bbe 100644 --- a/patchwork-dispatcher/build.gradle +++ b/patchwork-dispatcher/build.gradle @@ -2,9 +2,10 @@ archivesBaseName = "patchwork-dispatcher" version = getSubprojectVersion(project, "0.3.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') - compile project(path: ':patchwork-registries', configuration: 'dev') - compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') - compile project(path: ':patchwork-events-rendering', configuration: 'dev') - compile project(path: ':patchwork-model-loader', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-registries', configuration: 'dev') + implementation project(path: ':patchwork-events-lifecycle', configuration: 'dev') + implementation project(path: ':patchwork-events-rendering', configuration: 'dev') + implementation project(path: ':patchwork-model-loader', configuration: 'dev') } diff --git a/patchwork-loot/src/main/resources/patchwork-loot/icon.png b/patchwork-dispatcher/src/main/resources/assets/patchwork-dispatcher/icon.png similarity index 100% rename from patchwork-loot/src/main/resources/patchwork-loot/icon.png rename to patchwork-dispatcher/src/main/resources/assets/patchwork-dispatcher/icon.png diff --git a/patchwork-dispatcher/src/main/resources/fabric.mod.json b/patchwork-dispatcher/src/main/resources/fabric.mod.json index 2b63f05d..5cd7f2a2 100644 --- a/patchwork-dispatcher/src/main/resources/fabric.mod.json +++ b/patchwork-dispatcher/src/main/resources/fabric.mod.json @@ -16,8 +16,7 @@ ] }, "depends": { - "fabricloader": ">=0.8.4", - "fabric": "*", + "patchwork-api-base": "*", "patchwork-fml": "*", "patchwork-registries": "*", "patchwork-events-lifecycle": "*" diff --git a/patchwork-enum-hacks/build.gradle b/patchwork-enum-hacks/build.gradle index 5e41db54..1a155650 100644 --- a/patchwork-enum-hacks/build.gradle +++ b/patchwork-enum-hacks/build.gradle @@ -1,2 +1,6 @@ archivesBaseName = "patchwork-enum-hacks" version = getSubprojectVersion(project, "0.2.0") + +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} diff --git a/patchwork-enum-hacks/src/main/resources/fabric.mod.json b/patchwork-enum-hacks/src/main/resources/fabric.mod.json index 4fbe8282..f9b4a1aa 100644 --- a/patchwork-enum-hacks/src/main/resources/fabric.mod.json +++ b/patchwork-enum-hacks/src/main/resources/fabric.mod.json @@ -11,7 +11,7 @@ "license": "LGPL-2.1-only", "environment": "*", "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*" }, "mixins": [ "patchwork-enum-hacks.mixins.json" diff --git a/patchwork-events-entity/build.gradle b/patchwork-events-entity/build.gradle index 3a776fa4..24a87a27 100644 --- a/patchwork-events-entity/build.gradle +++ b/patchwork-events-entity/build.gradle @@ -2,7 +2,8 @@ archivesBaseName = "patchwork-events-entity" version = getSubprojectVersion(project, "0.4.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') - compile project(path: ':patchwork-extensions', configuration: 'dev') - compile project(path: ':patchwork-extensions-item', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-extensions', configuration: 'dev') + implementation project(path: ':patchwork-extensions-item', configuration: 'dev') } diff --git a/patchwork-events-entity/src/main/resources/fabric.mod.json b/patchwork-events-entity/src/main/resources/fabric.mod.json index a9cd92a8..9cd93e4a 100644 --- a/patchwork-events-entity/src/main/resources/fabric.mod.json +++ b/patchwork-events-entity/src/main/resources/fabric.mod.json @@ -6,7 +6,7 @@ "name": "Patchwork Entity Events", "description": "Provides an implementation of Minecraft Forge's Entity Events", "authors": [ - "coderbot" + "PatchworkMC" ], "license": "LGPL-2.1-only", "environment": "*", @@ -16,8 +16,7 @@ ] }, "depends": { - "fabricloader": ">=0.8.4", - "fabric": "*", + "patchwork-api-base": "*", "patchwork-fml": "*", "patchwork-extensions-item": "*" }, diff --git a/patchwork-events-input/build.gradle b/patchwork-events-input/build.gradle index 3dccb3dc..f9cd325d 100644 --- a/patchwork-events-input/build.gradle +++ b/patchwork-events-input/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-events-input" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-events-input/src/main/resources/fabric.mod.json b/patchwork-events-input/src/main/resources/fabric.mod.json index 8ec7b9f3..9bac8440 100644 --- a/patchwork-events-input/src/main/resources/fabric.mod.json +++ b/patchwork-events-input/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-events-lifecycle/build.gradle b/patchwork-events-lifecycle/build.gradle index 6d10be9c..f2c12b81 100644 --- a/patchwork-events-lifecycle/build.gradle +++ b/patchwork-events-lifecycle/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-events-lifecycle" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-events-lifecycle/src/main/resources/fabric.mod.json b/patchwork-events-lifecycle/src/main/resources/fabric.mod.json index 8b984aa3..6f88cf66 100644 --- a/patchwork-events-lifecycle/src/main/resources/fabric.mod.json +++ b/patchwork-events-lifecycle/src/main/resources/fabric.mod.json @@ -13,8 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", - "fabric": ">=0.15.0", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "entrypoints": { diff --git a/patchwork-events-rendering/build.gradle b/patchwork-events-rendering/build.gradle index bd15b80f..2e2f7fb1 100644 --- a/patchwork-events-rendering/build.gradle +++ b/patchwork-events-rendering/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-client-colors" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-events-rendering/src/main/resources/fabric.mod.json b/patchwork-events-rendering/src/main/resources/fabric.mod.json index 28112c8e..d8f37a2d 100644 --- a/patchwork-events-rendering/src/main/resources/fabric.mod.json +++ b/patchwork-events-rendering/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-events-world/build.gradle b/patchwork-events-world/build.gradle index b7289c8d..5795f99d 100644 --- a/patchwork-events-world/build.gradle +++ b/patchwork-events-world/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-events-world" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-events-world/src/main/resources/fabric.mod.json b/patchwork-events-world/src/main/resources/fabric.mod.json index cd2c8b0d..7a5d1dbf 100644 --- a/patchwork-events-world/src/main/resources/fabric.mod.json +++ b/patchwork-events-world/src/main/resources/fabric.mod.json @@ -13,8 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", - "fabric": ">=0.15.0", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-extensions-block/build.gradle b/patchwork-extensions-block/build.gradle index 7de9a209..559a2308 100644 --- a/patchwork-extensions-block/build.gradle +++ b/patchwork-extensions-block/build.gradle @@ -2,8 +2,9 @@ archivesBaseName = "patchwork-extensions-block" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-enum-hacks', configuration: 'dev') - compile project(path: ':patchwork-tooltype', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-enum-hacks', configuration: 'dev') + implementation project(path: ':patchwork-tooltype', configuration: 'dev') } minecraft { diff --git a/patchwork-extensions-block/src/main/resources/fabric.mod.json b/patchwork-extensions-block/src/main/resources/fabric.mod.json index 3e2c4673..7ccd29e1 100644 --- a/patchwork-extensions-block/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-block/src/main/resources/fabric.mod.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "id": "patchwork-extensions-block", "version": "${version}", - "icon": "assets/patchwork-enum-hacks/icon.png", + "icon": "assets/patchwork-extensions-block/icon.png", "name": "Patchwork Extensions Block", "description": "Implementation of Forge's block extensions", "authors": [ @@ -11,7 +11,9 @@ "license": "LGPL-2.1-only", "environment": "*", "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*", + "patchwork-enum-hacks": "*", + "patchwork-tooltype": "*" }, "mixins": [ "patchwork-extensions-block.mixins.json", diff --git a/patchwork-extensions-item/build.gradle b/patchwork-extensions-item/build.gradle index 1bb40bab..45de97a9 100644 --- a/patchwork-extensions-item/build.gradle +++ b/patchwork-extensions-item/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-extensions-item" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-tooltype', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-tooltype', configuration: 'dev') } diff --git a/patchwork-extensions-item/src/main/resources/fabric.mod.json b/patchwork-extensions-item/src/main/resources/fabric.mod.json index 154a6edb..a538560f 100644 --- a/patchwork-extensions-item/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-item/src/main/resources/fabric.mod.json @@ -15,8 +15,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", - "fabric": "*", + "patchwork-api-base": "*", "patchwork-tooltype": "*" }, "mixins": [ diff --git a/patchwork-extensions-shearing/build.gradle b/patchwork-extensions-shearing/build.gradle index 70518bac..a1c61fa9 100644 --- a/patchwork-extensions-shearing/build.gradle +++ b/patchwork-extensions-shearing/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-extensions-shearing" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-extensions-shearing/src/main/resources/fabric.mod.json b/patchwork-extensions-shearing/src/main/resources/fabric.mod.json index a59f138b..3d37616d 100644 --- a/patchwork-extensions-shearing/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-shearing/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-extensions/build.gradle b/patchwork-extensions/build.gradle index 7f1d5633..32e9c992 100644 --- a/patchwork-extensions/build.gradle +++ b/patchwork-extensions/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-extensions" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-extensions-block', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-extensions-block', configuration: 'dev') } diff --git a/patchwork-extensions/src/main/resources/fabric.mod.json b/patchwork-extensions/src/main/resources/fabric.mod.json index 89c4cb58..ec0a3d92 100644 --- a/patchwork-extensions/src/main/resources/fabric.mod.json +++ b/patchwork-extensions/src/main/resources/fabric.mod.json @@ -11,7 +11,7 @@ "icon": "assets/patchwork-extensions/icon.png", "environment": "*", "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "fabric": "*" }, "mixins": [ diff --git a/patchwork-fml/build.gradle b/patchwork-fml/build.gradle index 4880cf10..aa165b85 100644 --- a/patchwork-fml/build.gradle +++ b/patchwork-fml/build.gradle @@ -3,4 +3,6 @@ version = getSubprojectVersion(project, "0.2.0") dependencies { implementation 'com.electronwill.night-config:toml:3.6.2' + + implementation project(path: ':patchwork-api-base', configuration: 'dev') } diff --git a/patchwork-fml/src/main/resources/fabric.mod.json b/patchwork-fml/src/main/resources/fabric.mod.json index 8e0790fe..5f090b2c 100644 --- a/patchwork-fml/src/main/resources/fabric.mod.json +++ b/patchwork-fml/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*" }, "entrypoints": { "main": [ diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 33451b11..ce9b4ca5 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -2,12 +2,13 @@ archivesBaseName = "patchwork-god-classes" version = getSubprojectVersion(project, "0.1.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') - compile project(path: ':patchwork-capabilities', configuration: 'dev') - compile project(path: ':patchwork-events-entity', configuration: 'dev') - compile project(path: ':patchwork-events-input', configuration: 'dev') - compile project(path: ':patchwork-events-lifecycle', configuration: 'dev') - compile project(path: ':patchwork-events-rendering', configuration: 'dev') - compile project(path: ':patchwork-events-world', configuration: 'dev') - compile project(path: ':patchwork-loot', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-capabilities', configuration: 'dev') + implementation project(path: ':patchwork-events-entity', configuration: 'dev') + implementation project(path: ':patchwork-events-input', configuration: 'dev') + implementation project(path: ':patchwork-events-lifecycle', configuration: 'dev') + implementation project(path: ':patchwork-events-rendering', configuration: 'dev') + implementation project(path: ':patchwork-events-world', configuration: 'dev') + implementation project(path: ':patchwork-loot', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/resources/assets/patchwork-god-classes/icon.png b/patchwork-god-classes/src/main/resources/assets/patchwork-god-classes/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-god-classes/src/main/resources/fabric.mod.json b/patchwork-god-classes/src/main/resources/fabric.mod.json index b14cf7e8..4fc551a4 100644 --- a/patchwork-god-classes/src/main/resources/fabric.mod.json +++ b/patchwork-god-classes/src/main/resources/fabric.mod.json @@ -15,7 +15,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*", "patchwork-capabilities": "*", "patchwork-events-input": "*", diff --git a/patchwork-gui/build.gradle b/patchwork-gui/build.gradle index 2aaeb8f4..46e9be22 100644 --- a/patchwork-gui/build.gradle +++ b/patchwork-gui/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-gui" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-gui/src/main/resources/fabric.mod.json b/patchwork-gui/src/main/resources/fabric.mod.json index fc32dc9b..535cd7f4 100644 --- a/patchwork-gui/src/main/resources/fabric.mod.json +++ b/patchwork-gui/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-key-bindings/build.gradle b/patchwork-key-bindings/build.gradle index 65673173..96e91b15 100644 --- a/patchwork-key-bindings/build.gradle +++ b/patchwork-key-bindings/build.gradle @@ -1,2 +1,6 @@ archivesBaseName = "patchwork-key-bindings" version = getSubprojectVersion(project, "0.1.0") + +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} diff --git a/patchwork-key-bindings/src/main/resources/fabric.mod.json b/patchwork-key-bindings/src/main/resources/fabric.mod.json index 237e9f94..bed15e69 100644 --- a/patchwork-key-bindings/src/main/resources/fabric.mod.json +++ b/patchwork-key-bindings/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*" }, "mixins": [ "patchwork-key-bindings.mixins.json" diff --git a/patchwork-level-generators/build.gradle b/patchwork-level-generators/build.gradle index 597ee7b6..40fda7b5 100644 --- a/patchwork-level-generators/build.gradle +++ b/patchwork-level-generators/build.gradle @@ -2,8 +2,9 @@ archivesBaseName = "patchwork-level-generators" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') - compile project(path: ':patchwork-events-world', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-events-world', configuration: 'dev') } minecraft { diff --git a/patchwork-level-generators/src/main/resources/fabric.mod.json b/patchwork-level-generators/src/main/resources/fabric.mod.json index 01fc6bd6..018ec87d 100644 --- a/patchwork-level-generators/src/main/resources/fabric.mod.json +++ b/patchwork-level-generators/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*" }, "description": "Implementation of the Forge World Type API.", "mixins": [ diff --git a/patchwork-loot/build.gradle b/patchwork-loot/build.gradle index 0caa77dc..62a1d4aa 100644 --- a/patchwork-loot/build.gradle +++ b/patchwork-loot/build.gradle @@ -2,6 +2,7 @@ archivesBaseName = "patchwork-loot" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-loot/src/main/resources/assets/patchwork-loot/icon.png b/patchwork-loot/src/main/resources/assets/patchwork-loot/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-loot/src/main/resources/fabric.mod.json b/patchwork-loot/src/main/resources/fabric.mod.json index 46a3e957..215c4733 100644 --- a/patchwork-loot/src/main/resources/fabric.mod.json +++ b/patchwork-loot/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*" }, "mixins": [ "patchwork-loot.mixins.json" diff --git a/patchwork-model-loader/build.gradle b/patchwork-model-loader/build.gradle index 0baf9131..00f85fd8 100644 --- a/patchwork-model-loader/build.gradle +++ b/patchwork-model-loader/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-model-loader" version = getSubprojectVersion(project, "0.1.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-model-loader/src/main/resources/fabric.mod.json b/patchwork-model-loader/src/main/resources/fabric.mod.json index 33b4c93d..87194392 100644 --- a/patchwork-model-loader/src/main/resources/fabric.mod.json +++ b/patchwork-model-loader/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-networking-messages/build.gradle b/patchwork-networking-messages/build.gradle index 9fad475e..e170cf8b 100644 --- a/patchwork-networking-messages/build.gradle +++ b/patchwork-networking-messages/build.gradle @@ -2,6 +2,7 @@ archivesBaseName = "patchwork-networking-messages" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') - compile project(path: ':patchwork-networking', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-networking', configuration: 'dev') } diff --git a/patchwork-networking-messages/src/main/resources/assets/patchwork-networking-messages/icon.png b/patchwork-networking-messages/src/main/resources/assets/patchwork-networking-messages/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-networking-messages/src/main/resources/fabric.mod.json b/patchwork-networking-messages/src/main/resources/fabric.mod.json index 6552e4b2..1e74eee8 100644 --- a/patchwork-networking-messages/src/main/resources/fabric.mod.json +++ b/patchwork-networking-messages/src/main/resources/fabric.mod.json @@ -13,8 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", - "fabric-networking-v0": "*", + "patchwork-api-base": "*", "patchwork-fml": "*", "patchwork-networking": "*" }, diff --git a/patchwork-networking/build.gradle b/patchwork-networking/build.gradle index fa90b140..c14419a0 100644 --- a/patchwork-networking/build.gradle +++ b/patchwork-networking/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-networking" version = getSubprojectVersion(project, "0.2.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-networking/src/main/resources/fabric.mod.json b/patchwork-networking/src/main/resources/fabric.mod.json index d27421ae..458a68e7 100644 --- a/patchwork-networking/src/main/resources/fabric.mod.json +++ b/patchwork-networking/src/main/resources/fabric.mod.json @@ -13,8 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", - "fabric-networking-v0": "*", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-recipes/build.gradle b/patchwork-recipes/build.gradle index f13ee8e0..4d7b59b4 100644 --- a/patchwork-recipes/build.gradle +++ b/patchwork-recipes/build.gradle @@ -1,2 +1,6 @@ archivesBaseName = "patchwork-recipes" version = getSubprojectVersion(project, "0.2.0") + +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} diff --git a/patchwork-recipes/src/main/resources/fabric.mod.json b/patchwork-recipes/src/main/resources/fabric.mod.json index 329f85ac..176a8769 100644 --- a/patchwork-recipes/src/main/resources/fabric.mod.json +++ b/patchwork-recipes/src/main/resources/fabric.mod.json @@ -11,7 +11,7 @@ "icon": "assets/patchwork-recipes/icon.png", "environment": "*", "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "fabric": "*" }, "mixins": [ diff --git a/patchwork-registries/build.gradle b/patchwork-registries/build.gradle index 63ae5d33..9286ce7e 100644 --- a/patchwork-registries/build.gradle +++ b/patchwork-registries/build.gradle @@ -2,7 +2,8 @@ archivesBaseName = "patchwork-registries" version = getSubprojectVersion(project, "0.3.0") dependencies { - compile project(path: ':patchwork-fml', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } minecraft { diff --git a/patchwork-registries/src/main/resources/fabric.mod.json b/patchwork-registries/src/main/resources/fabric.mod.json index 1715ad9d..8064936c 100644 --- a/patchwork-registries/src/main/resources/fabric.mod.json +++ b/patchwork-registries/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "description": "Implementation of the Forge Registry API.", diff --git a/patchwork-resource/readme.md b/patchwork-resource/README.md similarity index 100% rename from patchwork-resource/readme.md rename to patchwork-resource/README.md diff --git a/patchwork-resource/build.gradle b/patchwork-resource/build.gradle index f60f2882..92cb0ffb 100644 --- a/patchwork-resource/build.gradle +++ b/patchwork-resource/build.gradle @@ -1,2 +1,6 @@ archivesBaseName = "patchwork-resource" -version = getSubprojectVersion(project, "0.1.0") \ No newline at end of file +version = getSubprojectVersion(project, "0.1.0") + +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} diff --git a/patchwork-resource/src/main/resources/fabric.mod.json b/patchwork-resource/src/main/resources/fabric.mod.json index 809ef331..16abce0b 100644 --- a/patchwork-resource/src/main/resources/fabric.mod.json +++ b/patchwork-resource/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", + "patchwork-api-base": "*", "patchwork-fml": "*" }, "mixins": [ diff --git a/patchwork-tags/build.gradle b/patchwork-tags/build.gradle index 808194bb..5d8ca819 100644 --- a/patchwork-tags/build.gradle +++ b/patchwork-tags/build.gradle @@ -1,6 +1,10 @@ archivesBaseName = "patchwork-tags" version = getSubprojectVersion(project, "0.1.0") +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} + minecraft { accessWidener "src/main/resources/patchwork-tags.accesswidener" } diff --git a/patchwork-tags/src/main/resources/fabric.mod.json b/patchwork-tags/src/main/resources/fabric.mod.json index 23be96f8..6ffa7c17 100644 --- a/patchwork-tags/src/main/resources/fabric.mod.json +++ b/patchwork-tags/src/main/resources/fabric.mod.json @@ -14,7 +14,7 @@ ], "accessWidener": "patchwork-tags.accesswidener", "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*" }, "description": "Implementation of the Forge Tags API.", "custom": { diff --git a/patchwork-tooltype/build.gradle b/patchwork-tooltype/build.gradle index 670bfabc..3f8c878a 100644 --- a/patchwork-tooltype/build.gradle +++ b/patchwork-tooltype/build.gradle @@ -1,3 +1,6 @@ archivesBaseName = "patchwork-tooltype" version = getSubprojectVersion(project, "0.2.0") +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} diff --git a/patchwork-tooltype/src/main/resources/fabric.mod.json b/patchwork-tooltype/src/main/resources/fabric.mod.json index bcd2b0c6..a6c45979 100644 --- a/patchwork-tooltype/src/main/resources/fabric.mod.json +++ b/patchwork-tooltype/src/main/resources/fabric.mod.json @@ -15,8 +15,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4", - "fabric": "*" + "patchwork-api-base": "*" }, "custom": { "modmenu:api": true, diff --git a/patchwork-vanilla-patches/build.gradle b/patchwork-vanilla-patches/build.gradle index 9281f2cd..bff51246 100644 --- a/patchwork-vanilla-patches/build.gradle +++ b/patchwork-vanilla-patches/build.gradle @@ -1,2 +1,6 @@ archivesBaseName = "patchwork-vanilla-patches" version = getSubprojectVersion(project, "0.2.0") + +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} diff --git a/patchwork-vanilla-patches/src/main/resources/fabric.mod.json b/patchwork-vanilla-patches/src/main/resources/fabric.mod.json index 272756cd..95e57bda 100644 --- a/patchwork-vanilla-patches/src/main/resources/fabric.mod.json +++ b/patchwork-vanilla-patches/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*" }, "description": "A collection of Forge's small patches and bugfixes that change vanilla behavior.", "mixins": [ diff --git a/settings.gradle b/settings.gradle index 9cd4535f..03a12707 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,6 +12,7 @@ pluginManagement { rootProject.name = "patchwork-api" +include 'patchwork-api-base' include 'patchwork-biomes' include 'patchwork-capabilities' include 'patchwork-data-generators' diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 41e75d59..0a98e243 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -13,7 +13,10 @@ "PatchworkMC" ], "depends": { - "fabricloader": ">=0.8.4" + // This is copied over from patchwork-api-base until Loader/201 is resolved properly. + // Loader/204 exists as a bandage fix, but not a real solution. + "fabricloader": ">=0.8.4", + "fabric": ">=0.15.1" }, "description": "Implementation of Minecraft Forge for Fabric.", "custom": { From e92de09120bed0c07c9634b26c98f0affe9f766b Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Thu, 30 Jul 2020 18:15:07 -0400 Subject: [PATCH 30/73] Clean up stacktrace for unimplemented class / method / field errors. (#138) * Clean up stacktrace for unimplemented class / method / field errors. * Prettify BootstrapMethodErrors and add more information --- .../java/net/patchworkmc/impl/Patchwork.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java b/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java index 59b74ed9..f6a0b20b 100644 --- a/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java +++ b/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java @@ -108,6 +108,33 @@ public void onInitialize() { error = new PatchworkInitializationException("Failed to construct Patchwork mods"); } + Throwable checked; + + if (t instanceof BootstrapMethodError) { + checked = t.getCause(); + } else { + checked = t; + } + + if (checked instanceof NoClassDefFoundError || checked instanceof NoSuchMethodError || checked instanceof NoSuchFieldError) { + final String unDefinedClass = checked.getMessage().substring(checked.getMessage().lastIndexOf(' ') + 1).replace('/', '.'); + String type; + + if (checked instanceof NoClassDefFoundError) { + type = "class"; + } else if (checked instanceof NoSuchMethodError) { + type = "method"; + } else { + type = "field"; + } + + if (unDefinedClass.startsWith("net.minecraft.") || (unDefinedClass.startsWith("net.minecraftforge.") && !unDefinedClass.startsWith("net.minecraftforge.lex."))) { + throw new PatchworkInitializationException("Patchwork mod " + initializer.getModId() + " tried to access an unimplemented " + type + ".", t); + } else { + throw new PatchworkInitializationException("Patchwork mod " + initializer.getModId() + " tried to access a missing " + type + " from a missing and undeclared, or outdated dependency.", t); + } + } + error.addSuppressed(t); } From c9f2cdfc432ab4487e9d28b6d377cf05363c7119 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Thu, 30 Jul 2020 17:26:15 -0500 Subject: [PATCH 31/73] Patchwork v0.8.0: BoP, ForgeHooks, basic BEs, start of models, and many events! For the full changelog, click [here](https://github.com/PatchworkMC/patchwork-api/compare/v0.7.0...v0.8.0) This release has all the needed features for Biomes o' Plenty to run properly. Thanks to everyone who's contributed--especially @famous1622, @kitlith, and @rikka0w0, who have contributed an insane amount of code in the past month. --- build.gradle | 2 +- patchwork-biomes/build.gradle | 2 +- patchwork-capabilities/build.gradle | 2 +- patchwork-data-generators/build.gradle | 2 +- patchwork-dispatcher/build.gradle | 2 +- patchwork-enum-hacks/build.gradle | 2 +- patchwork-events-entity/build.gradle | 2 +- patchwork-events-input/build.gradle | 2 +- patchwork-events-lifecycle/build.gradle | 2 +- patchwork-events-rendering/build.gradle | 2 +- patchwork-events-world/build.gradle | 2 +- patchwork-extensions-block/build.gradle | 2 +- patchwork-extensions-item/build.gradle | 2 +- patchwork-extensions-shearing/build.gradle | 2 +- patchwork-extensions/build.gradle | 2 +- patchwork-fml/build.gradle | 2 +- patchwork-god-classes/build.gradle | 2 +- patchwork-gui/build.gradle | 2 +- patchwork-key-bindings/build.gradle | 2 +- patchwork-level-generators/build.gradle | 2 +- patchwork-loot/build.gradle | 2 +- patchwork-model-loader/build.gradle | 2 +- patchwork-networking-messages/build.gradle | 2 +- patchwork-networking/build.gradle | 2 +- patchwork-recipes/build.gradle | 2 +- patchwork-registries/build.gradle | 2 +- patchwork-resource/build.gradle | 2 +- patchwork-tooltype/build.gradle | 2 +- patchwork-vanilla-patches/build.gradle | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) diff --git a/build.gradle b/build.gradle index 4c91f2f8..16892af4 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ plugins { def ENV = System.getenv() class Globals { - static def baseVersion = "0.7.0" + static def baseVersion = "0.8.0" static def mcVersion = "1.14.4" static def yarnVersion = "+build.16" } diff --git a/patchwork-biomes/build.gradle b/patchwork-biomes/build.gradle index 3d61c99f..3521c4ab 100644 --- a/patchwork-biomes/build.gradle +++ b/patchwork-biomes/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-biomes" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-capabilities/build.gradle b/patchwork-capabilities/build.gradle index b9d2c928..f1be1c41 100644 --- a/patchwork-capabilities/build.gradle +++ b/patchwork-capabilities/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-capabilities" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-data-generators/build.gradle b/patchwork-data-generators/build.gradle index 0b2809a9..41620ba2 100644 --- a/patchwork-data-generators/build.gradle +++ b/patchwork-data-generators/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-data-generators" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-dispatcher/build.gradle b/patchwork-dispatcher/build.gradle index bbc88bbe..e42a016b 100644 --- a/patchwork-dispatcher/build.gradle +++ b/patchwork-dispatcher/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-dispatcher" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.4.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-enum-hacks/build.gradle b/patchwork-enum-hacks/build.gradle index 1a155650..91078b2d 100644 --- a/patchwork-enum-hacks/build.gradle +++ b/patchwork-enum-hacks/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-enum-hacks" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-entity/build.gradle b/patchwork-events-entity/build.gradle index 24a87a27..0c0ccee0 100644 --- a/patchwork-events-entity/build.gradle +++ b/patchwork-events-entity/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-events-entity" -version = getSubprojectVersion(project, "0.4.0") +version = getSubprojectVersion(project, "0.5.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-input/build.gradle b/patchwork-events-input/build.gradle index f9cd325d..c8587791 100644 --- a/patchwork-events-input/build.gradle +++ b/patchwork-events-input/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-events-input" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-lifecycle/build.gradle b/patchwork-events-lifecycle/build.gradle index f2c12b81..6991be53 100644 --- a/patchwork-events-lifecycle/build.gradle +++ b/patchwork-events-lifecycle/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-events-lifecycle" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-rendering/build.gradle b/patchwork-events-rendering/build.gradle index 2e2f7fb1..16784a5e 100644 --- a/patchwork-events-rendering/build.gradle +++ b/patchwork-events-rendering/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-client-colors" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-world/build.gradle b/patchwork-events-world/build.gradle index 5795f99d..06036392 100644 --- a/patchwork-events-world/build.gradle +++ b/patchwork-events-world/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-events-world" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-extensions-block/build.gradle b/patchwork-extensions-block/build.gradle index 559a2308..6bdfc305 100644 --- a/patchwork-extensions-block/build.gradle +++ b/patchwork-extensions-block/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-extensions-block" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-extensions-item/build.gradle b/patchwork-extensions-item/build.gradle index 45de97a9..a7ef0341 100644 --- a/patchwork-extensions-item/build.gradle +++ b/patchwork-extensions-item/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-extensions-item" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-extensions-shearing/build.gradle b/patchwork-extensions-shearing/build.gradle index a1c61fa9..1faf845c 100644 --- a/patchwork-extensions-shearing/build.gradle +++ b/patchwork-extensions-shearing/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-extensions-shearing" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-extensions/build.gradle b/patchwork-extensions/build.gradle index 32e9c992..1abcf4b6 100644 --- a/patchwork-extensions/build.gradle +++ b/patchwork-extensions/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-extensions" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-fml/build.gradle b/patchwork-fml/build.gradle index aa165b85..f4fcac45 100644 --- a/patchwork-fml/build.gradle +++ b/patchwork-fml/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-fml" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation 'com.electronwill.night-config:toml:3.6.2' diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index ce9b4ca5..27e9eb18 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-god-classes" -version = getSubprojectVersion(project, "0.1.0") +version = getSubprojectVersion(project, "0.2.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-gui/build.gradle b/patchwork-gui/build.gradle index 46e9be22..200b9b8a 100644 --- a/patchwork-gui/build.gradle +++ b/patchwork-gui/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-gui" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-key-bindings/build.gradle b/patchwork-key-bindings/build.gradle index 96e91b15..33c56484 100644 --- a/patchwork-key-bindings/build.gradle +++ b/patchwork-key-bindings/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-key-bindings" -version = getSubprojectVersion(project, "0.1.0") +version = getSubprojectVersion(project, "0.2.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-level-generators/build.gradle b/patchwork-level-generators/build.gradle index 40fda7b5..a7cf6271 100644 --- a/patchwork-level-generators/build.gradle +++ b/patchwork-level-generators/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-level-generators" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-loot/build.gradle b/patchwork-loot/build.gradle index 62a1d4aa..0f3d0fb1 100644 --- a/patchwork-loot/build.gradle +++ b/patchwork-loot/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-loot" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-model-loader/build.gradle b/patchwork-model-loader/build.gradle index 00f85fd8..9c1c13d0 100644 --- a/patchwork-model-loader/build.gradle +++ b/patchwork-model-loader/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-model-loader" -version = getSubprojectVersion(project, "0.1.0") +version = getSubprojectVersion(project, "0.2.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-networking-messages/build.gradle b/patchwork-networking-messages/build.gradle index e170cf8b..6a8bfc95 100644 --- a/patchwork-networking-messages/build.gradle +++ b/patchwork-networking-messages/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-networking-messages" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-networking/build.gradle b/patchwork-networking/build.gradle index c14419a0..3a995a3b 100644 --- a/patchwork-networking/build.gradle +++ b/patchwork-networking/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-networking" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-recipes/build.gradle b/patchwork-recipes/build.gradle index 4d7b59b4..ad6c0ed0 100644 --- a/patchwork-recipes/build.gradle +++ b/patchwork-recipes/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-recipes" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-registries/build.gradle b/patchwork-registries/build.gradle index 9286ce7e..7be4dbc8 100644 --- a/patchwork-registries/build.gradle +++ b/patchwork-registries/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-registries" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.4.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-resource/build.gradle b/patchwork-resource/build.gradle index 92cb0ffb..0eb1c3b8 100644 --- a/patchwork-resource/build.gradle +++ b/patchwork-resource/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-resource" -version = getSubprojectVersion(project, "0.1.0") +version = getSubprojectVersion(project, "0.2.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-tooltype/build.gradle b/patchwork-tooltype/build.gradle index 3f8c878a..e82d4976 100644 --- a/patchwork-tooltype/build.gradle +++ b/patchwork-tooltype/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-tooltype" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-vanilla-patches/build.gradle b/patchwork-vanilla-patches/build.gradle index bff51246..55da2b7e 100644 --- a/patchwork-vanilla-patches/build.gradle +++ b/patchwork-vanilla-patches/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-vanilla-patches" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') From 6702c754789c9caa7ce8b1bfded3e7c58b85840f Mon Sep 17 00:00:00 2001 From: qouteall Date: Sun, 2 Aug 2020 10:53:04 +0800 Subject: [PATCH 32/73] Fix annotation scanning argument object types (#76) * Fix annotation scanning argument object wrappers * rename * Renames and minor changes * Minor rename --- .../loading/moddiscovery/ModAnnotation.java | 123 ++++++++++++++++++ .../forgespi/language/ModFileScanData.java | 60 ++++++--- 2 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 patchwork-fml/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotation.java diff --git a/patchwork-fml/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotation.java b/patchwork-fml/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotation.java new file mode 100644 index 00000000..ce6fb30a --- /dev/null +++ b/patchwork-fml/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotation.java @@ -0,0 +1,123 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.loading.moddiscovery; + +import java.lang.annotation.ElementType; +import java.util.ArrayList; +import java.util.Map; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import net.minecraftforge.forgespi.language.ModFileScanData; +import org.objectweb.asm.Type; + +public class ModAnnotation { + private final ElementType type; + private final Type asmType; + private final String member; + private final Map elements; + private ArrayList arrayList; + private String arrayName; + + public static ModFileScanData.AnnotationData fromModAnnotation(Type clazz, ModAnnotation annotation) { + return new ModFileScanData.AnnotationData( + annotation.asmType, annotation.type, clazz, annotation.member, annotation.elements + ); + } + + public ModAnnotation(ElementType type, Type asmType, String member) { + this.elements = Maps.newHashMap(); + this.type = type; + this.asmType = asmType; + this.member = member; + } + + public ModAnnotation(Type asmType, ModAnnotation parent) { + this.elements = Maps.newHashMap(); + this.type = parent.type; + this.asmType = asmType; + this.member = parent.member; + } + + public String toString() { + return MoreObjects.toStringHelper("Annotation") + .add("type", this.type).add("name", this.asmType.getClassName()) + .add("member", this.member).add("values", this.elements).toString(); + } + + public ElementType getType() { + return this.type; + } + + public String getMember() { + return this.member; + } + + public Map getValues() { + return this.elements; + } + + public void addArray(String name) { + this.arrayList = Lists.newArrayList(); + this.arrayName = name; + } + + public void addProperty(String key, Object value) { + if (this.arrayList != null) { + this.arrayList.add(value); + } else { + this.elements.put(key, value); + } + } + + public void addEnumProperty(String key, String enumName, String value) { + this.addProperty(key, new ModAnnotation.EnumHolder(enumName, value)); + } + + public void endArray() { + this.elements.put(this.arrayName, this.arrayList); + this.arrayList = null; + } + + public ModAnnotation addChildAnnotation(String name, String desc) { + ModAnnotation child = new ModAnnotation(Type.getType(desc), this); + this.addProperty(name, child.getValues()); + return child; + } + + public static class EnumHolder { + private final String desc; + private final String value; + + public EnumHolder(String desc, String value) { + this.desc = desc; + this.value = value; + } + + public String getDesc() { + return this.desc; + } + + public String getValue() { + return this.value; + } + } +} diff --git a/patchwork-fml/src/main/java/net/minecraftforge/forgespi/language/ModFileScanData.java b/patchwork-fml/src/main/java/net/minecraftforge/forgespi/language/ModFileScanData.java index b066770f..284e7aaf 100644 --- a/patchwork-fml/src/main/java/net/minecraftforge/forgespi/language/ModFileScanData.java +++ b/patchwork-fml/src/main/java/net/minecraftforge/forgespi/language/ModFileScanData.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import com.google.gson.Gson; +import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.Type; @@ -110,8 +111,7 @@ public static class AnnotationData { private final Type clazz; private final String memberName; - //lazy evaluated - private Map annotationData; + private Map elements; public AnnotationData( final Type annotationType, final ElementType targetType, @@ -123,6 +123,17 @@ public AnnotationData( this.memberName = memberName; } + public AnnotationData( + Type annotationType, ElementType targetType, Type clazz, + String memberName, Map elements + ) { + this.annotationType = annotationType; + this.targetType = targetType; + this.clazz = clazz; + this.memberName = memberName; + this.elements = elements; + } + public Type getAnnotationType() { return annotationType; } @@ -140,15 +151,15 @@ public String getMemberName() { } public Map getAnnotationData() { - if (annotationData == null) { + if (elements == null) { initAnnotationData(); } - return annotationData; + return elements; } private void initAnnotationData() { - annotationData = new HashMap<>(); + elements = new HashMap<>(); try { // TODO: This *may* load classes in the wrong order, but it shouldn't be an issue @@ -163,14 +174,13 @@ private void initAnnotationData() { return; } - Method[] argMethods = annotationObject.getClass().getDeclaredMethods(); + Method[] elementGetters = annotationObject.getClass().getDeclaredMethods(); - for (Method argMethod : argMethods) { - if (isArgumentMethod(argMethod)) { - annotationData.put( - argMethod.getName(), - argMethod.invoke(annotationObject) - ); + for (Method elementGetter : elementGetters) { + if (isElementGetter(elementGetter)) { + Object value = elementGetter.invoke(annotationObject); + + elements.put(elementGetter.getName(), processElementObject(value)); } } } catch (Throwable e) { @@ -178,7 +188,7 @@ private void initAnnotationData() { } } - private static boolean isArgumentMethod(Method method) { + private static boolean isElementGetter(Method method) { String name = method.getName(); if (name.equals("toString")) return false; if (name.equals("hashCode")) return false; @@ -199,15 +209,14 @@ private Annotation getAnnotationObject(Class clazzObj, Class annotationType) case METHOD: String methodName = memberName.substring(0, memberName.indexOf('(')); Method[] methods = Arrays.stream(clazzObj.getDeclaredMethods()) - .filter(method -> method.getName().equals(methodName)) - .toArray(Method[]::new); + .filter(method -> method.getName().equals(methodName)) + .toArray(Method[]::new); if (methods.length == 0) { throw new RuntimeException("Cannot find method " + methodName); } if (methods.length > 1) { //TODO handle overloaded methods - throw new RuntimeException("Currently Cannot Handle Overloaded Methods"); } @@ -235,4 +244,23 @@ public int hashCode() { return Objects.hash(annotationType, targetType, clazz, memberName); } } + + private static Object processElementObject(Object object) { + if (object instanceof Object[]) { + return Arrays.stream((Object[]) object) + .map(ModFileScanData::processElementObject) + .collect(Collectors.toList()); + } + + if (object instanceof Enum) { + Enum enumObject = (Enum) object; + String className = enumObject.getDeclaringClass().getName(); + return new ModAnnotation.EnumHolder( + className.replace('.', '/'), + enumObject.toString() + ); + } + + return object; + } } From 1a4e892470f21771a337b79053d3ab7e0dc0345d Mon Sep 17 00:00:00 2001 From: Walker Knapp <30479917+WalkerKnapp@users.noreply.github.com> Date: Sun, 2 Aug 2020 18:06:07 -0400 Subject: [PATCH 33/73] Implement ProjectileImpactEvent (#168) --- .../event/entity/ProjectileImpactEvent.java | 97 +++++++++++++++++++ .../impl/event/entity/EntityEvents.java | 21 ++++ .../MixinExplosiveProjectileEntity.java | 48 +++++++++ .../event/entity/MixinLlamaSpitEntity.java | 52 ++++++++++ .../event/entity/MixinProjectileEntity.java | 54 +++++++++++ .../entity/MixinShulkerBulletEntity.java | 48 +++++++++ .../mixin/event/entity/MixinThrownEntity.java | 48 +++++++++ .../patchwork-events-entity.mixins.json | 7 +- .../event/ForgeEventFactory.java | 21 ++++ 9 files changed, 395 insertions(+), 1 deletion(-) create mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/ProjectileImpactEvent.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinExplosiveProjectileEntity.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLlamaSpitEntity.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinProjectileEntity.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinShulkerBulletEntity.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinThrownEntity.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/ProjectileImpactEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/ProjectileImpactEvent.java new file mode 100644 index 00000000..f84f8807 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/ProjectileImpactEvent.java @@ -0,0 +1,97 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.projectile.ExplosiveProjectileEntity; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.entity.thrown.ThrownEntity; +import net.minecraft.util.hit.HitResult; + +/** + * This event is fired when a projectile entity impacts something. + * + *

Subclasses of this event exist for more specific types of projectile.

+ * + *

This event is fired for all vanilla projectiles by Patchwork. + * Custom projectiles should fire this event via {@link net.patchworkmc.impl.event.entity.EntityEvents}, check the result, + * and cancel the impact if false.

+ * + *

This event is cancelable. When canceled, the impact will not be processed. + * Killing or other handling of the entity after event cancellation is up to the modder.

+ * + *

This event is fired on the {@link net.minecraftforge.common.MinecraftForge#EVENT_BUS}.

+ */ +public class ProjectileImpactEvent extends EntityEvent { + private final HitResult ray; + + public ProjectileImpactEvent(Entity entity, HitResult ray) { + super(entity); + this.ray = ray; + } + + @Override + public boolean isCancelable() { + return true; + } + + public HitResult getRayTraceResult() { + return ray; + } + + public static class Arrow extends ProjectileImpactEvent { + private final ProjectileEntity arrow; + + public Arrow(ProjectileEntity arrow, HitResult ray) { + super(arrow, ray); + this.arrow = arrow; + } + + public ProjectileEntity getArrow() { + return arrow; + } + } + + public static class Fireball extends ProjectileImpactEvent { + private final ExplosiveProjectileEntity fireball; + + public Fireball(ExplosiveProjectileEntity fireball, HitResult ray) { + super(fireball, ray); + this.fireball = fireball; + } + + public ExplosiveProjectileEntity getFireball() { + return fireball; + } + } + + public static class Throwable extends ProjectileImpactEvent { + private final ThrownEntity throwable; + + public Throwable(ThrownEntity throwable, HitResult ray) { + super(throwable, ray); + this.throwable = throwable; + } + + public ThrownEntity getThrowable() { + return throwable; + } + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index 96f57705..e2ee6208 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -26,6 +26,7 @@ import net.minecraftforge.common.extensions.IForgeItem; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.ProjectileImpactEvent; import net.minecraftforge.event.entity.living.AnimalTameEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingDamageEvent; @@ -56,10 +57,14 @@ import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.ExplosiveProjectileEntity; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.entity.thrown.ThrownEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; +import net.minecraft.util.hit.HitResult; import net.minecraft.world.IWorld; import net.minecraft.world.MobSpawnerLogic; import net.minecraft.world.World; @@ -196,6 +201,22 @@ public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { return MinecraftForge.EVENT_BUS.post(new AnimalTameEvent(animal, tamer)); } + public static boolean onProjectileImpact(Entity entity, HitResult ray) { + return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent(entity, ray)); + } + + public static boolean onProjectileImpact(ProjectileEntity arrow, HitResult ray) { + return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent.Arrow(arrow, ray)); + } + + public static boolean onProjectileImpact(ExplosiveProjectileEntity fireball, HitResult ray) { + return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent.Fireball(fireball, ray)); + } + + public static boolean onProjectileImpact(ThrownEntity throwable, HitResult ray) { + return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent.Throwable(throwable, ray)); + } + @Override public void onInitialize() { UseItemCallback.EVENT.register((player, world, hand) -> { diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinExplosiveProjectileEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinExplosiveProjectileEntity.java new file mode 100644 index 00000000..5e08f1aa --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinExplosiveProjectileEntity.java @@ -0,0 +1,48 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +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.Redirect; + +import net.minecraft.entity.projectile.ExplosiveProjectileEntity; +import net.minecraft.util.hit.HitResult; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(ExplosiveProjectileEntity.class) +public abstract class MixinExplosiveProjectileEntity { + @Shadow + protected abstract void onCollision(HitResult hitResult); + + /** + * Mixin to the redirect the onCollision method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}. + * + *

Note: In future versions, the @Redirect should be replaced with a @ModifyVariable to the bl flag.

+ */ + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/ExplosiveProjectileEntity;onCollision(Lnet/minecraft/util/hit/HitResult;)V")) + private void hookTick(ExplosiveProjectileEntity entity, HitResult hitResult) { + if (!EntityEvents.onProjectileImpact(entity, hitResult)) { + this.onCollision(hitResult); + } + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLlamaSpitEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLlamaSpitEntity.java new file mode 100644 index 00000000..6581436e --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLlamaSpitEntity.java @@ -0,0 +1,52 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.entity.projectile.LlamaSpitEntity; +import net.minecraft.util.hit.HitResult; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(LlamaSpitEntity.class) +public class MixinLlamaSpitEntity { + /** + * Mixin to the projectile hit method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}. + * + *

This will cancel the rest of method_7481 if the forge event pipeline requests it, but a Fabric mod with higher + * priority can still inject into its head.

+ * + *

This mixin is implemented differently from the other onProjectileImpact mixins because there is no check that + * the hit didn't miss before calling onHit, so we need to maintain calls to onHit for missed shots, but still need + * to check that it didn't miss before calling onProjectileImpact.

+ */ + @Inject(method = "method_7481", at = @At("HEAD"), cancellable = true) + private void hookHit(HitResult hitResult, CallbackInfo callback) { + LlamaSpitEntity entity = (LlamaSpitEntity) (Object) this; + + if (EntityEvents.onProjectileImpact(entity, hitResult)) { + callback.cancel(); + } + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinProjectileEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinProjectileEntity.java new file mode 100644 index 00000000..27da7c5d --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinProjectileEntity.java @@ -0,0 +1,54 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.util.hit.HitResult; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(ProjectileEntity.class) +public class MixinProjectileEntity { + /** + * Mixin to the projectile hit method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}. + * + *

This will cancel the rest of onHit if the event pipeline requests it, but a Fabric mod with higher + * priority can still inject into its head.

+ * + *

This mixin is implemented differently from the other onProjectileImpact mixins because there is no check that + * the hit didn't miss before calling onHit, so we need to maintain calls to onHit for missed shots, but still need + * to check that it didn't miss before calling onProjectileImpact.

+ */ + @Inject(method = "onHit(Lnet/minecraft/util/hit/HitResult;)V", at = @At("HEAD"), cancellable = true) + private void hookHit(HitResult hitResult, CallbackInfo callback) { + if (hitResult.getType() != HitResult.Type.MISS) { + ProjectileEntity entity = (ProjectileEntity) (Object) this; + + if (EntityEvents.onProjectileImpact(entity, hitResult)) { + callback.cancel(); + } + } + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinShulkerBulletEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinShulkerBulletEntity.java new file mode 100644 index 00000000..4f9a1062 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinShulkerBulletEntity.java @@ -0,0 +1,48 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +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.Redirect; + +import net.minecraft.entity.projectile.ShulkerBulletEntity; +import net.minecraft.util.hit.HitResult; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(ShulkerBulletEntity.class) +public abstract class MixinShulkerBulletEntity { + @Shadow + protected abstract void onHit(HitResult hitResult); + + /** + * Mixin to the redirect the ShulkerBulletEntity hit method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}. + * + *

Note: In future versions, the @Redirect should be replaced with a @ModifyVariable to the bl flag.

+ */ + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/ShulkerBulletEntity;onHit(Lnet/minecraft/util/hit/HitResult;)V")) + private void hookTick(ShulkerBulletEntity entity, HitResult hitResult) { + if (!EntityEvents.onProjectileImpact(entity, hitResult)) { + this.onHit(hitResult); + } + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinThrownEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinThrownEntity.java new file mode 100644 index 00000000..bc0d7ef0 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinThrownEntity.java @@ -0,0 +1,48 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +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.Redirect; + +import net.minecraft.entity.thrown.ThrownEntity; +import net.minecraft.util.hit.HitResult; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(ThrownEntity.class) +public abstract class MixinThrownEntity { + @Shadow + protected abstract void onCollision(HitResult hitResult); + + /** + * Mixin to the redirect the ThrownEntity hit method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}. + * + *

Note: In future versions, the @Redirect should be replaced with a @ModifyVariable to the bl flag.

+ */ + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/thrown/ThrownEntity;onCollision(Lnet/minecraft/util/hit/HitResult;)V")) + private void hookTick(ThrownEntity entity, HitResult hitResult) { + if (!EntityEvents.onProjectileImpact(entity, hitResult)) { + this.onCollision(hitResult); + } + } +} diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 7c76cbce..55275923 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -8,23 +8,28 @@ "MixinEntityTrackerEntry", "MixinEntityType", "MixinExperienceOrbEntity", + "MixinExplosiveProjectileEntity", "MixinFishingBobberEntity", "MixinFurnaceOutputSlot", "MixinHorseBondWithPlayerGoal", "MixinItemEntity", "MixinLivingEntity", + "MixinLlamaSpitEntity", "MixinMobEntity", "MixinMobSpawnerLogic", "MixinPlayerEntity", "MixinPlayerManager", + "MixinProjectileEntity", "MixinServerPlayerEntity", "MixinServerWorld", + "MixinShulkerBulletEntity", "MixinSpawnHelper", + "MixinThrownEntity", "MixinWorldChunk" ], "client": [ - "MixinClientWorld", "MixinClientPlayerEntity", + "MixinClientWorld", "MixinItemStack", "MixinOtherClientPlayerEntity" ], diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 779dc74a..27cd34c2 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -29,9 +29,14 @@ import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.Entity; +import net.minecraft.entity.projectile.ExplosiveProjectileEntity; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.entity.thrown.ThrownEntity; import net.minecraft.loot.LootManager; import net.minecraft.loot.LootTable; import net.minecraft.util.Identifier; +import net.minecraft.util.hit.HitResult; import net.minecraft.world.IWorld; import net.minecraft.world.MobSpawnerLogic; import net.minecraft.world.World; @@ -87,4 +92,20 @@ public static float fireBlockHarvesting(DefaultedList drops, World wo public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { return EntityEvents.onAnimalTame(animal, tamer); } + + public static boolean onProjectileImpact(Entity entity, HitResult ray) { + return EntityEvents.onProjectileImpact(entity, ray); + } + + public static boolean onProjectileImpact(ProjectileEntity arrow, HitResult ray) { + return EntityEvents.onProjectileImpact(arrow, ray); + } + + public static boolean onProjectileImpact(ExplosiveProjectileEntity fireball, HitResult ray) { + return EntityEvents.onProjectileImpact(fireball, ray); + } + + public static boolean onProjectileImpact(ThrownEntity throwable, HitResult ray) { + return EntityEvents.onProjectileImpact(throwable, ray); + } } From 515c8ac068ba16bce4e3d746b06b9bce23c40e0d Mon Sep 17 00:00:00 2001 From: Gamma <20158146+GammaWhiskey@users.noreply.github.com> Date: Sun, 2 Aug 2020 18:07:19 -0400 Subject: [PATCH 34/73] Fix Dedicated Server inject using CallbackInfo instead of CallbackInfoReturnable (#166) --- .../mixin/event/lifecycle/MixinMinecraftDedicatedServer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftDedicatedServer.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftDedicatedServer.java index 8988b3f7..777948bc 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftDedicatedServer.java +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftDedicatedServer.java @@ -22,7 +22,7 @@ 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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.MinecraftDedicatedServer; @@ -32,7 +32,7 @@ @Mixin(MinecraftDedicatedServer.class) public class MixinMinecraftDedicatedServer { @Inject(method = "setupServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/UserCache;setUseRemote(Z)V", shift = At.Shift.AFTER)) - private void onServerAboutToStart(CallbackInfo ci) { + private void onServerAboutToStart(CallbackInfoReturnable cir) { LifecycleEvents.handleLoadComplete(); // This is a "multithreaded" event that would be called around this time. LifecycleEvents.handleServerAboutToStart((MinecraftServer) (Object) this); } From 3d5e35e72ae5b8a0d79393488b61738fab383fda Mon Sep 17 00:00:00 2001 From: Snakefangox Date: Tue, 4 Aug 2020 13:58:05 +1200 Subject: [PATCH 35/73] Refactor PatchworkKeyBinding (#170) * Refactor PatchworkKeyBinding * Remove old file --- .../keybindings/PatchworkKeyBinding.java} | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) rename patchwork-key-bindings/src/main/java/net/patchworkmc/{impl/keybindings/PatchworkKeybinding.java => api/keybindings/PatchworkKeyBinding.java} (81%) diff --git a/patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/PatchworkKeybinding.java b/patchwork-key-bindings/src/main/java/net/patchworkmc/api/keybindings/PatchworkKeyBinding.java similarity index 81% rename from patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/PatchworkKeybinding.java rename to patchwork-key-bindings/src/main/java/net/patchworkmc/api/keybindings/PatchworkKeyBinding.java index a4aef14c..664b217b 100644 --- a/patchwork-key-bindings/src/main/java/net/patchworkmc/impl/keybindings/PatchworkKeybinding.java +++ b/patchwork-key-bindings/src/main/java/net/patchworkmc/api/keybindings/PatchworkKeyBinding.java @@ -17,7 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.patchworkmc.impl.keybindings; +package net.patchworkmc.api.keybindings; import net.minecraftforge.client.extensions.IForgeKeybinding; import net.minecraftforge.client.settings.IKeyConflictContext; @@ -28,30 +28,32 @@ import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -public class PatchworkKeybinding extends KeyBinding { - public PatchworkKeybinding(String id, int keyCode, String category) { +import net.patchworkmc.impl.keybindings.ForgeKeyBindingConstruct; + +public class PatchworkKeyBinding extends KeyBinding { + public PatchworkKeyBinding(String id, int keyCode, String category) { super(id, keyCode, category); KeyBindingHelper.registerKeyBinding(this); } - public PatchworkKeybinding(String id, InputUtil.Type type, int code, String category) { + public PatchworkKeyBinding(String id, InputUtil.Type type, int code, String category) { super(id, type, code, category); KeyBindingHelper.registerKeyBinding(this); } - public PatchworkKeybinding(String id, IKeyConflictContext keyConflictContext, final InputUtil.Type inputType, final int keyCode, String category) { + public PatchworkKeyBinding(String id, IKeyConflictContext keyConflictContext, final InputUtil.Type inputType, final int keyCode, String category) { this(id, keyConflictContext, inputType.createFromCode(keyCode), category); } - public PatchworkKeybinding(String id, IKeyConflictContext keyConflictContext, InputUtil.KeyCode keyCode, String category) { + public PatchworkKeyBinding(String id, IKeyConflictContext keyConflictContext, InputUtil.KeyCode keyCode, String category) { this(id, keyConflictContext, KeyModifier.NONE, keyCode, category); } - public PatchworkKeybinding(String id, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, final InputUtil.Type inputType, final int keyCode, String category) { + public PatchworkKeyBinding(String id, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, final InputUtil.Type inputType, final int keyCode, String category) { this(id, keyConflictContext, keyModifier, inputType.createFromCode(keyCode), category); } - public PatchworkKeybinding(String id, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, InputUtil.KeyCode keyCode, String category) { + public PatchworkKeyBinding(String id, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, InputUtil.KeyCode keyCode, String category) { super(id, keyCode.getCategory(), keyCode.getKeyCode(), category); ((IForgeKeybinding) this).setKeyConflictContext(keyConflictContext); ((IForgeKeybinding) this).setKeyModifierAndCode(keyModifier, keyCode); From fc655ee13eacf200f2fe682e03904800eb571db5 Mon Sep 17 00:00:00 2001 From: Glitch Date: Tue, 4 Aug 2020 20:52:03 -0500 Subject: [PATCH 36/73] Move the Forge EventBus (and some other classes) to api-base (#164) --- .../src/main/java/net/minecraftforge/api/distmarker/Dist.java | 0 .../main/java/net/minecraftforge/common/MinecraftForge.java | 0 .../src/main/java/net/minecraftforge/fml/LogicalSide.java | 0 patchwork-api-base/src/main/resources/fabric.mod.json | 2 +- patchwork-capabilities/build.gradle | 1 - patchwork-capabilities/src/main/resources/fabric.mod.json | 1 - patchwork-data-generators/src/main/resources/fabric.mod.json | 3 ++- patchwork-events-entity/build.gradle | 1 - patchwork-events-entity/src/main/resources/fabric.mod.json | 1 - patchwork-events-input/build.gradle | 1 - patchwork-events-input/src/main/resources/fabric.mod.json | 3 +-- patchwork-events-rendering/build.gradle | 1 - patchwork-events-rendering/src/main/resources/fabric.mod.json | 3 +-- patchwork-events-world/build.gradle | 1 - patchwork-events-world/src/main/resources/fabric.mod.json | 1 - patchwork-extensions-shearing/build.gradle | 1 - .../src/main/resources/fabric.mod.json | 1 - patchwork-gui/build.gradle | 1 - patchwork-gui/src/main/resources/fabric.mod.json | 1 - patchwork-loot/build.gradle | 1 - patchwork-networking-messages/build.gradle | 1 - .../src/main/resources/fabric.mod.json | 1 - 22 files changed, 5 insertions(+), 21 deletions(-) rename {patchwork-fml => patchwork-api-base}/src/main/java/net/minecraftforge/api/distmarker/Dist.java (100%) rename {patchwork-fml => patchwork-api-base}/src/main/java/net/minecraftforge/common/MinecraftForge.java (100%) rename {patchwork-fml => patchwork-api-base}/src/main/java/net/minecraftforge/fml/LogicalSide.java (100%) diff --git a/patchwork-fml/src/main/java/net/minecraftforge/api/distmarker/Dist.java b/patchwork-api-base/src/main/java/net/minecraftforge/api/distmarker/Dist.java similarity index 100% rename from patchwork-fml/src/main/java/net/minecraftforge/api/distmarker/Dist.java rename to patchwork-api-base/src/main/java/net/minecraftforge/api/distmarker/Dist.java diff --git a/patchwork-fml/src/main/java/net/minecraftforge/common/MinecraftForge.java b/patchwork-api-base/src/main/java/net/minecraftforge/common/MinecraftForge.java similarity index 100% rename from patchwork-fml/src/main/java/net/minecraftforge/common/MinecraftForge.java rename to patchwork-api-base/src/main/java/net/minecraftforge/common/MinecraftForge.java diff --git a/patchwork-fml/src/main/java/net/minecraftforge/fml/LogicalSide.java b/patchwork-api-base/src/main/java/net/minecraftforge/fml/LogicalSide.java similarity index 100% rename from patchwork-fml/src/main/java/net/minecraftforge/fml/LogicalSide.java rename to patchwork-api-base/src/main/java/net/minecraftforge/fml/LogicalSide.java diff --git a/patchwork-api-base/src/main/resources/fabric.mod.json b/patchwork-api-base/src/main/resources/fabric.mod.json index 1b530f19..4f19bf71 100644 --- a/patchwork-api-base/src/main/resources/fabric.mod.json +++ b/patchwork-api-base/src/main/resources/fabric.mod.json @@ -17,7 +17,7 @@ "fabricloader": ">=0.8.4", "fabric": ">=0.15.1" }, - "description": "Common zero-overhead classes used across Patchwork modules", + "description": "Common classes that don't require Mixins or involve mod loading", "custom": { "modmenu:api": true, "modmenu:parent": "patchwork" diff --git a/patchwork-capabilities/build.gradle b/patchwork-capabilities/build.gradle index f1be1c41..0a376f19 100644 --- a/patchwork-capabilities/build.gradle +++ b/patchwork-capabilities/build.gradle @@ -3,5 +3,4 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-capabilities/src/main/resources/fabric.mod.json b/patchwork-capabilities/src/main/resources/fabric.mod.json index 7b20ca58..ef217ff5 100644 --- a/patchwork-capabilities/src/main/resources/fabric.mod.json +++ b/patchwork-capabilities/src/main/resources/fabric.mod.json @@ -14,7 +14,6 @@ ], "depends": { "patchwork-api-base": "*", - "patchwork-fml": "*" }, "mixins": [ "patchwork-capabilities.mixins.json" diff --git a/patchwork-data-generators/src/main/resources/fabric.mod.json b/patchwork-data-generators/src/main/resources/fabric.mod.json index 16c6dfc2..1bc564f2 100644 --- a/patchwork-data-generators/src/main/resources/fabric.mod.json +++ b/patchwork-data-generators/src/main/resources/fabric.mod.json @@ -13,7 +13,8 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*" + "patchwork-api-base": "*", + "patchwork-fml": "*" }, "mixins": [ ], diff --git a/patchwork-events-entity/build.gradle b/patchwork-events-entity/build.gradle index 0c0ccee0..60c8a0a1 100644 --- a/patchwork-events-entity/build.gradle +++ b/patchwork-events-entity/build.gradle @@ -3,7 +3,6 @@ version = getSubprojectVersion(project, "0.5.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') implementation project(path: ':patchwork-extensions', configuration: 'dev') implementation project(path: ':patchwork-extensions-item', configuration: 'dev') } diff --git a/patchwork-events-entity/src/main/resources/fabric.mod.json b/patchwork-events-entity/src/main/resources/fabric.mod.json index 9cd93e4a..f3a9aaed 100644 --- a/patchwork-events-entity/src/main/resources/fabric.mod.json +++ b/patchwork-events-entity/src/main/resources/fabric.mod.json @@ -17,7 +17,6 @@ }, "depends": { "patchwork-api-base": "*", - "patchwork-fml": "*", "patchwork-extensions-item": "*" }, "mixins": [ diff --git a/patchwork-events-input/build.gradle b/patchwork-events-input/build.gradle index c8587791..f1ce9aa8 100644 --- a/patchwork-events-input/build.gradle +++ b/patchwork-events-input/build.gradle @@ -3,5 +3,4 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-events-input/src/main/resources/fabric.mod.json b/patchwork-events-input/src/main/resources/fabric.mod.json index 9bac8440..7b8dd8a5 100644 --- a/patchwork-events-input/src/main/resources/fabric.mod.json +++ b/patchwork-events-input/src/main/resources/fabric.mod.json @@ -13,8 +13,7 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*", - "patchwork-fml": "*" + "patchwork-api-base": "*" }, "mixins": [ "patchwork-events-input.mixins.json" diff --git a/patchwork-events-rendering/build.gradle b/patchwork-events-rendering/build.gradle index 16784a5e..68e8173b 100644 --- a/patchwork-events-rendering/build.gradle +++ b/patchwork-events-rendering/build.gradle @@ -3,5 +3,4 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-events-rendering/src/main/resources/fabric.mod.json b/patchwork-events-rendering/src/main/resources/fabric.mod.json index d8f37a2d..8ad3995c 100644 --- a/patchwork-events-rendering/src/main/resources/fabric.mod.json +++ b/patchwork-events-rendering/src/main/resources/fabric.mod.json @@ -13,8 +13,7 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*", - "patchwork-fml": "*" + "patchwork-api-base": "*" }, "mixins": [ "patchwork-events-rendering.mixins.json" diff --git a/patchwork-events-world/build.gradle b/patchwork-events-world/build.gradle index 06036392..b8809b37 100644 --- a/patchwork-events-world/build.gradle +++ b/patchwork-events-world/build.gradle @@ -3,5 +3,4 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-events-world/src/main/resources/fabric.mod.json b/patchwork-events-world/src/main/resources/fabric.mod.json index 7a5d1dbf..531ff2d6 100644 --- a/patchwork-events-world/src/main/resources/fabric.mod.json +++ b/patchwork-events-world/src/main/resources/fabric.mod.json @@ -14,7 +14,6 @@ ], "depends": { "patchwork-api-base": "*", - "patchwork-fml": "*" }, "mixins": [ "patchwork-events-world.mixins.json" diff --git a/patchwork-extensions-shearing/build.gradle b/patchwork-extensions-shearing/build.gradle index 1faf845c..d5a35e96 100644 --- a/patchwork-extensions-shearing/build.gradle +++ b/patchwork-extensions-shearing/build.gradle @@ -3,5 +3,4 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-extensions-shearing/src/main/resources/fabric.mod.json b/patchwork-extensions-shearing/src/main/resources/fabric.mod.json index 3d37616d..6e3a93e2 100644 --- a/patchwork-extensions-shearing/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-shearing/src/main/resources/fabric.mod.json @@ -14,7 +14,6 @@ ], "depends": { "patchwork-api-base": "*", - "patchwork-fml": "*" }, "mixins": [ "patchwork-extensions-shearing.mixins.json" diff --git a/patchwork-gui/build.gradle b/patchwork-gui/build.gradle index 200b9b8a..be606503 100644 --- a/patchwork-gui/build.gradle +++ b/patchwork-gui/build.gradle @@ -3,5 +3,4 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-gui/src/main/resources/fabric.mod.json b/patchwork-gui/src/main/resources/fabric.mod.json index 535cd7f4..8fd841cb 100644 --- a/patchwork-gui/src/main/resources/fabric.mod.json +++ b/patchwork-gui/src/main/resources/fabric.mod.json @@ -14,7 +14,6 @@ ], "depends": { "patchwork-api-base": "*", - "patchwork-fml": "*" }, "mixins": [ "patchwork-gui.mixins.json" diff --git a/patchwork-loot/build.gradle b/patchwork-loot/build.gradle index 0f3d0fb1..7b270e2c 100644 --- a/patchwork-loot/build.gradle +++ b/patchwork-loot/build.gradle @@ -3,6 +3,5 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-networking-messages/build.gradle b/patchwork-networking-messages/build.gradle index 6a8bfc95..c88ad201 100644 --- a/patchwork-networking-messages/build.gradle +++ b/patchwork-networking-messages/build.gradle @@ -3,6 +3,5 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-fml', configuration: 'dev') implementation project(path: ':patchwork-networking', configuration: 'dev') } diff --git a/patchwork-networking-messages/src/main/resources/fabric.mod.json b/patchwork-networking-messages/src/main/resources/fabric.mod.json index 1e74eee8..7ac1725b 100644 --- a/patchwork-networking-messages/src/main/resources/fabric.mod.json +++ b/patchwork-networking-messages/src/main/resources/fabric.mod.json @@ -14,7 +14,6 @@ ], "depends": { "patchwork-api-base": "*", - "patchwork-fml": "*", "patchwork-networking": "*" }, "entrypoints": { From 7f4157788f6891e3c5d5fed32ef6fb7b40da1914 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Tue, 4 Aug 2020 21:17:25 -0500 Subject: [PATCH 37/73] Hotfix: Remove trailing commas --- patchwork-capabilities/src/main/resources/fabric.mod.json | 2 +- patchwork-events-world/src/main/resources/fabric.mod.json | 2 +- .../src/main/resources/fabric.mod.json | 2 +- patchwork-gui/src/main/resources/fabric.mod.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/patchwork-capabilities/src/main/resources/fabric.mod.json b/patchwork-capabilities/src/main/resources/fabric.mod.json index ef217ff5..09d3abf5 100644 --- a/patchwork-capabilities/src/main/resources/fabric.mod.json +++ b/patchwork-capabilities/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*", + "patchwork-api-base": "*" }, "mixins": [ "patchwork-capabilities.mixins.json" diff --git a/patchwork-events-world/src/main/resources/fabric.mod.json b/patchwork-events-world/src/main/resources/fabric.mod.json index 531ff2d6..509b8176 100644 --- a/patchwork-events-world/src/main/resources/fabric.mod.json +++ b/patchwork-events-world/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*", + "patchwork-api-base": "*" }, "mixins": [ "patchwork-events-world.mixins.json" diff --git a/patchwork-extensions-shearing/src/main/resources/fabric.mod.json b/patchwork-extensions-shearing/src/main/resources/fabric.mod.json index 6e3a93e2..ba76f678 100644 --- a/patchwork-extensions-shearing/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-shearing/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*", + "patchwork-api-base": "*" }, "mixins": [ "patchwork-extensions-shearing.mixins.json" diff --git a/patchwork-gui/src/main/resources/fabric.mod.json b/patchwork-gui/src/main/resources/fabric.mod.json index 8fd841cb..cea0eadf 100644 --- a/patchwork-gui/src/main/resources/fabric.mod.json +++ b/patchwork-gui/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*", + "patchwork-api-base": "*" }, "mixins": [ "patchwork-gui.mixins.json" From eef59b69155abd790cbdb1b1b9c0799175f03a9b Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Tue, 4 Aug 2020 21:37:51 -0500 Subject: [PATCH 38/73] Hotfix: Make patchwork-networking-messages work on the server --- .../PatchworkPlayNetworkingMessages.java | 26 ++++--------------- ...PatchworkPlayNetworkingMessagesClient.java | 26 +++++++++++++++++++ .../networking/MixinServerPlayerEntity.java | 22 ++++++---------- .../src/main/resources/fabric.mod.json | 3 +++ .../patchwork-networking-messages.mixins.json | 3 ++- 5 files changed, 44 insertions(+), 36 deletions(-) create mode 100644 patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessagesClient.java diff --git a/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessages.java b/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessages.java index d1b0ae9a..1db5de7a 100644 --- a/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessages.java +++ b/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessages.java @@ -37,36 +37,20 @@ import net.minecraft.util.PacketByteBuf; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; public class PatchworkPlayNetworkingMessages implements ModInitializer, MessageFactory { - private static final Logger LOGGER = LogManager.getLogger("patchwork-networking"); - private static final Identifier IDENTIFIER = new Identifier("fml", "play"); - private static final NetworkChannelVersion VERSION = new NetworkChannelVersion("FML2", version -> true, version -> true); - private static final short SPAWN_ENTITY = 0; - private static final short OPEN_CONTAINER = 1; + public static final Logger LOGGER = LogManager.getLogger("patchwork-networking"); + public static final Identifier IDENTIFIER = new Identifier("fml", "play"); + public static final NetworkChannelVersion VERSION = new NetworkChannelVersion("FML2", version -> true, version -> true); + public static final short SPAWN_ENTITY = 0; + public static final short OPEN_CONTAINER = 1; @Override public void onInitialize() { PatchworkNetworking.getVersionManager().createChannel(IDENTIFIER, VERSION); PatchworkNetworking.setFactory(this); - // TODO: Move to client initializer - ClientSidePacketRegistry.INSTANCE.register(IDENTIFIER, (context, buf) -> { - int id = buf.readUnsignedByte(); - - if (id == SPAWN_ENTITY) { - FMLPlayMessages.SpawnEntity spawn = FMLPlayMessages.SpawnEntity.decode(buf); - FMLPlayMessages.SpawnEntity.handle(spawn, context); - } else if (id == OPEN_CONTAINER) { - FMLPlayMessages.OpenContainer open = FMLPlayMessages.OpenContainer.decode(buf); - FMLPlayMessages.OpenContainer.handle(open, context); - } else { - LOGGER.warn("Received an unknown fml:play message with an id of {} and a payload of {} bytes", id, buf.readableBytes()); - } - }); - ServerSidePacketRegistry.INSTANCE.register(IDENTIFIER, (context, buf) -> { LOGGER.warn("Received an fml:play on the server, this should not happen! Kicking the offending client."); diff --git a/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessagesClient.java b/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessagesClient.java new file mode 100644 index 00000000..ec13eac2 --- /dev/null +++ b/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessagesClient.java @@ -0,0 +1,26 @@ +package net.patchworkmc.impl.networking; + +import net.minecraftforge.fml.network.FMLPlayMessages; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; + +public class PatchworkPlayNetworkingMessagesClient implements ClientModInitializer { + @Override + public void onInitializeClient() { + // TODO: Move to client initializer + ClientSidePacketRegistry.INSTANCE.register(PatchworkPlayNetworkingMessages.IDENTIFIER, (context, buf) -> { + int id = buf.readUnsignedByte(); + + if (id == PatchworkPlayNetworkingMessages.SPAWN_ENTITY) { + FMLPlayMessages.SpawnEntity spawn = FMLPlayMessages.SpawnEntity.decode(buf); + FMLPlayMessages.SpawnEntity.handle(spawn, context); + } else if (id == PatchworkPlayNetworkingMessages.OPEN_CONTAINER) { + FMLPlayMessages.OpenContainer open = FMLPlayMessages.OpenContainer.decode(buf); + FMLPlayMessages.OpenContainer.handle(open, context); + } else { + PatchworkPlayNetworkingMessages.LOGGER.warn("Received an unknown fml:play message with an id of {} and a payload of {} bytes", id, buf.readableBytes()); + } + }); + } +} diff --git a/patchwork-networking-messages/src/main/java/net/patchworkmc/mixin/networking/MixinServerPlayerEntity.java b/patchwork-networking-messages/src/main/java/net/patchworkmc/mixin/networking/MixinServerPlayerEntity.java index 55c8ec24..f43fcc2d 100644 --- a/patchwork-networking-messages/src/main/java/net/patchworkmc/mixin/networking/MixinServerPlayerEntity.java +++ b/patchwork-networking-messages/src/main/java/net/patchworkmc/mixin/networking/MixinServerPlayerEntity.java @@ -20,29 +20,23 @@ package net.patchworkmc.mixin.networking; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.asm.mixin.Shadow; import net.minecraft.server.network.ServerPlayerEntity; import net.patchworkmc.impl.networking.ContainerSyncAccess; @Mixin(ServerPlayerEntity.class) -public class MixinServerPlayerEntity implements ContainerSyncAccess { - @Accessor - private int getContainerSyncId() { - throw new AssertionError("Mixin not applied"); - } - - @Invoker - private void invokeIncrementContainerSyncId() { - throw new AssertionError("Mixin not applied"); - } +public abstract class MixinServerPlayerEntity implements ContainerSyncAccess { + @Shadow + private int containerSyncId; + @Shadow + protected abstract void incrementContainerSyncId(); @Override public int patchwork$getNewContainerSyncId() { - invokeIncrementContainerSyncId(); + incrementContainerSyncId(); - return getContainerSyncId(); + return containerSyncId; } } diff --git a/patchwork-networking-messages/src/main/resources/fabric.mod.json b/patchwork-networking-messages/src/main/resources/fabric.mod.json index 7ac1725b..45f3390f 100644 --- a/patchwork-networking-messages/src/main/resources/fabric.mod.json +++ b/patchwork-networking-messages/src/main/resources/fabric.mod.json @@ -19,6 +19,9 @@ "entrypoints": { "main": [ "net.patchworkmc.impl.networking.PatchworkPlayNetworkingMessages" + ], + "client": [ + "net.patchworkmc.impl.networking.PatchworkPlayNetworkingMessagesClient" ] }, "mixins": [ diff --git a/patchwork-networking-messages/src/main/resources/patchwork-networking-messages.mixins.json b/patchwork-networking-messages/src/main/resources/patchwork-networking-messages.mixins.json index 0cd067e8..37fda991 100644 --- a/patchwork-networking-messages/src/main/resources/patchwork-networking-messages.mixins.json +++ b/patchwork-networking-messages/src/main/resources/patchwork-networking-messages.mixins.json @@ -4,7 +4,8 @@ "compatibilityLevel": "JAVA_8", "mixins": [ "MixinEntityType", - "MixinEntityTypeBuilder" + "MixinEntityTypeBuilder", + "MixinServerPlayerEntity" ], "injectors": { "defaultRequire": 1 From 31e2fcacc2851e3aef781ef84c8ca766b0d8f929 Mon Sep 17 00:00:00 2001 From: Kitlith Date: Thu, 6 Aug 2020 13:39:39 -0700 Subject: [PATCH 39/73] `./gradlew licenseFormat` at the behest of Glitch --- ...PatchworkPlayNetworkingMessagesClient.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessagesClient.java b/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessagesClient.java index ec13eac2..1c5a5825 100644 --- a/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessagesClient.java +++ b/patchwork-networking-messages/src/main/java/net/patchworkmc/impl/networking/PatchworkPlayNetworkingMessagesClient.java @@ -1,3 +1,22 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + package net.patchworkmc.impl.networking; import net.minecraftforge.fml.network.FMLPlayMessages; From 7d7f2b12316696c348089b99c0e02858aaedeec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Sat, 8 Aug 2020 08:47:41 +1000 Subject: [PATCH 40/73] Impl removedByPlayer and canHarvestBlock in IForgeBlock (#126) * Impl removedByPlayer and canHarvestBlock in IForgeBlock * Apply kitlith's suggestions * Fix ThreadLocal memory leakage * Apply suggestions * Remove unneeded dependency Co-authored-by: TheGlitch76 --- patchwork-events-world/build.gradle | 1 + .../event/world/BlockEvent.java | 18 +-- .../impl/event/world/WorldEvents.java | 59 +++++++++ .../MixinServerPlayerInteractionManager.java | 66 ++-------- .../src/main/resources/fabric.mod.json | 3 +- patchwork-extensions-block/build.gradle | 1 + .../common/extensions/IForgeBlock.java | 28 +++-- .../common/extensions/IForgeBlockState.java | 15 ++- .../impl/extensions/block/BlockContext.java | 22 ++-- .../extensions/block/BlockHarvestManager.java | 101 +++++++++++++++ .../impl/extensions/block/PatchworkBlock.java | 26 ++++ .../mixin/extensions/block/MixinBlock.java | 14 +++ .../block/flammable/MixinWorld.java | 49 ++++++++ .../MixinClientPlayerInteractionManager.java | 56 +++++++++ .../block/harvest/MixinOreBlock.java | 42 +++++++ .../block/harvest/MixinRedstoneOreBlock.java | 36 ++++++ .../MixinServerPlayerInteractionManager.java | 119 ++++++++++++++++++ .../block/harvest/MixinSpawnerBlock.java | 36 ++++++ .../src/main/resources/fabric.mod.json | 5 +- ...ork-extensions-block-flammable.mixins.json | 11 ++ ...hwork-extensions-block-harvest.mixins.json | 17 +++ .../patchwork-extensions-block.accesswidener | 2 + 22 files changed, 635 insertions(+), 92 deletions(-) create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinClientPlayerInteractionManager.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java create mode 100644 patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json create mode 100644 patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json diff --git a/patchwork-events-world/build.gradle b/patchwork-events-world/build.gradle index b8809b37..913a6bf0 100644 --- a/patchwork-events-world/build.gradle +++ b/patchwork-events-world/build.gradle @@ -3,4 +3,5 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-extensions-block', configuration: 'dev') } diff --git a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java index 57308dd5..07123fb3 100644 --- a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java +++ b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java @@ -21,16 +21,21 @@ import java.util.List; +import net.minecraftforge.common.extensions.IForgeBlockState; import net.minecraftforge.eventbus.api.Event; import net.minecraft.item.ItemStack; import net.minecraft.util.DefaultedList; import net.minecraft.block.BlockState; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; import net.minecraft.world.World; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; + public class BlockEvent extends Event { private final IWorld world; private final BlockPos pos; @@ -73,17 +78,14 @@ public BreakEvent(World world, BlockPos pos, BlockState state, PlayerEntity play this.player = player; this.exp = 0; - // TODO: BlockState#getExpDrop - - /* // Handle empty block or player unable to break block scenario - if (state == null || !ForgeHooks.canHarvestBlock(state, player, world, pos)) { + if (state == null || !BlockHarvestManager.canHarvestBlock(state, player, world, pos)) { this.exp = 0; } else { - int bonusLevel = EnchantmentHelper.getLevel(Enchantments.FORTUNE, player.getHeldItemMainhand()); - int silklevel = EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, player.getHeldItemMainhand()); - this.exp = state.getExpDrop(world, pos, bonusLevel, silklevel); - }*/ + int bonusLevel = EnchantmentHelper.getLevel(Enchantments.FORTUNE, player.getMainHandStack()); + int silklevel = EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, player.getMainHandStack()); + this.exp = ((IForgeBlockState) state).getExpDrop(world, pos, bonusLevel, silklevel); + } } public PlayerEntity getPlayer() { diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index 4b33e3a3..cae0e965 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -28,14 +28,19 @@ import net.minecraftforge.event.world.WorldEvent; import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.DefaultedList; import net.minecraft.world.World; import net.minecraft.entity.EntityCategory; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.EmptyBlockView; +import net.minecraft.world.GameMode; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; @@ -72,6 +77,60 @@ public static void onWorldSave(IWorld world) { MinecraftForge.EVENT_BUS.post(new WorldEvent.Save(world)); } + /** + * Called by Mixin and ForgeHooks. + * @return experience dropped, -1 = block breaking is cancelled. + */ + public static int onBlockBreakEvent(World world, GameMode gameMode, ServerPlayerEntity player, BlockPos pos) { + // Logic from tryHarvestBlock for pre-canceling the event + boolean preCancelEvent = false; + + ItemStack itemstack = player.getMainHandStack(); + + if (!itemstack.isEmpty() && !itemstack.getItem().canMine(world.getBlockState(pos), world, pos, player)) { + preCancelEvent = true; + } + + // method_21701 => canMine + // Isn't the function really canNotMine? + + if (player.method_21701(world, pos, gameMode)) { + preCancelEvent = true; + } + + // Tell client the block is gone immediately then process events + if (world.getBlockEntity(pos) == null) { + player.networkHandler.sendPacket(new BlockUpdateS2CPacket(EmptyBlockView.INSTANCE, pos)); + } + + // Post the block break event + BlockState state = world.getBlockState(pos); + BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player); + event.setCanceled(preCancelEvent); + MinecraftForge.EVENT_BUS.post(event); + + // Handle if the event is canceled + if (event.isCanceled()) { + // Let the client know the block still exists + player.networkHandler.sendPacket(new BlockUpdateS2CPacket(world, pos)); + + // Update any block entity data for this block + BlockEntity entity = world.getBlockEntity(pos); + + if (entity != null) { + BlockEntityUpdateS2CPacket packet = entity.toUpdatePacket(); + + if (packet != null) { + player.networkHandler.sendPacket(packet); + } + } + + return -1; // Cancelled + } else { + return event.getExpToDrop(); + } + } + // TODO: Leaving this unfired is intentional. See: https://github.com/MinecraftForge/MinecraftForge/issues/5828 public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(world, pos, state, fortune, dropChance, drops, player, silkTouch); diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java index 7b62fa81..713a88b2 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java @@ -19,28 +19,23 @@ package net.patchworkmc.mixin.event.world; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.world.BlockEvent; 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.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerInteractionManager; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.EmptyBlockView; import net.minecraft.world.GameMode; +import net.patchworkmc.impl.event.world.WorldEvents; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; + @Mixin(ServerPlayerInteractionManager.class) -public class MixinServerPlayerInteractionManager { +public abstract class MixinServerPlayerInteractionManager { @Shadow public ServerWorld world; @Shadow @@ -50,52 +45,17 @@ public class MixinServerPlayerInteractionManager { @Inject(method = "tryBreakBlock", at = @At("HEAD"), cancellable = true) private void hookBreakBlock(BlockPos pos, CallbackInfoReturnable callback) { - boolean preCancelEvent = false; - - ItemStack itemstack = player.getMainHandStack(); - - if (!itemstack.isEmpty() && !itemstack.getItem().canMine(world.getBlockState(pos), world, pos, player)) { - preCancelEvent = true; - } - - // method_21701 => canMine - // Isn't the function really canNotMine? - - if (player.method_21701(world, pos, gameMode)) { - preCancelEvent = true; - } - - // Tell client the block is gone immediately then process events - if (world.getBlockEntity(pos) == null) { - player.networkHandler.sendPacket(new BlockUpdateS2CPacket(EmptyBlockView.INSTANCE, pos)); - } - - // Post the block break event - BlockState state = world.getBlockState(pos); - BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player); - event.setCanceled(preCancelEvent); - MinecraftForge.EVENT_BUS.post(event); - - // Handle if the event is canceled - if (event.isCanceled()) { - // Let the client know the block still exists - player.networkHandler.sendPacket(new BlockUpdateS2CPacket(world, pos)); - - // Update any block entity data for this block - BlockEntity entity = world.getBlockEntity(pos); - - if (entity != null) { - BlockEntityUpdateS2CPacket packet = entity.toUpdatePacket(); - - if (packet != null) { - player.networkHandler.sendPacket(packet); - } - } + int exp = WorldEvents.onBlockBreakEvent(world, gameMode, player, pos); + if (exp < 0) { callback.setReturnValue(false); - } else if (event.getExpToDrop() != 0) { - // TODO: Drop experience - throw new UnsupportedOperationException("Cannot drop exp from a BreakEvent yet"); + } else { + BlockHarvestManager.pushExpDropStack(exp); } } + + @Inject(method = "tryBreakBlock", at = @At("RETURN"), cancellable = true) + private void tryBreakBlock_return(BlockPos pos, CallbackInfoReturnable callback) { + BlockHarvestManager.popExpDropStack(); + } } diff --git a/patchwork-events-world/src/main/resources/fabric.mod.json b/patchwork-events-world/src/main/resources/fabric.mod.json index 509b8176..f74ea781 100644 --- a/patchwork-events-world/src/main/resources/fabric.mod.json +++ b/patchwork-events-world/src/main/resources/fabric.mod.json @@ -13,7 +13,8 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*" + "patchwork-api-base": "*", + "patchwork-extensions-block": "*" }, "mixins": [ "patchwork-events-world.mixins.json" diff --git a/patchwork-extensions-block/build.gradle b/patchwork-extensions-block/build.gradle index 6bdfc305..94c92392 100644 --- a/patchwork-extensions-block/build.gradle +++ b/patchwork-extensions-block/build.gradle @@ -4,6 +4,7 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') implementation project(path: ':patchwork-enum-hacks', configuration: 'dev') + implementation project(path: ':patchwork-extensions-item', configuration: 'dev') implementation project(path: ':patchwork-tooltype', configuration: 'dev') } diff --git a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java index 4c540345..2a860bff 100644 --- a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java +++ b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java @@ -27,6 +27,7 @@ import javax.annotation.Nullable; import net.minecraftforge.common.IPlantable; +import net.minecraftforge.common.ToolType; import net.minecraft.block.BedBlock; import net.minecraft.block.Block; @@ -82,10 +83,12 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; +import net.patchworkmc.impl.extensions.block.PatchworkBlock; import net.patchworkmc.mixin.extensions.block.FireBlockAccessor; import net.patchworkmc.mixin.extensions.block.PlantBlockAccessor; -public interface IForgeBlock { +public interface IForgeBlock extends PatchworkBlock { default Block getBlock() { return (Block) this; } @@ -204,7 +207,7 @@ default BlockEntity createTileEntity(BlockState state, BlockView world) { return null; } - /* TODO IForgeBlock#canHarvestBlock indirectly requires ToolType (via ForgeHooks#canHarvestBlock) + /* TODO IForgeBlock#canHarvestBlock indirectly requires ToolType (via ForgeHooks#canHarvestBlock) */ /** * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed. * @@ -212,10 +215,10 @@ default BlockEntity createTileEntity(BlockState state, BlockView world) { * @param pos The block's current position * @param player The player damaging the block * @return True to spawn the drops - * + */ default boolean canHarvestBlock(BlockState state, BlockView world, BlockPos pos, PlayerEntity player) { - return ForgeHooks.canHarvestBlock(state, player, world, pos); - }*/ + return BlockHarvestManager.canHarvestBlock(state, player, world, pos); + } // TODO Call locations: Patches: ServerPlayerInteractionManager* /** @@ -240,7 +243,7 @@ default boolean canHarvestBlock(BlockState state, BlockView world, BlockPos pos, */ default boolean removedByPlayer(BlockState state, World world, BlockPos pos, PlayerEntity player, boolean willHarvest, FluidState fluid) { getBlock().onBreak(world, pos, state, player); - return world.removeBlock(pos, false); + return world.setBlockState(pos, fluid.getBlockState(), world.isClient ? 11 : 3); } // TODO Call locations: Patches: LivingEntity*, PlayerEntity*, Forge classes: ForgeEventFactory (called from LivingEntity patch) @@ -645,6 +648,7 @@ default boolean isBeaconBase(BlockState state, CollisionView world, BlockPos pos // TODO Call locations: Forge classes: BreakEvent* /** * Gathers how much experience this block drops when broken. + * TODO: there's no equivalent callback in Fabric API, so for now Fabric mods should always return 0 here. * * @param state The current state * @param world The world @@ -778,12 +782,12 @@ default boolean getWeakChanges(BlockState state, CollisionView world, BlockPos p return false; } - /* TODO IForgeBlock#getHarvestTool needs ToolType + /* TODO IForgeBlock#getHarvestTool needs ToolType */ /** * Queries the class of tool required to harvest this block, if null is returned * we assume that anything can harvest this block. - * - ToolType getHarvestTool(BlockState state);*/ + */ + ToolType getHarvestTool(BlockState state); // TODO Call locations: Patches: PickaxeItem*, Forge classes: ForgeHooks* /** @@ -793,18 +797,18 @@ default boolean getWeakChanges(BlockState state, CollisionView world, BlockPos p */ int getHarvestLevel(BlockState state); - /* TODO IForgeBlock#isToolEffective needs ToolType + /* TODO IForgeBlock#isToolEffective needs ToolType */ /** * Checks if the specified tool type is efficient on this block, * meaning that it digs at full speed. - * + */ default boolean isToolEffective(BlockState state, ToolType tool) { if (tool == ToolType.PICKAXE && (this.getBlock() == Blocks.REDSTONE_ORE || this.getBlock() == Blocks.REDSTONE_LAMP || this.getBlock() == Blocks.OBSIDIAN)) { return false; } return tool == getHarvestTool(state); - }*/ + } // TODO Call locations: Forge classes: ForgeHooksClient /** diff --git a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java index 55e94ee2..0f0c4182 100644 --- a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java +++ b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java @@ -25,6 +25,7 @@ import javax.annotation.Nullable; import net.minecraftforge.common.IPlantable; +import net.minecraftforge.common.ToolType; import net.minecraft.block.Block; import net.minecraft.block.BlockEntityProvider; @@ -149,7 +150,7 @@ default BlockEntity createTileEntity(BlockView world) { return patchwork$getForgeBlock().createTileEntity(getBlockState(), world); } - /* TODO IForgeBlockState#canHarvestBlock indirectly requires ToolType + /* TODO IForgeBlockState#canHarvestBlock indirectly requires ToolType */ /** * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed. * @@ -157,10 +158,10 @@ default BlockEntity createTileEntity(BlockView world) { * @param pos The block's current position * @param player The player damaging the block * @return True to spawn the drops - * + */ default boolean canHarvestBlock(BlockView world, BlockPos pos, PlayerEntity player) { return patchwork$getForgeBlock().canHarvestBlock(getBlockState(), world, pos, player); - }*/ + } /** * Called when a player removes a block. This is responsible for @@ -582,14 +583,14 @@ default boolean getWeakChanges(CollisionView world, BlockPos pos) { return patchwork$getForgeBlock().getWeakChanges(getBlockState(), world, pos); } - /* TODO IForgeBlockState#getHarvestTool needs ToolType + /* TODO IForgeBlockState#getHarvestTool needs ToolType */ /** * Queries the class of tool required to harvest this block, if null is returned * we assume that anything can harvest this block. - * + */ default ToolType getHarvestTool() { return patchwork$getForgeBlock().getHarvestTool(getBlockState()); - }*/ + } default int getHarvestLevel() { return patchwork$getForgeBlock().getHarvestLevel(getBlockState()); @@ -605,6 +606,7 @@ default boolean isToolEffective(ToolType tool) { }*/ /** + * TODO: do not bother implementing hooks, deprecated since 1.13 * Can return IExtendedBlockState. */ default BlockState getExtendedState(BlockView world, BlockPos pos) { @@ -612,6 +614,7 @@ default BlockState getExtendedState(BlockView world, BlockPos pos) { } /** + * TODO: do not bother implementing hooks, deprecated since 1.15 * Queries if this block should render in a given layer. * A custom {@link net.minecraft.client.render.model.BakedModel} can use {@link net.minecraftforge.client.MinecraftForgeClient#getRenderLayer()} to alter the model based on layer. */ diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java index 5f06ae28..be0317d9 100644 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java @@ -40,30 +40,30 @@ public static ThreadLocal createContext() { return ThreadLocal.withInitial(() -> BlockContext.CLEAN_MARKER); } - public static void setContext(ThreadLocal stack, Object value) { - Object oldValue = stack.get(); + public static void setContext(ThreadLocal context, Object value) { + Object oldValue = context.get(); if (oldValue != CLEAN_MARKER) { throw new IllegalStateException("The context is not clean."); } - stack.set(value); + context.set(value); } @SuppressWarnings("unchecked") - public static T getContext(ThreadLocal stack) { - Object oldValue = stack.get(); + public static T getContext(ThreadLocal context) { + Object oldValue = context.get(); if (oldValue == CLEAN_MARKER) { throw new IllegalStateException("The context is not set."); } - return (T) stack.get(); + return (T) context.get(); } @SuppressWarnings("unchecked") - public static T getContextOr(ThreadLocal stack, T defaultValue) { - Object value = stack.get(); + public static T getContextOr(ThreadLocal context, T defaultValue) { + Object value = context.get(); if (value == CLEAN_MARKER) { return defaultValue; @@ -73,14 +73,14 @@ public static T getContextOr(ThreadLocal stack, T defaultValue) { } @SuppressWarnings("unchecked") - public static T releaseContext(ThreadLocal stack) { - Object oldValue = stack.get(); + public static T releaseContext(ThreadLocal context) { + Object oldValue = context.get(); if (oldValue == CLEAN_MARKER) { throw new IllegalStateException("The context is not set."); } - stack.set(CLEAN_MARKER); + context.remove(); return (T) oldValue; } diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java new file mode 100644 index 00000000..da60ddf3 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java @@ -0,0 +1,101 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.extensions.block; + +import java.util.Stack; + +import javax.annotation.Nonnull; + +import net.minecraftforge.common.ToolType; +import net.minecraftforge.common.extensions.IForgeBlockState; +import net.minecraftforge.common.extensions.IForgeItem; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.OreBlock; +import net.minecraft.block.RedstoneOreBlock; +import net.minecraft.block.SpawnerBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; + +public class BlockHarvestManager { + private static final ThreadLocal> expDrops = ThreadLocal.withInitial(Stack::new); + + private static void checkExpDropStack() { + if (expDrops.get().isEmpty()) { + throw new IllegalStateException("Patchwork's experience drop stack is not balanced!"); + } + } + + public static void pushExpDropStack(int exp) { + expDrops.get().push(exp); + } + + public static int getLastExpDrop() { + checkExpDropStack(); + return expDrops.get().lastElement(); + } + + public static int popExpDropStack() { + checkExpDropStack(); + return expDrops.get().pop(); + } + + /** + * Called by Mixins and ForgeHooks.canHarvestBlock, + * Requires harvest levels. + */ + @SuppressWarnings("unused") + public static boolean canHarvestBlock(@Nonnull BlockState state, @Nonnull PlayerEntity player, @Nonnull BlockView world, @Nonnull BlockPos pos) { + // state = state.getActualState(world, pos); + if (state.getMaterial().canBreakByHand()) { + return true; + } + + ItemStack stack = player.getMainHandStack(); + ToolType tool = null; // TODO: Unimplemented: ((IForgeBlockState) state).getHarvestTool(); + + if (stack.isEmpty() || tool == null) { + return player.isUsingEffectiveTool(state); + } + + int toolLevel = ((IForgeItem) stack.getItem()).getHarvestLevel(stack, tool, player, state); + + if (toolLevel < 0) { + return player.isUsingEffectiveTool(state); + } + + return toolLevel >= ((IForgeBlockState) state).getHarvestLevel(); + } + + public static boolean isVanillaBlock(Block block) { + if (block instanceof OreBlock || block instanceof RedstoneOreBlock) { + return true; + } + + if (block instanceof SpawnerBlock) { + return true; + } + + return false; + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java new file mode 100644 index 00000000..68bd014e --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java @@ -0,0 +1,26 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.extensions.block; + +import java.util.Random; + +public interface PatchworkBlock { + Random getRandom(); +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java index a93ee87d..7db399eb 100644 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java @@ -21,12 +21,14 @@ import java.util.HashSet; import java.util.Map; +import java.util.Random; import java.util.Set; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import net.minecraftforge.common.ToolType; import net.minecraftforge.common.extensions.IForgeBlock; import net.minecraft.block.Block; @@ -40,6 +42,8 @@ @Mixin(Block.class) public class MixinBlock implements IForgeBlock { + protected Random RANDOM = new Random(); + @Shadow @Final private float slipperiness; @@ -54,6 +58,11 @@ public float getSlipperiness(BlockState state, CollisionView world, BlockPos pos return slipperiness; } + @Override + public ToolType getHarvestTool(BlockState state) { + throw new UnsupportedOperationException("Harvest levels not yet implemented"); // TODO implement getHarvestLevel + } + @Override public int getHarvestLevel(BlockState state) { throw new UnsupportedOperationException("Harvest levels not yet implemented"); // TODO implement getHarvestLevel, really sucks for vanilla blocks so i'm putting it off @@ -75,4 +84,9 @@ public Set getTags() { return this.cachedTags; } + + @Override + public Random getRandom() { + return RANDOM; + } } diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java new file mode 100644 index 00000000..5399b00a --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java @@ -0,0 +1,49 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.flammable; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import net.minecraftforge.common.extensions.IForgeBlockState; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.patchworkmc.impl.extensions.block.Signatures; + +@Mixin(World.class) +public abstract class MixinWorld { + //////////////////////////////////////////////////////// + /// doesAreaContainFireSource - IForgeBlock.isBurning + /// In 1.16.1, this patch is moved to Entity. + //////////////////////////////////////////////////////// + // This really should be included in the Fabric API! + // Block block = this.getBlockState(pooledMutable.set(o, p, q)).getBlock(); + // if (block == Blocks.FIRE || block == Blocks.LAVA) { + @Redirect(method = "doesAreaContainFireSource", at = @At(value = "INVOKE", target = Signatures.World_getBlockState, ordinal = 0)) + private BlockState patchwork_doesAreaContainFireSource_getBlockState(World world, BlockPos blockPos) { + BlockState blockState = world.getBlockState(blockPos); + boolean isBurning = ((IForgeBlockState) blockState).isBurning(world, blockPos); + return isBurning ? Blocks.FIRE.getDefaultState() : Blocks.WATER.getDefaultState(); + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinClientPlayerInteractionManager.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinClientPlayerInteractionManager.java new file mode 100644 index 00000000..612f9069 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinClientPlayerInteractionManager.java @@ -0,0 +1,56 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +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.Redirect; +import net.minecraftforge.common.extensions.IForgeBlockState; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.fluid.FluidState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.patchworkmc.impl.extensions.block.Signatures; + +@Mixin(ClientPlayerInteractionManager.class) +public abstract class MixinClientPlayerInteractionManager { + @Shadow + @Final + private MinecraftClient client; + + @Redirect(method = "breakBlock", at = @At(value = "INVOKE", target = Signatures.Block_onBreak, ordinal = 0)) + private void patchwork$breakBlock_onBreak(Block block, World world, BlockPos pos, BlockState state, PlayerEntity player) { + // Suppress this call: block.onBreak(world, pos, blockState, this.client.player); + } + + @Redirect(method = "breakBlock", at = @At(value = "INVOKE", target = Signatures.World_setBlockState, ordinal = 0)) + private boolean patchwork_breakBlock_setBlockState(World world, BlockPos pos, BlockState state, int flags) { + FluidState ifluidstate = world.getFluidState(pos); + return ((IForgeBlockState) state).removedByPlayer(world, pos, client.player, false, ifluidstate); + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java new file mode 100644 index 00000000..92640771 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java @@ -0,0 +1,42 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +import java.util.Random; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import net.minecraftforge.common.extensions.IForgeBlock; + +import net.minecraft.block.BlockState; +import net.minecraft.block.OreBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.CollisionView; + +@Mixin(OreBlock.class) +public abstract class MixinOreBlock implements IForgeBlock { + @Shadow + protected abstract int getExperienceWhenMined(Random random); + + @Override + public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { + return silktouch == 0 ? getExperienceWhenMined(getRandom()) : 0; + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java new file mode 100644 index 00000000..fcaaab76 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java @@ -0,0 +1,36 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +import org.spongepowered.asm.mixin.Mixin; +import net.minecraftforge.common.extensions.IForgeBlock; + +import net.minecraft.block.BlockState; +import net.minecraft.block.RedstoneOreBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.CollisionView; + +@Mixin(RedstoneOreBlock.class) +public abstract class MixinRedstoneOreBlock implements IForgeBlock { + @Override + public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { + return silktouch == 0 ? 1 + getRandom().nextInt(5) : 0; + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java new file mode 100644 index 00000000..cb929eaa --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java @@ -0,0 +1,119 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +import javax.annotation.Nullable; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import net.minecraftforge.common.extensions.IForgeBlockState; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.network.ServerPlayerInteractionManager; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; + +import net.patchworkmc.impl.extensions.block.BlockContext; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; +import net.patchworkmc.impl.extensions.block.Signatures; + +@Mixin(ServerPlayerInteractionManager.class) +public abstract class MixinServerPlayerInteractionManager { + // removedByPlayer, canHarvestBlock + + @Unique + private boolean patchwork$removeBlock(BlockPos pos, boolean canHarvest) { + ServerPlayerInteractionManager me = (ServerPlayerInteractionManager) (Object) this; + BlockState state = me.world.getBlockState(pos); + boolean removed = ((IForgeBlockState) state).removedByPlayer(me.world, pos, me.player, canHarvest, me.world.getFluidState(pos)); + + if (removed) { + state.getBlock().onBroken(me.world, pos, state); + } + + return removed; + } + + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_onBreak, ordinal = 0)) + private void patchwork$tryBreakBlock_onBreak(Block block, World world, BlockPos pos, BlockState state, PlayerEntity player) { + // Suppress this call + } + + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.ServerWorld_removeBlock, ordinal = 0)) + private boolean patchwork$tryBreakBlock_removeBlock(ServerWorld world, BlockPos pos, boolean bool) { + return true; // bypass if (bl && bl2) { + } + + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_onBroken, ordinal = 0)) + private void patchwork$tryBreakBlock_onBroken(Block block, IWorld world, BlockPos pos, BlockState state) { + // Suppress this call + } + + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.ServerPlayerInteractionManager_isCreative, ordinal = 0)) + private boolean patchwork$tryBreakBlock_isCreative(ServerPlayerInteractionManager me, BlockPos pos) { + boolean isCreative = me.isCreative(); + + if (isCreative) { + patchwork$removeBlock(pos, false); + } + + return isCreative; + } + + @Unique + private static final ThreadLocal tryBreakBlock_canHarvest = BlockContext.createContext(); // flag1 + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.ServerPlayerEntity_isUsingEffectiveTool, ordinal = 0)) + private boolean patchwork$tryBreakBlock_isUsingEffectiveTool(ServerPlayerEntity player, BlockState blockState, BlockPos pos) { + ServerPlayerInteractionManager me = (ServerPlayerInteractionManager) (Object) this; + boolean canHarvest = ((IForgeBlockState) blockState).canHarvestBlock(me.world, pos, player); + BlockContext.setContext(tryBreakBlock_canHarvest, canHarvest); + return true; // bypass if (bl && bl2) { + } + + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_afterBreak, ordinal = 0)) + private void patchwork$tryBreakBlock_afterBreak(Block block, World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) { + boolean canHarvest = BlockContext.releaseContext(tryBreakBlock_canHarvest); + boolean removed = patchwork$removeBlock(pos, canHarvest); + + if (removed && canHarvest) { + block.afterBreak(world, player, pos, state, blockEntity, stack); + } + + int exp = BlockHarvestManager.getLastExpDrop(); + + // isVanillaBlock exp Action + // Vanilla true xxx Let the vanilla method do the orb drop + // Fabric mod false == 0 Let the vanilla method do the orb drop + // Forge mod false >0 Do orb drop here + // Forge mod false <=0 Do nothing + if (removed && exp > 0 && !BlockHarvestManager.isVanillaBlock(block)) { + state.getBlock().dropExperience(world, pos, exp); + } + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java new file mode 100644 index 00000000..40100d06 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java @@ -0,0 +1,36 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +import org.spongepowered.asm.mixin.Mixin; +import net.minecraftforge.common.extensions.IForgeBlock; + +import net.minecraft.block.BlockState; +import net.minecraft.block.SpawnerBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.CollisionView; + +@Mixin(SpawnerBlock.class) +public abstract class MixinSpawnerBlock implements IForgeBlock { + @Override + public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { + return 15 + getRandom().nextInt(15) + getRandom().nextInt(15); + } +} diff --git a/patchwork-extensions-block/src/main/resources/fabric.mod.json b/patchwork-extensions-block/src/main/resources/fabric.mod.json index 7ccd29e1..f1f22b18 100644 --- a/patchwork-extensions-block/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-block/src/main/resources/fabric.mod.json @@ -13,11 +13,14 @@ "depends": { "patchwork-api-base": "*", "patchwork-enum-hacks": "*", + "patchwork-extensions-item": "*", "patchwork-tooltype": "*" }, "mixins": [ "patchwork-extensions-block.mixins.json", - "patchwork-extensions-block-blockentity.mixins.json" + "patchwork-extensions-block-blockentity.mixins.json", + "patchwork-extensions-block-flammable.mixins.json", + "patchwork-extensions-block-harvest.mixins.json" ], "accessWidener": "patchwork-extensions-block.accesswidener", "custom": { diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json new file mode 100644 index 00000000..973ae16c --- /dev/null +++ b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.extensions.block.flammable", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinWorld" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json new file mode 100644 index 00000000..2650febb --- /dev/null +++ b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json @@ -0,0 +1,17 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.extensions.block.harvest", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinOreBlock", + "MixinRedstoneOreBlock", + "MixinServerPlayerInteractionManager", + "MixinSpawnerBlock" + ], + "client": [ + "MixinClientPlayerInteractionManager" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener index 2188fab7..4b314a92 100644 --- a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener +++ b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener @@ -9,3 +9,5 @@ accessible field net/minecraft/item/AxeItem STRIPPED_BLOCKS Ljava/util/Map; # accessible method net/minecraft/block/PressurePlateBlock (Lnet/minecraft/block/PressurePlateBlock$ActivationRule;Lnet/minecraft/Block$Settings;)V accessible method net/minecraft/class_2440 (Lnet/minecraft/class_2440$class_2441;Lnet/minecraft/class_2248$class_2251;)V + +accessible method net/minecraft/block/Block dropExperience (Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;I)V From 3389d85eb3d196417aa453884d76203c8ad74517 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Fri, 7 Aug 2020 18:52:12 -0500 Subject: [PATCH 41/73] Revert "Impl removedByPlayer and canHarvestBlock in IForgeBlock (#126)" This reverts commit 7d7f2b12 --- patchwork-events-world/build.gradle | 1 - .../event/world/BlockEvent.java | 18 ++- .../impl/event/world/WorldEvents.java | 59 --------- .../MixinServerPlayerInteractionManager.java | 66 ++++++++-- .../src/main/resources/fabric.mod.json | 3 +- patchwork-extensions-block/build.gradle | 1 - .../common/extensions/IForgeBlock.java | 28 ++--- .../common/extensions/IForgeBlockState.java | 15 +-- .../impl/extensions/block/BlockContext.java | 22 ++-- .../extensions/block/BlockHarvestManager.java | 101 --------------- .../impl/extensions/block/PatchworkBlock.java | 26 ---- .../mixin/extensions/block/MixinBlock.java | 14 --- .../block/flammable/MixinWorld.java | 49 -------- .../MixinClientPlayerInteractionManager.java | 56 --------- .../block/harvest/MixinOreBlock.java | 42 ------- .../block/harvest/MixinRedstoneOreBlock.java | 36 ------ .../MixinServerPlayerInteractionManager.java | 119 ------------------ .../block/harvest/MixinSpawnerBlock.java | 36 ------ .../src/main/resources/fabric.mod.json | 5 +- ...ork-extensions-block-flammable.mixins.json | 11 -- ...hwork-extensions-block-harvest.mixins.json | 17 --- .../patchwork-extensions-block.accesswidener | 2 - 22 files changed, 92 insertions(+), 635 deletions(-) delete mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java delete mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java delete mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java delete mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinClientPlayerInteractionManager.java delete mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java delete mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java delete mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java delete mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java delete mode 100644 patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json delete mode 100644 patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json diff --git a/patchwork-events-world/build.gradle b/patchwork-events-world/build.gradle index 913a6bf0..b8809b37 100644 --- a/patchwork-events-world/build.gradle +++ b/patchwork-events-world/build.gradle @@ -3,5 +3,4 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') - implementation project(path: ':patchwork-extensions-block', configuration: 'dev') } diff --git a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java index 07123fb3..57308dd5 100644 --- a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java +++ b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java @@ -21,21 +21,16 @@ import java.util.List; -import net.minecraftforge.common.extensions.IForgeBlockState; import net.minecraftforge.eventbus.api.Event; import net.minecraft.item.ItemStack; import net.minecraft.util.DefaultedList; import net.minecraft.block.BlockState; -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; import net.minecraft.world.World; -import net.patchworkmc.impl.extensions.block.BlockHarvestManager; - public class BlockEvent extends Event { private final IWorld world; private final BlockPos pos; @@ -78,14 +73,17 @@ public BreakEvent(World world, BlockPos pos, BlockState state, PlayerEntity play this.player = player; this.exp = 0; + // TODO: BlockState#getExpDrop + + /* // Handle empty block or player unable to break block scenario - if (state == null || !BlockHarvestManager.canHarvestBlock(state, player, world, pos)) { + if (state == null || !ForgeHooks.canHarvestBlock(state, player, world, pos)) { this.exp = 0; } else { - int bonusLevel = EnchantmentHelper.getLevel(Enchantments.FORTUNE, player.getMainHandStack()); - int silklevel = EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, player.getMainHandStack()); - this.exp = ((IForgeBlockState) state).getExpDrop(world, pos, bonusLevel, silklevel); - } + int bonusLevel = EnchantmentHelper.getLevel(Enchantments.FORTUNE, player.getHeldItemMainhand()); + int silklevel = EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, player.getHeldItemMainhand()); + this.exp = state.getExpDrop(world, pos, bonusLevel, silklevel); + }*/ } public PlayerEntity getPlayer() { diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index cae0e965..4b33e3a3 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -28,19 +28,14 @@ import net.minecraftforge.event.world.WorldEvent; import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.DefaultedList; import net.minecraft.world.World; import net.minecraft.entity.EntityCategory; -import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.EmptyBlockView; -import net.minecraft.world.GameMode; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; @@ -77,60 +72,6 @@ public static void onWorldSave(IWorld world) { MinecraftForge.EVENT_BUS.post(new WorldEvent.Save(world)); } - /** - * Called by Mixin and ForgeHooks. - * @return experience dropped, -1 = block breaking is cancelled. - */ - public static int onBlockBreakEvent(World world, GameMode gameMode, ServerPlayerEntity player, BlockPos pos) { - // Logic from tryHarvestBlock for pre-canceling the event - boolean preCancelEvent = false; - - ItemStack itemstack = player.getMainHandStack(); - - if (!itemstack.isEmpty() && !itemstack.getItem().canMine(world.getBlockState(pos), world, pos, player)) { - preCancelEvent = true; - } - - // method_21701 => canMine - // Isn't the function really canNotMine? - - if (player.method_21701(world, pos, gameMode)) { - preCancelEvent = true; - } - - // Tell client the block is gone immediately then process events - if (world.getBlockEntity(pos) == null) { - player.networkHandler.sendPacket(new BlockUpdateS2CPacket(EmptyBlockView.INSTANCE, pos)); - } - - // Post the block break event - BlockState state = world.getBlockState(pos); - BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player); - event.setCanceled(preCancelEvent); - MinecraftForge.EVENT_BUS.post(event); - - // Handle if the event is canceled - if (event.isCanceled()) { - // Let the client know the block still exists - player.networkHandler.sendPacket(new BlockUpdateS2CPacket(world, pos)); - - // Update any block entity data for this block - BlockEntity entity = world.getBlockEntity(pos); - - if (entity != null) { - BlockEntityUpdateS2CPacket packet = entity.toUpdatePacket(); - - if (packet != null) { - player.networkHandler.sendPacket(packet); - } - } - - return -1; // Cancelled - } else { - return event.getExpToDrop(); - } - } - // TODO: Leaving this unfired is intentional. See: https://github.com/MinecraftForge/MinecraftForge/issues/5828 public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(world, pos, state, fortune, dropChance, drops, player, silkTouch); diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java index 713a88b2..7b62fa81 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java @@ -19,23 +19,28 @@ package net.patchworkmc.mixin.event.world; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.BlockEvent; 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.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerInteractionManager; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.EmptyBlockView; import net.minecraft.world.GameMode; -import net.patchworkmc.impl.event.world.WorldEvents; -import net.patchworkmc.impl.extensions.block.BlockHarvestManager; - @Mixin(ServerPlayerInteractionManager.class) -public abstract class MixinServerPlayerInteractionManager { +public class MixinServerPlayerInteractionManager { @Shadow public ServerWorld world; @Shadow @@ -45,17 +50,52 @@ public abstract class MixinServerPlayerInteractionManager { @Inject(method = "tryBreakBlock", at = @At("HEAD"), cancellable = true) private void hookBreakBlock(BlockPos pos, CallbackInfoReturnable callback) { - int exp = WorldEvents.onBlockBreakEvent(world, gameMode, player, pos); + boolean preCancelEvent = false; - if (exp < 0) { - callback.setReturnValue(false); - } else { - BlockHarvestManager.pushExpDropStack(exp); + ItemStack itemstack = player.getMainHandStack(); + + if (!itemstack.isEmpty() && !itemstack.getItem().canMine(world.getBlockState(pos), world, pos, player)) { + preCancelEvent = true; } - } - @Inject(method = "tryBreakBlock", at = @At("RETURN"), cancellable = true) - private void tryBreakBlock_return(BlockPos pos, CallbackInfoReturnable callback) { - BlockHarvestManager.popExpDropStack(); + // method_21701 => canMine + // Isn't the function really canNotMine? + + if (player.method_21701(world, pos, gameMode)) { + preCancelEvent = true; + } + + // Tell client the block is gone immediately then process events + if (world.getBlockEntity(pos) == null) { + player.networkHandler.sendPacket(new BlockUpdateS2CPacket(EmptyBlockView.INSTANCE, pos)); + } + + // Post the block break event + BlockState state = world.getBlockState(pos); + BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player); + event.setCanceled(preCancelEvent); + MinecraftForge.EVENT_BUS.post(event); + + // Handle if the event is canceled + if (event.isCanceled()) { + // Let the client know the block still exists + player.networkHandler.sendPacket(new BlockUpdateS2CPacket(world, pos)); + + // Update any block entity data for this block + BlockEntity entity = world.getBlockEntity(pos); + + if (entity != null) { + BlockEntityUpdateS2CPacket packet = entity.toUpdatePacket(); + + if (packet != null) { + player.networkHandler.sendPacket(packet); + } + } + + callback.setReturnValue(false); + } else if (event.getExpToDrop() != 0) { + // TODO: Drop experience + throw new UnsupportedOperationException("Cannot drop exp from a BreakEvent yet"); + } } } diff --git a/patchwork-events-world/src/main/resources/fabric.mod.json b/patchwork-events-world/src/main/resources/fabric.mod.json index f74ea781..509b8176 100644 --- a/patchwork-events-world/src/main/resources/fabric.mod.json +++ b/patchwork-events-world/src/main/resources/fabric.mod.json @@ -13,8 +13,7 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*", - "patchwork-extensions-block": "*" + "patchwork-api-base": "*" }, "mixins": [ "patchwork-events-world.mixins.json" diff --git a/patchwork-extensions-block/build.gradle b/patchwork-extensions-block/build.gradle index 94c92392..6bdfc305 100644 --- a/patchwork-extensions-block/build.gradle +++ b/patchwork-extensions-block/build.gradle @@ -4,7 +4,6 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') implementation project(path: ':patchwork-enum-hacks', configuration: 'dev') - implementation project(path: ':patchwork-extensions-item', configuration: 'dev') implementation project(path: ':patchwork-tooltype', configuration: 'dev') } diff --git a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java index 2a860bff..4c540345 100644 --- a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java +++ b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java @@ -27,7 +27,6 @@ import javax.annotation.Nullable; import net.minecraftforge.common.IPlantable; -import net.minecraftforge.common.ToolType; import net.minecraft.block.BedBlock; import net.minecraft.block.Block; @@ -83,12 +82,10 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.patchworkmc.impl.extensions.block.BlockHarvestManager; -import net.patchworkmc.impl.extensions.block.PatchworkBlock; import net.patchworkmc.mixin.extensions.block.FireBlockAccessor; import net.patchworkmc.mixin.extensions.block.PlantBlockAccessor; -public interface IForgeBlock extends PatchworkBlock { +public interface IForgeBlock { default Block getBlock() { return (Block) this; } @@ -207,7 +204,7 @@ default BlockEntity createTileEntity(BlockState state, BlockView world) { return null; } - /* TODO IForgeBlock#canHarvestBlock indirectly requires ToolType (via ForgeHooks#canHarvestBlock) */ + /* TODO IForgeBlock#canHarvestBlock indirectly requires ToolType (via ForgeHooks#canHarvestBlock) /** * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed. * @@ -215,10 +212,10 @@ default BlockEntity createTileEntity(BlockState state, BlockView world) { * @param pos The block's current position * @param player The player damaging the block * @return True to spawn the drops - */ + * default boolean canHarvestBlock(BlockState state, BlockView world, BlockPos pos, PlayerEntity player) { - return BlockHarvestManager.canHarvestBlock(state, player, world, pos); - } + return ForgeHooks.canHarvestBlock(state, player, world, pos); + }*/ // TODO Call locations: Patches: ServerPlayerInteractionManager* /** @@ -243,7 +240,7 @@ default boolean canHarvestBlock(BlockState state, BlockView world, BlockPos pos, */ default boolean removedByPlayer(BlockState state, World world, BlockPos pos, PlayerEntity player, boolean willHarvest, FluidState fluid) { getBlock().onBreak(world, pos, state, player); - return world.setBlockState(pos, fluid.getBlockState(), world.isClient ? 11 : 3); + return world.removeBlock(pos, false); } // TODO Call locations: Patches: LivingEntity*, PlayerEntity*, Forge classes: ForgeEventFactory (called from LivingEntity patch) @@ -648,7 +645,6 @@ default boolean isBeaconBase(BlockState state, CollisionView world, BlockPos pos // TODO Call locations: Forge classes: BreakEvent* /** * Gathers how much experience this block drops when broken. - * TODO: there's no equivalent callback in Fabric API, so for now Fabric mods should always return 0 here. * * @param state The current state * @param world The world @@ -782,12 +778,12 @@ default boolean getWeakChanges(BlockState state, CollisionView world, BlockPos p return false; } - /* TODO IForgeBlock#getHarvestTool needs ToolType */ + /* TODO IForgeBlock#getHarvestTool needs ToolType /** * Queries the class of tool required to harvest this block, if null is returned * we assume that anything can harvest this block. - */ - ToolType getHarvestTool(BlockState state); + * + ToolType getHarvestTool(BlockState state);*/ // TODO Call locations: Patches: PickaxeItem*, Forge classes: ForgeHooks* /** @@ -797,18 +793,18 @@ default boolean getWeakChanges(BlockState state, CollisionView world, BlockPos p */ int getHarvestLevel(BlockState state); - /* TODO IForgeBlock#isToolEffective needs ToolType */ + /* TODO IForgeBlock#isToolEffective needs ToolType /** * Checks if the specified tool type is efficient on this block, * meaning that it digs at full speed. - */ + * default boolean isToolEffective(BlockState state, ToolType tool) { if (tool == ToolType.PICKAXE && (this.getBlock() == Blocks.REDSTONE_ORE || this.getBlock() == Blocks.REDSTONE_LAMP || this.getBlock() == Blocks.OBSIDIAN)) { return false; } return tool == getHarvestTool(state); - } + }*/ // TODO Call locations: Forge classes: ForgeHooksClient /** diff --git a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java index 0f0c4182..55e94ee2 100644 --- a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java +++ b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java @@ -25,7 +25,6 @@ import javax.annotation.Nullable; import net.minecraftforge.common.IPlantable; -import net.minecraftforge.common.ToolType; import net.minecraft.block.Block; import net.minecraft.block.BlockEntityProvider; @@ -150,7 +149,7 @@ default BlockEntity createTileEntity(BlockView world) { return patchwork$getForgeBlock().createTileEntity(getBlockState(), world); } - /* TODO IForgeBlockState#canHarvestBlock indirectly requires ToolType */ + /* TODO IForgeBlockState#canHarvestBlock indirectly requires ToolType /** * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed. * @@ -158,10 +157,10 @@ default BlockEntity createTileEntity(BlockView world) { * @param pos The block's current position * @param player The player damaging the block * @return True to spawn the drops - */ + * default boolean canHarvestBlock(BlockView world, BlockPos pos, PlayerEntity player) { return patchwork$getForgeBlock().canHarvestBlock(getBlockState(), world, pos, player); - } + }*/ /** * Called when a player removes a block. This is responsible for @@ -583,14 +582,14 @@ default boolean getWeakChanges(CollisionView world, BlockPos pos) { return patchwork$getForgeBlock().getWeakChanges(getBlockState(), world, pos); } - /* TODO IForgeBlockState#getHarvestTool needs ToolType */ + /* TODO IForgeBlockState#getHarvestTool needs ToolType /** * Queries the class of tool required to harvest this block, if null is returned * we assume that anything can harvest this block. - */ + * default ToolType getHarvestTool() { return patchwork$getForgeBlock().getHarvestTool(getBlockState()); - } + }*/ default int getHarvestLevel() { return patchwork$getForgeBlock().getHarvestLevel(getBlockState()); @@ -606,7 +605,6 @@ default boolean isToolEffective(ToolType tool) { }*/ /** - * TODO: do not bother implementing hooks, deprecated since 1.13 * Can return IExtendedBlockState. */ default BlockState getExtendedState(BlockView world, BlockPos pos) { @@ -614,7 +612,6 @@ default BlockState getExtendedState(BlockView world, BlockPos pos) { } /** - * TODO: do not bother implementing hooks, deprecated since 1.15 * Queries if this block should render in a given layer. * A custom {@link net.minecraft.client.render.model.BakedModel} can use {@link net.minecraftforge.client.MinecraftForgeClient#getRenderLayer()} to alter the model based on layer. */ diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java index be0317d9..5f06ae28 100644 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java @@ -40,30 +40,30 @@ public static ThreadLocal createContext() { return ThreadLocal.withInitial(() -> BlockContext.CLEAN_MARKER); } - public static void setContext(ThreadLocal context, Object value) { - Object oldValue = context.get(); + public static void setContext(ThreadLocal stack, Object value) { + Object oldValue = stack.get(); if (oldValue != CLEAN_MARKER) { throw new IllegalStateException("The context is not clean."); } - context.set(value); + stack.set(value); } @SuppressWarnings("unchecked") - public static T getContext(ThreadLocal context) { - Object oldValue = context.get(); + public static T getContext(ThreadLocal stack) { + Object oldValue = stack.get(); if (oldValue == CLEAN_MARKER) { throw new IllegalStateException("The context is not set."); } - return (T) context.get(); + return (T) stack.get(); } @SuppressWarnings("unchecked") - public static T getContextOr(ThreadLocal context, T defaultValue) { - Object value = context.get(); + public static T getContextOr(ThreadLocal stack, T defaultValue) { + Object value = stack.get(); if (value == CLEAN_MARKER) { return defaultValue; @@ -73,14 +73,14 @@ public static T getContextOr(ThreadLocal context, T defaultValue) { } @SuppressWarnings("unchecked") - public static T releaseContext(ThreadLocal context) { - Object oldValue = context.get(); + public static T releaseContext(ThreadLocal stack) { + Object oldValue = stack.get(); if (oldValue == CLEAN_MARKER) { throw new IllegalStateException("The context is not set."); } - context.remove(); + stack.set(CLEAN_MARKER); return (T) oldValue; } diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java deleted file mode 100644 index da60ddf3..00000000 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.impl.extensions.block; - -import java.util.Stack; - -import javax.annotation.Nonnull; - -import net.minecraftforge.common.ToolType; -import net.minecraftforge.common.extensions.IForgeBlockState; -import net.minecraftforge.common.extensions.IForgeItem; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.OreBlock; -import net.minecraft.block.RedstoneOreBlock; -import net.minecraft.block.SpawnerBlock; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.BlockView; - -public class BlockHarvestManager { - private static final ThreadLocal> expDrops = ThreadLocal.withInitial(Stack::new); - - private static void checkExpDropStack() { - if (expDrops.get().isEmpty()) { - throw new IllegalStateException("Patchwork's experience drop stack is not balanced!"); - } - } - - public static void pushExpDropStack(int exp) { - expDrops.get().push(exp); - } - - public static int getLastExpDrop() { - checkExpDropStack(); - return expDrops.get().lastElement(); - } - - public static int popExpDropStack() { - checkExpDropStack(); - return expDrops.get().pop(); - } - - /** - * Called by Mixins and ForgeHooks.canHarvestBlock, - * Requires harvest levels. - */ - @SuppressWarnings("unused") - public static boolean canHarvestBlock(@Nonnull BlockState state, @Nonnull PlayerEntity player, @Nonnull BlockView world, @Nonnull BlockPos pos) { - // state = state.getActualState(world, pos); - if (state.getMaterial().canBreakByHand()) { - return true; - } - - ItemStack stack = player.getMainHandStack(); - ToolType tool = null; // TODO: Unimplemented: ((IForgeBlockState) state).getHarvestTool(); - - if (stack.isEmpty() || tool == null) { - return player.isUsingEffectiveTool(state); - } - - int toolLevel = ((IForgeItem) stack.getItem()).getHarvestLevel(stack, tool, player, state); - - if (toolLevel < 0) { - return player.isUsingEffectiveTool(state); - } - - return toolLevel >= ((IForgeBlockState) state).getHarvestLevel(); - } - - public static boolean isVanillaBlock(Block block) { - if (block instanceof OreBlock || block instanceof RedstoneOreBlock) { - return true; - } - - if (block instanceof SpawnerBlock) { - return true; - } - - return false; - } -} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java deleted file mode 100644 index 68bd014e..00000000 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.impl.extensions.block; - -import java.util.Random; - -public interface PatchworkBlock { - Random getRandom(); -} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java index 7db399eb..a93ee87d 100644 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java @@ -21,14 +21,12 @@ import java.util.HashSet; import java.util.Map; -import java.util.Random; import java.util.Set; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; -import net.minecraftforge.common.ToolType; import net.minecraftforge.common.extensions.IForgeBlock; import net.minecraft.block.Block; @@ -42,8 +40,6 @@ @Mixin(Block.class) public class MixinBlock implements IForgeBlock { - protected Random RANDOM = new Random(); - @Shadow @Final private float slipperiness; @@ -58,11 +54,6 @@ public float getSlipperiness(BlockState state, CollisionView world, BlockPos pos return slipperiness; } - @Override - public ToolType getHarvestTool(BlockState state) { - throw new UnsupportedOperationException("Harvest levels not yet implemented"); // TODO implement getHarvestLevel - } - @Override public int getHarvestLevel(BlockState state) { throw new UnsupportedOperationException("Harvest levels not yet implemented"); // TODO implement getHarvestLevel, really sucks for vanilla blocks so i'm putting it off @@ -84,9 +75,4 @@ public Set getTags() { return this.cachedTags; } - - @Override - public Random getRandom() { - return RANDOM; - } } diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java deleted file mode 100644 index 5399b00a..00000000 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.extensions.block.flammable; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import net.minecraftforge.common.extensions.IForgeBlockState; - -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import net.patchworkmc.impl.extensions.block.Signatures; - -@Mixin(World.class) -public abstract class MixinWorld { - //////////////////////////////////////////////////////// - /// doesAreaContainFireSource - IForgeBlock.isBurning - /// In 1.16.1, this patch is moved to Entity. - //////////////////////////////////////////////////////// - // This really should be included in the Fabric API! - // Block block = this.getBlockState(pooledMutable.set(o, p, q)).getBlock(); - // if (block == Blocks.FIRE || block == Blocks.LAVA) { - @Redirect(method = "doesAreaContainFireSource", at = @At(value = "INVOKE", target = Signatures.World_getBlockState, ordinal = 0)) - private BlockState patchwork_doesAreaContainFireSource_getBlockState(World world, BlockPos blockPos) { - BlockState blockState = world.getBlockState(blockPos); - boolean isBurning = ((IForgeBlockState) blockState).isBurning(world, blockPos); - return isBurning ? Blocks.FIRE.getDefaultState() : Blocks.WATER.getDefaultState(); - } -} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinClientPlayerInteractionManager.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinClientPlayerInteractionManager.java deleted file mode 100644 index 612f9069..00000000 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinClientPlayerInteractionManager.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.extensions.block.harvest; - -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.Redirect; -import net.minecraftforge.common.extensions.IForgeBlockState; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.fluid.FluidState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import net.patchworkmc.impl.extensions.block.Signatures; - -@Mixin(ClientPlayerInteractionManager.class) -public abstract class MixinClientPlayerInteractionManager { - @Shadow - @Final - private MinecraftClient client; - - @Redirect(method = "breakBlock", at = @At(value = "INVOKE", target = Signatures.Block_onBreak, ordinal = 0)) - private void patchwork$breakBlock_onBreak(Block block, World world, BlockPos pos, BlockState state, PlayerEntity player) { - // Suppress this call: block.onBreak(world, pos, blockState, this.client.player); - } - - @Redirect(method = "breakBlock", at = @At(value = "INVOKE", target = Signatures.World_setBlockState, ordinal = 0)) - private boolean patchwork_breakBlock_setBlockState(World world, BlockPos pos, BlockState state, int flags) { - FluidState ifluidstate = world.getFluidState(pos); - return ((IForgeBlockState) state).removedByPlayer(world, pos, client.player, false, ifluidstate); - } -} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java deleted file mode 100644 index 92640771..00000000 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.extensions.block.harvest; - -import java.util.Random; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import net.minecraftforge.common.extensions.IForgeBlock; - -import net.minecraft.block.BlockState; -import net.minecraft.block.OreBlock; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.CollisionView; - -@Mixin(OreBlock.class) -public abstract class MixinOreBlock implements IForgeBlock { - @Shadow - protected abstract int getExperienceWhenMined(Random random); - - @Override - public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { - return silktouch == 0 ? getExperienceWhenMined(getRandom()) : 0; - } -} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java deleted file mode 100644 index fcaaab76..00000000 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.extensions.block.harvest; - -import org.spongepowered.asm.mixin.Mixin; -import net.minecraftforge.common.extensions.IForgeBlock; - -import net.minecraft.block.BlockState; -import net.minecraft.block.RedstoneOreBlock; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.CollisionView; - -@Mixin(RedstoneOreBlock.class) -public abstract class MixinRedstoneOreBlock implements IForgeBlock { - @Override - public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { - return silktouch == 0 ? 1 + getRandom().nextInt(5) : 0; - } -} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java deleted file mode 100644 index cb929eaa..00000000 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.extensions.block.harvest; - -import javax.annotation.Nullable; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import net.minecraftforge.common.extensions.IForgeBlockState; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.network.ServerPlayerInteractionManager; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorld; -import net.minecraft.world.World; - -import net.patchworkmc.impl.extensions.block.BlockContext; -import net.patchworkmc.impl.extensions.block.BlockHarvestManager; -import net.patchworkmc.impl.extensions.block.Signatures; - -@Mixin(ServerPlayerInteractionManager.class) -public abstract class MixinServerPlayerInteractionManager { - // removedByPlayer, canHarvestBlock - - @Unique - private boolean patchwork$removeBlock(BlockPos pos, boolean canHarvest) { - ServerPlayerInteractionManager me = (ServerPlayerInteractionManager) (Object) this; - BlockState state = me.world.getBlockState(pos); - boolean removed = ((IForgeBlockState) state).removedByPlayer(me.world, pos, me.player, canHarvest, me.world.getFluidState(pos)); - - if (removed) { - state.getBlock().onBroken(me.world, pos, state); - } - - return removed; - } - - @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_onBreak, ordinal = 0)) - private void patchwork$tryBreakBlock_onBreak(Block block, World world, BlockPos pos, BlockState state, PlayerEntity player) { - // Suppress this call - } - - @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.ServerWorld_removeBlock, ordinal = 0)) - private boolean patchwork$tryBreakBlock_removeBlock(ServerWorld world, BlockPos pos, boolean bool) { - return true; // bypass if (bl && bl2) { - } - - @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_onBroken, ordinal = 0)) - private void patchwork$tryBreakBlock_onBroken(Block block, IWorld world, BlockPos pos, BlockState state) { - // Suppress this call - } - - @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.ServerPlayerInteractionManager_isCreative, ordinal = 0)) - private boolean patchwork$tryBreakBlock_isCreative(ServerPlayerInteractionManager me, BlockPos pos) { - boolean isCreative = me.isCreative(); - - if (isCreative) { - patchwork$removeBlock(pos, false); - } - - return isCreative; - } - - @Unique - private static final ThreadLocal tryBreakBlock_canHarvest = BlockContext.createContext(); // flag1 - @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.ServerPlayerEntity_isUsingEffectiveTool, ordinal = 0)) - private boolean patchwork$tryBreakBlock_isUsingEffectiveTool(ServerPlayerEntity player, BlockState blockState, BlockPos pos) { - ServerPlayerInteractionManager me = (ServerPlayerInteractionManager) (Object) this; - boolean canHarvest = ((IForgeBlockState) blockState).canHarvestBlock(me.world, pos, player); - BlockContext.setContext(tryBreakBlock_canHarvest, canHarvest); - return true; // bypass if (bl && bl2) { - } - - @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_afterBreak, ordinal = 0)) - private void patchwork$tryBreakBlock_afterBreak(Block block, World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) { - boolean canHarvest = BlockContext.releaseContext(tryBreakBlock_canHarvest); - boolean removed = patchwork$removeBlock(pos, canHarvest); - - if (removed && canHarvest) { - block.afterBreak(world, player, pos, state, blockEntity, stack); - } - - int exp = BlockHarvestManager.getLastExpDrop(); - - // isVanillaBlock exp Action - // Vanilla true xxx Let the vanilla method do the orb drop - // Fabric mod false == 0 Let the vanilla method do the orb drop - // Forge mod false >0 Do orb drop here - // Forge mod false <=0 Do nothing - if (removed && exp > 0 && !BlockHarvestManager.isVanillaBlock(block)) { - state.getBlock().dropExperience(world, pos, exp); - } - } -} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java deleted file mode 100644 index 40100d06..00000000 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.extensions.block.harvest; - -import org.spongepowered.asm.mixin.Mixin; -import net.minecraftforge.common.extensions.IForgeBlock; - -import net.minecraft.block.BlockState; -import net.minecraft.block.SpawnerBlock; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.CollisionView; - -@Mixin(SpawnerBlock.class) -public abstract class MixinSpawnerBlock implements IForgeBlock { - @Override - public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { - return 15 + getRandom().nextInt(15) + getRandom().nextInt(15); - } -} diff --git a/patchwork-extensions-block/src/main/resources/fabric.mod.json b/patchwork-extensions-block/src/main/resources/fabric.mod.json index f1f22b18..7ccd29e1 100644 --- a/patchwork-extensions-block/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-block/src/main/resources/fabric.mod.json @@ -13,14 +13,11 @@ "depends": { "patchwork-api-base": "*", "patchwork-enum-hacks": "*", - "patchwork-extensions-item": "*", "patchwork-tooltype": "*" }, "mixins": [ "patchwork-extensions-block.mixins.json", - "patchwork-extensions-block-blockentity.mixins.json", - "patchwork-extensions-block-flammable.mixins.json", - "patchwork-extensions-block-harvest.mixins.json" + "patchwork-extensions-block-blockentity.mixins.json" ], "accessWidener": "patchwork-extensions-block.accesswidener", "custom": { diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json deleted file mode 100644 index 973ae16c..00000000 --- a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "required": true, - "package": "net.patchworkmc.mixin.extensions.block.flammable", - "compatibilityLevel": "JAVA_8", - "mixins": [ - "MixinWorld" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json deleted file mode 100644 index 2650febb..00000000 --- a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "required": true, - "package": "net.patchworkmc.mixin.extensions.block.harvest", - "compatibilityLevel": "JAVA_8", - "mixins": [ - "MixinOreBlock", - "MixinRedstoneOreBlock", - "MixinServerPlayerInteractionManager", - "MixinSpawnerBlock" - ], - "client": [ - "MixinClientPlayerInteractionManager" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener index 4b314a92..2188fab7 100644 --- a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener +++ b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener @@ -9,5 +9,3 @@ accessible field net/minecraft/item/AxeItem STRIPPED_BLOCKS Ljava/util/Map; # accessible method net/minecraft/block/PressurePlateBlock (Lnet/minecraft/block/PressurePlateBlock$ActivationRule;Lnet/minecraft/Block$Settings;)V accessible method net/minecraft/class_2440 (Lnet/minecraft/class_2440$class_2441;Lnet/minecraft/class_2248$class_2251;)V - -accessible method net/minecraft/block/Block dropExperience (Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;I)V From 5c633e67e3871c47c0f92061bdf794c59d8c6b52 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Sat, 8 Aug 2020 21:38:14 -0500 Subject: [PATCH 42/73] Hotfix: Accessors must be interfaces --- .../patchworkmc/mixin/extensions/item/ItemTagsAccessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/ItemTagsAccessor.java b/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/ItemTagsAccessor.java index 6f42875e..f7fe918f 100644 --- a/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/ItemTagsAccessor.java +++ b/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/ItemTagsAccessor.java @@ -25,9 +25,9 @@ import net.minecraft.tag.ItemTags; @Mixin(ItemTags.class) -public class ItemTagsAccessor { +public interface ItemTagsAccessor { @Accessor - public static int getLatestVersion() { + static int getLatestVersion() { throw new UnsupportedOperationException(); } } From c92e7480c619290de093f867f635d1c8f369d2a5 Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Tue, 11 Aug 2020 12:23:31 -0400 Subject: [PATCH 43/73] Make CapabilityRegisteredCallback store class names not class objects (#175) --- .../api/capability/CapabilityRegisteredCallback.java | 6 +++++- .../capability/CapabilityRegisteredCallbackInternal.java | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/patchwork-capabilities/src/main/java/net/patchworkmc/api/capability/CapabilityRegisteredCallback.java b/patchwork-capabilities/src/main/java/net/patchworkmc/api/capability/CapabilityRegisteredCallback.java index 0186551d..c9e9f095 100644 --- a/patchwork-capabilities/src/main/java/net/patchworkmc/api/capability/CapabilityRegisteredCallback.java +++ b/patchwork-capabilities/src/main/java/net/patchworkmc/api/capability/CapabilityRegisteredCallback.java @@ -29,6 +29,10 @@ public interface CapabilityRegisteredCallback { void onCapabilityRegistered(Capability capability); static Event> event(Class type) { - return CapabilityRegisteredCallbackInternal.getOrCreateEvent(type); + return CapabilityRegisteredCallbackInternal.getOrCreateEvent(type.getName()); + } + + static Event> event(String className) { + return CapabilityRegisteredCallbackInternal.getOrCreateEvent(className); } } diff --git a/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/CapabilityRegisteredCallbackInternal.java b/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/CapabilityRegisteredCallbackInternal.java index f8b56981..604093aa 100644 --- a/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/CapabilityRegisteredCallbackInternal.java +++ b/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/CapabilityRegisteredCallbackInternal.java @@ -19,7 +19,7 @@ package net.patchworkmc.impl.capability; -import java.util.IdentityHashMap; +import java.util.HashMap; import java.util.Map; import org.apache.logging.log4j.LogManager; @@ -33,10 +33,10 @@ public class CapabilityRegisteredCallbackInternal { private static final Logger LOGGER = LogManager.getLogger(CapabilityRegisteredCallback.class); - private static final Map, Event> CALLBACKS = new IdentityHashMap<>(); + private static final Map> CALLBACKS = new HashMap<>(); @SuppressWarnings("unchecked") - public static Event> getOrCreateEvent(Class type) { + public static Event> getOrCreateEvent(String type) { return (Event>) CALLBACKS.computeIfAbsent(type, $ -> EventFactory.createArrayBacked(CapabilityRegisteredCallback.class, capability -> { }, callbacks -> capability -> { boolean error = false; Throwable throwable = new Throwable(); @@ -51,7 +51,7 @@ public static Event> getOrCreateEvent(Class< } if (error) { - LOGGER.error("An uncaught exception was thrown while processing a CapabilityRegisteredCallback<{}>", type.getName(), throwable); + LOGGER.error("An uncaught exception was thrown while processing a CapabilityRegisteredCallback<{}>", type, throwable); } })); } From 4789f0ad4bd94e9e6592300c52c22e0edbdbd78e Mon Sep 17 00:00:00 2001 From: famous1622 <8428080+famous1622@users.noreply.github.com> Date: Tue, 11 Aug 2020 12:37:30 -0400 Subject: [PATCH 44/73] IItemHandler support (#142) * IItemHandler support * Remove a sneaky debug print * Apparently this can cause a memory leak, TIL * Update patchwork-items/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java Co-authored-by: Glitch --- patchwork-items/build.gradle | 6 + .../items/CapabilityItemHandler.java | 79 +++++++ .../minecraftforge/items/IItemHandler.java | 112 +++++++++ .../items/IItemHandlerModifiable.java | 39 ++++ .../items/ItemHandlerHelper.java | 219 ++++++++++++++++++ .../items/ItemStackHandler.java | 210 +++++++++++++++++ .../items/ItemHandlerInventoryWrapper.java | 92 ++++++++ .../impl/items/PatchworkItems.java | 38 +++ .../mixin/items/MixinDropperBlock.java | 39 ++++ .../mixin/items/MixinHopperBlockEntity.java | 93 ++++++++ .../resources/assets/patchwork-items/icon.png | Bin 0 -> 22738 bytes .../src/main/resources/fabric.mod.json | 27 +++ .../resources/patchwork-items.mixins.json | 12 + settings.gradle | 1 + 14 files changed, 967 insertions(+) create mode 100644 patchwork-items/build.gradle create mode 100644 patchwork-items/src/main/java/net/minecraftforge/items/CapabilityItemHandler.java create mode 100644 patchwork-items/src/main/java/net/minecraftforge/items/IItemHandler.java create mode 100644 patchwork-items/src/main/java/net/minecraftforge/items/IItemHandlerModifiable.java create mode 100644 patchwork-items/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java create mode 100644 patchwork-items/src/main/java/net/minecraftforge/items/ItemStackHandler.java create mode 100644 patchwork-items/src/main/java/net/patchworkmc/impl/items/ItemHandlerInventoryWrapper.java create mode 100644 patchwork-items/src/main/java/net/patchworkmc/impl/items/PatchworkItems.java create mode 100644 patchwork-items/src/main/java/net/patchworkmc/mixin/items/MixinDropperBlock.java create mode 100644 patchwork-items/src/main/java/net/patchworkmc/mixin/items/MixinHopperBlockEntity.java create mode 100644 patchwork-items/src/main/resources/assets/patchwork-items/icon.png create mode 100644 patchwork-items/src/main/resources/fabric.mod.json create mode 100644 patchwork-items/src/main/resources/patchwork-items.mixins.json diff --git a/patchwork-items/build.gradle b/patchwork-items/build.gradle new file mode 100644 index 00000000..b5f9e26a --- /dev/null +++ b/patchwork-items/build.gradle @@ -0,0 +1,6 @@ +archivesBaseName = "patchwork-items" +version = getSubprojectVersion(project, "0.1.0") + +dependencies { + compile project(path: ':patchwork-capabilities', configuration: 'dev') +} diff --git a/patchwork-items/src/main/java/net/minecraftforge/items/CapabilityItemHandler.java b/patchwork-items/src/main/java/net/minecraftforge/items/CapabilityItemHandler.java new file mode 100644 index 00000000..4d00ee3e --- /dev/null +++ b/patchwork-items/src/main/java/net/minecraftforge/items/CapabilityItemHandler.java @@ -0,0 +1,79 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.items; + +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.util.math.Direction; + +import net.patchworkmc.api.capability.CapabilityRegisteredCallback; + +public class CapabilityItemHandler { + public static Capability ITEM_HANDLER_CAPABILITY = null; + + public static void register() { + CapabilityRegisteredCallback.event(IItemHandler.class).register(cap -> ITEM_HANDLER_CAPABILITY = cap); + + CapabilityManager.INSTANCE.register(IItemHandler.class, new Capability.IStorage() { + @Override + public Tag writeNBT(Capability capability, IItemHandler instance, Direction side) { + ListTag nbtTagList = new ListTag(); + int size = instance.getSlots(); + + for (int i = 0; i < size; i++) { + ItemStack stack = instance.getStackInSlot(i); + + if (!stack.isEmpty()) { + CompoundTag itemTag = new CompoundTag(); + itemTag.putInt("Slot", i); + stack.toTag(itemTag); + nbtTagList.add(itemTag); + } + } + + return nbtTagList; + } + + @Override + public void readNBT(Capability capability, IItemHandler instance, Direction side, Tag base) { + if (!(instance instanceof IItemHandlerModifiable)) { + throw new RuntimeException("IItemHandler instance does not implement IItemHandlerModifiable"); + } + + IItemHandlerModifiable itemHandlerModifiable = (IItemHandlerModifiable) instance; + ListTag tagList = (ListTag) base; + + for (int i = 0; i < tagList.size(); i++) { + CompoundTag itemTags = tagList.getCompound(i); + int j = itemTags.getInt("Slot"); + + if (j >= 0 && j < instance.getSlots()) { + itemHandlerModifiable.setStackInSlot(j, ItemStack.fromTag(itemTags)); + } + } + } + }, ItemStackHandler::new); + } +} diff --git a/patchwork-items/src/main/java/net/minecraftforge/items/IItemHandler.java b/patchwork-items/src/main/java/net/minecraftforge/items/IItemHandler.java new file mode 100644 index 00000000..23851bb9 --- /dev/null +++ b/patchwork-items/src/main/java/net/minecraftforge/items/IItemHandler.java @@ -0,0 +1,112 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.items; + +import javax.annotation.Nonnull; + +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; + +public interface IItemHandler { + /** + * Returns the number of slots available. + * + * @return The number of slots available + */ + int getSlots(); + + /** + * Returns the ItemStack in a given slot. + * + *

The result's stack size may be greater than the itemstack's max size. + * + *

If the result is empty, then the slot is empty. + * + *

IMPORTANT: This ItemStack MUST NOT be modified. This method is not for + * altering an inventory's contents. Any implementers who are able to detect + * modification through this method should throw an exception. + * + *

SERIOUSLY: DO NOT MODIFY THE RETURNED ITEMSTACK + * + * @param slot Slot to query + * @return ItemStack in given slot. Empty Itemstack if the slot is empty. + */ + @Nonnull + ItemStack getStackInSlot(int slot); + + /** + *

Inserts an ItemStack into the given slot and return the remainder. + * The ItemStack should not be modified in this function! + *

+ * Note: This behaviour is subtly different from net.minecraftforge.fluids.capability.IFluidHandler#fill(net.minecraftforge.fluids.FluidStack, boolean) + * + * @param slot Slot to insert into. + * @param stack ItemStack to insert. This must not be modified by the item handler. + * @param simulate If true, the insertion is only simulated + * @return The remaining ItemStack that was not inserted (if the entire stack is accepted, then return an empty ItemStack). + * May be the same as the input ItemStack if unchanged, otherwise a new ItemStack. + * The returned ItemStack can be safely modified after. + */ + @Nonnull + ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate); + + /** + * Extracts an ItemStack from the given slot. + *

The returned value must be empty if nothing is extracted, + * otherwise its stack size must be less than or equal to {@code amount} and {@link ItemStack#getMaxCount()} ()}. + *

+ * + * @param slot Slot to extract from. + * @param amount Amount to extract (may be greater than the current stack's max limit) + * @param simulate If true, the extraction is only simulated + * @return ItemStack extracted from the slot, must be empty if nothing can be extracted. + * The returned ItemStack can be safely modified after, so item handlers should return a new or copied stack. + */ + @Nonnull + ItemStack extractItem(int slot, int amount, boolean simulate); + + /** + * Retrieves the maximum stack size allowed to exist in the given slot. + * + * @param slot Slot to query. + * @return The maximum stack size allowed in the slot. + */ + int getSlotLimit(int slot); + + /** + *

This function re-implements the vanilla function {@link Inventory#isValidInvStack(int, ItemStack)}. + * It should be used instead of simulated insertions in cases where the contents and state of the inventory are + * irrelevant, mainly for the purpose of automation and logic (for instance, testing if a minecart can wait + * to deposit its items into a full inventory, or if the items in the minecart can never be placed into the + * inventory and should move on). + *

+ *
    + *
  • isItemValid is false when insertion of the item is never valid.
  • + *
  • When isItemValid is true, no assumptions can be made and insertion must be simulated case-by-case.
  • + *
  • The actual items in the inventory, its fullness, or any other state are not considered by isItemValid.
  • + *
+ * + * @param slot Slot to query for validity + * @param stack Stack to test with for validity + * @return true if the slot can insert the ItemStack, not considering the current state of the inventory. + * false if the slot can never insert the ItemStack in any situation. + */ + boolean isItemValid(int slot, @Nonnull ItemStack stack); +} diff --git a/patchwork-items/src/main/java/net/minecraftforge/items/IItemHandlerModifiable.java b/patchwork-items/src/main/java/net/minecraftforge/items/IItemHandlerModifiable.java new file mode 100644 index 00000000..e24731cc --- /dev/null +++ b/patchwork-items/src/main/java/net/minecraftforge/items/IItemHandlerModifiable.java @@ -0,0 +1,39 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.items; + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; + +public interface IItemHandlerModifiable extends IItemHandler { + /** + * Overrides the stack in the given slot. This method is used by the + * standard Forge helper methods and classes. It is not intended for + * general use by other mods, and the handler may throw an error if it + * is called unexpectedly. + * + * @param slot Slot to modify + * @param stack ItemStack to set slot to (may be empty). + * @throws RuntimeException if the handler is called in a way that the handler + * was not expecting. + */ + void setStackInSlot(int slot, @Nonnull ItemStack stack); +} diff --git a/patchwork-items/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java b/patchwork-items/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java new file mode 100644 index 00000000..9fc6ed38 --- /dev/null +++ b/patchwork-items/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java @@ -0,0 +1,219 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.items; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; + +import net.patchworkmc.impl.capability.CapabilityProviderHolder; + +public class ItemHandlerHelper { + private static boolean patchwork$areItemStackCapsCompatible(ItemStack a, ItemStack b) { + return ((CapabilityProviderHolder) (Object) a).areCapsCompatible(((CapabilityProviderHolder) (Object) b).getCapabilityProvider()); + } + + @Nonnull + public static ItemStack insertItem(IItemHandler dest, @Nonnull ItemStack stack, boolean simulate) { + if (dest == null || stack.isEmpty()) { + return stack; + } + + for (int i = 0; i < dest.getSlots(); i++) { + stack = dest.insertItem(i, stack, simulate); + + if (stack.isEmpty()) { + return ItemStack.EMPTY; + } + } + + return stack; + } + + public static boolean canItemStacksStack(@Nonnull ItemStack a, @Nonnull ItemStack b) { + if (a.isEmpty() || !a.isItemEqualIgnoreDamage(b) || a.hasTag() != b.hasTag()) { + return false; + } + + return (!a.hasTag() || a.getTag().equals(b.getTag())) && patchwork$areItemStackCapsCompatible(a, b); + } + + /** + * A relaxed version of canItemStacksStack that stacks itemstacks with different metadata if they don't have subtypes. + * This usually only applies when players pick up items. + */ + public static boolean canItemStacksStackRelaxed(@Nonnull ItemStack a, @Nonnull ItemStack b) { + if (a.isEmpty() || b.isEmpty() || a.getItem() != b.getItem()) { + return false; + } + + if (!a.isStackable()) { + return false; + } + + if (a.hasTag() != b.hasTag()) { + return false; + } + + return (!a.hasTag() || a.getTag().equals(b.getTag())) && patchwork$areItemStackCapsCompatible(a, b); + } + + @Nonnull + public static ItemStack copyStackWithSize(@Nonnull ItemStack itemStack, int size) { + if (size == 0) { + return ItemStack.EMPTY; + } + + ItemStack copy = itemStack.copy(); + copy.setCount(size); + return copy; + } + + /** + * Inserts the ItemStack into the inventory, filling up already present stacks first. + * This is equivalent to the behaviour of a player picking up an item. + * Note: This function stacks items without subtypes with different metadata together. + */ + @Nonnull + public static ItemStack insertItemStacked(IItemHandler inventory, @Nonnull ItemStack stack, boolean simulate) { + if (inventory == null || stack.isEmpty()) { + return stack; + } + + // not stackable -> just insert into a new slot + if (!stack.isStackable()) { + return insertItem(inventory, stack, simulate); + } + + int sizeInventory = inventory.getSlots(); + + // go through the inventory and try to fill up already existing items + for (int i = 0; i < sizeInventory; i++) { + ItemStack slot = inventory.getStackInSlot(i); + + if (canItemStacksStackRelaxed(slot, stack)) { + stack = inventory.insertItem(i, stack, simulate); + + if (stack.isEmpty()) { + break; + } + } + } + + // insert remainder into empty slots + if (!stack.isEmpty()) { + // find empty slot + for (int i = 0; i < sizeInventory; i++) { + if (inventory.getStackInSlot(i).isEmpty()) { + stack = inventory.insertItem(i, stack, simulate); + + if (stack.isEmpty()) { + break; + } + } + } + } + + return stack; + } + + /** + * giveItemToPlayer without preferred slot + */ + + /* TODO: PlayerMainInvWrapper + public static void giveItemToPlayer(PlayerEntity player, @Nonnull ItemStack stack) { + giveItemToPlayer(player, stack, -1); + }*/ + + /** + * Inserts the given itemstack into the players inventory. + * If the inventory can't hold it, the item will be dropped in the world at the players position. + * + * @param player The player to give the item to + * @param stack The itemstack to insert + */ + + /* TODO: PlayerMainInvWrapper + public static void giveItemToPlayer(PlayerEntity player, @Nonnull ItemStack stack, int preferredSlot) { + if (stack.isEmpty()) return; + + IItemHandler inventory = new PlayerMainInvWrapper(player.inventory); + World world = player.world; + + // try adding it into the inventory + ItemStack remainder = stack; + + // insert into preferred slot first + if (preferredSlot >= 0 && preferredSlot < inventory.getSlots()) { + remainder = inventory.insertItem(preferredSlot, stack, false); + } + + // then into the inventory in general + if (!remainder.isEmpty()) { + remainder = insertItemStacked(inventory, remainder, false); + } + + // play sound if something got picked up + if (remainder.isEmpty() || remainder.getCount() != stack.getCount()) { + world.playSound(null, player.x, player.y + 0.5, player.z, + SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 0.2F, ((world.random.nextFloat() - world.random.nextFloat()) * 0.7F + 1.0F) * 2.0F); + } + + // drop remaining itemstack into the world + if (!remainder.isEmpty() && !world.isClient) { + ItemEntity entityitem = new ItemEntity(world, player.x, player.y + 0.5, player.z, remainder); + entityitem.setPickupDelay(40); + entityitem.setVelocity(entityitem.getVelocity().multiply(0, 1, 0)); + + world.spawnEntity(entityitem); + } + }*/ + + /** + * This method uses the standard vanilla algorithm to calculate a comparator output for how "full" the inventory is. + * This method is an adaptation of Container#calculateComparatorOutput(Inventory). + * + * @param inv The inventory handler to test. + * @return A redstone value in the range [0,15] representing how "full" this inventory is. + */ + public static int calcRedstoneFromInventory(@Nullable IItemHandler inv) { + if (inv == null) { + return 0; + } else { + int itemsFound = 0; + float proportion = 0.0F; + + for (int j = 0; j < inv.getSlots(); ++j) { + ItemStack itemstack = inv.getStackInSlot(j); + + if (!itemstack.isEmpty()) { + proportion += (float) itemstack.getCount() / (float) Math.min(inv.getSlotLimit(j), itemstack.getMaxCount()); + ++itemsFound; + } + } + + proportion = proportion / (float) inv.getSlots(); + return MathHelper.floor(proportion * 14.0F) + (itemsFound > 0 ? 1 : 0); + } + } +} diff --git a/patchwork-items/src/main/java/net/minecraftforge/items/ItemStackHandler.java b/patchwork-items/src/main/java/net/minecraftforge/items/ItemStackHandler.java new file mode 100644 index 00000000..064ec704 --- /dev/null +++ b/patchwork-items/src/main/java/net/minecraftforge/items/ItemStackHandler.java @@ -0,0 +1,210 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.items; + +import javax.annotation.Nonnull; + +import net.minecraftforge.common.util.INBTSerializable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.util.DefaultedList; + +import net.fabricmc.fabric.api.util.NbtType; + +public class ItemStackHandler implements IItemHandler, IItemHandlerModifiable, INBTSerializable { + protected DefaultedList stacks; + + public ItemStackHandler() { + this(1); + } + + public ItemStackHandler(int size) { + stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); + } + + public ItemStackHandler(DefaultedList stacks) { + this.stacks = stacks; + } + + public void setSize(int size) { + stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); + } + + @Override + public void setStackInSlot(int slot, @Nonnull ItemStack stack) { + validateSlotIndex(slot); + this.stacks.set(slot, stack); + onContentsChanged(slot); + } + + @Override + public int getSlots() { + return stacks.size(); + } + + @Override + @Nonnull + public ItemStack getStackInSlot(int slot) { + validateSlotIndex(slot); + return this.stacks.get(slot); + } + + @Override + @Nonnull + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + if (stack.isEmpty()) { + return ItemStack.EMPTY; + } + + if (!isItemValid(slot, stack)) { + return stack; + } + + validateSlotIndex(slot); + + ItemStack existing = this.stacks.get(slot); + + int limit = getStackLimit(slot, stack); + + if (!existing.isEmpty()) { + if (!ItemHandlerHelper.canItemStacksStack(stack, existing)) { + return stack; + } + + limit -= existing.getCount(); + } + + if (limit <= 0) { + return stack; + } + + boolean reachedLimit = stack.getCount() > limit; + + if (!simulate) { + if (existing.isEmpty()) { + this.stacks.set(slot, reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack); + } else { + existing.increment(reachedLimit ? limit : stack.getCount()); + } + + onContentsChanged(slot); + } + + return reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - limit) : ItemStack.EMPTY; + } + + @Override + @Nonnull + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (amount == 0) { + return ItemStack.EMPTY; + } + + validateSlotIndex(slot); + + ItemStack existing = this.stacks.get(slot); + + if (existing.isEmpty()) { + return ItemStack.EMPTY; + } + + int toExtract = Math.min(amount, existing.getMaxCount()); + + if (existing.getCount() <= toExtract) { + if (!simulate) { + this.stacks.set(slot, ItemStack.EMPTY); + onContentsChanged(slot); + } + + return existing; + } else { + if (!simulate) { + this.stacks.set(slot, ItemHandlerHelper.copyStackWithSize(existing, existing.getCount() - toExtract)); + onContentsChanged(slot); + } + + return ItemHandlerHelper.copyStackWithSize(existing, toExtract); + } + } + + @Override + public int getSlotLimit(int slot) { + return 64; + } + + protected int getStackLimit(int slot, @Nonnull ItemStack stack) { + return Math.min(getSlotLimit(slot), stack.getMaxCount()); + } + + @Override + public boolean isItemValid(int slot, @Nonnull ItemStack stack) { + return true; + } + + @Override + public CompoundTag serializeNBT() { + ListTag nbtTagList = new ListTag(); + + for (int i = 0; i < stacks.size(); i++) { + if (!stacks.get(i).isEmpty()) { + CompoundTag itemTag = new CompoundTag(); + itemTag.putInt("Slot", i); + stacks.get(i).toTag(itemTag); + nbtTagList.add(itemTag); + } + } + + CompoundTag nbt = new CompoundTag(); + nbt.put("Items", nbtTagList); + nbt.putInt("Size", stacks.size()); + return nbt; + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + setSize(nbt.contains("Size", NbtType.INT) ? nbt.getInt("Size") : stacks.size()); + ListTag tagList = nbt.getList("Items", NbtType.COMPOUND); + + for (int i = 0; i < tagList.size(); i++) { + CompoundTag itemTags = tagList.getCompound(i); + int slot = itemTags.getInt("Slot"); + + if (slot >= 0 && slot < stacks.size()) { + stacks.set(slot, ItemStack.fromTag(itemTags)); + } + } + + onLoad(); + } + + protected void validateSlotIndex(int slot) { + if (slot < 0 || slot >= stacks.size()) { + throw new RuntimeException("Slot " + slot + " not in valid range - [0," + stacks.size() + ")"); + } + } + + protected void onLoad() { + } + + protected void onContentsChanged(int slot) { + } +} diff --git a/patchwork-items/src/main/java/net/patchworkmc/impl/items/ItemHandlerInventoryWrapper.java b/patchwork-items/src/main/java/net/patchworkmc/impl/items/ItemHandlerInventoryWrapper.java new file mode 100644 index 00000000..219899e3 --- /dev/null +++ b/patchwork-items/src/main/java/net/patchworkmc/impl/items/ItemHandlerInventoryWrapper.java @@ -0,0 +1,92 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.items; + +import net.minecraftforge.items.IItemHandlerModifiable; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; + +public class ItemHandlerInventoryWrapper implements Inventory { + private IItemHandlerModifiable itemHandler; + + public ItemHandlerInventoryWrapper(IItemHandlerModifiable itemHandler) { + this.itemHandler = itemHandler; + } + + @Override + public int getInvSize() { + return itemHandler.getSlots(); + } + + @Override + public boolean isInvEmpty() { + for (int i = 0; i < itemHandler.getSlots(); i++) { + if (!itemHandler.getStackInSlot(i).isEmpty()) { + return false; + } + } + + return true; + } + + @Override + public ItemStack getInvStack(int slot) { + return itemHandler.getStackInSlot(slot); + } + + @Override + public ItemStack takeInvStack(int slot, int amount) { + return itemHandler.extractItem(slot, amount, false); + } + + @Override + public ItemStack removeInvStack(int slot) { + ItemStack copy = itemHandler.getStackInSlot(slot).copy(); + itemHandler.setStackInSlot(slot, ItemStack.EMPTY); + return copy; + } + + @Override + public void setInvStack(int slot, ItemStack stack) { + itemHandler.setStackInSlot(slot, stack); + } + + @Override + public void markDirty() { + } + + @Override + public boolean canPlayerUseInv(PlayerEntity player) { + return false; + } + + @Override + public void clear() { + for (int i = 0; i < itemHandler.getSlots(); i++) { + itemHandler.setStackInSlot(i, ItemStack.EMPTY); + } + } + + public IItemHandlerModifiable getItemHandler() { + return this.itemHandler; + } +} diff --git a/patchwork-items/src/main/java/net/patchworkmc/impl/items/PatchworkItems.java b/patchwork-items/src/main/java/net/patchworkmc/impl/items/PatchworkItems.java new file mode 100644 index 00000000..fba684d7 --- /dev/null +++ b/patchwork-items/src/main/java/net/patchworkmc/impl/items/PatchworkItems.java @@ -0,0 +1,38 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.items; + +import net.minecraftforge.items.CapabilityItemHandler; + +import net.minecraft.util.math.Direction; + +import net.fabricmc.api.ModInitializer; + +public class PatchworkItems implements ModInitializer { + /** + * Shared ThreadLocal for {@link net.patchworkmc.mixin.items.MixinDropperBlock} and {@link net.patchworkmc.mixin.items.MixinHopperBlockEntity}. + */ + public static final ThreadLocal currentSide = new ThreadLocal<>(); + + @Override + public void onInitialize() { + CapabilityItemHandler.register(); + } +} diff --git a/patchwork-items/src/main/java/net/patchworkmc/mixin/items/MixinDropperBlock.java b/patchwork-items/src/main/java/net/patchworkmc/mixin/items/MixinDropperBlock.java new file mode 100644 index 00000000..b4bd9c1f --- /dev/null +++ b/patchwork-items/src/main/java/net/patchworkmc/mixin/items/MixinDropperBlock.java @@ -0,0 +1,39 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.items; + +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.block.DropperBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.patchworkmc.impl.items.PatchworkItems; + +@Mixin(DropperBlock.class) +public class MixinDropperBlock { + @Inject(method = "dispense", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/HopperBlockEntity;getInventoryAt(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/inventory/Inventory;")) + private void onDispenseGetInventory(World world, BlockPos pos, CallbackInfo ci) { + PatchworkItems.currentSide.set(world.getBlockState(pos).get(DropperBlock.FACING)); + } +} diff --git a/patchwork-items/src/main/java/net/patchworkmc/mixin/items/MixinHopperBlockEntity.java b/patchwork-items/src/main/java/net/patchworkmc/mixin/items/MixinHopperBlockEntity.java new file mode 100644 index 00000000..bc8ffb7d --- /dev/null +++ b/patchwork-items/src/main/java/net/patchworkmc/mixin/items/MixinHopperBlockEntity.java @@ -0,0 +1,93 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.items; + +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.HopperBlock; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.Hopper; +import net.minecraft.block.entity.HopperBlockEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +import net.patchworkmc.impl.items.PatchworkItems; +import net.patchworkmc.impl.items.ItemHandlerInventoryWrapper; + +@Mixin(HopperBlockEntity.class) +public class MixinHopperBlockEntity { + @Inject(method = "getInputInventory", at = @At("HEAD")) + private static void onGetInputInventory(Hopper hopper, CallbackInfoReturnable cir) { + PatchworkItems.currentSide.set(Direction.UP); + } + + @Inject(method = "getOutputInventory", at = @At("HEAD")) + private void onGetOutputInventory(CallbackInfoReturnable cir) { + PatchworkItems.currentSide.set(((BlockEntity) (Object) this).getCachedState().get(HopperBlock.FACING)); + } + + @Inject(method = "getInventoryAt(Lnet/minecraft/world/World;DDD)Lnet/minecraft/inventory/Inventory;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getEntities(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/Box;Ljava/util/function/Predicate;)Ljava/util/List;"), cancellable = true) + private static void onGetInventoryAt(World world, double x, double y, double z, CallbackInfoReturnable cir) { + BlockPos blockPos = new BlockPos(x, y, z); + BlockState blockState = world.getBlockState(blockPos); + Block block = blockState.getBlock(); + + if (block.hasBlockEntity()) { + BlockEntity blockEntity = world.getBlockEntity(blockPos); + + if (blockEntity != null) { + Direction direction = PatchworkItems.currentSide.get(); + + if (direction != null) { + LazyOptional capability = ((ICapabilityProvider) blockEntity).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()); + PatchworkItems.currentSide.remove(); + capability.ifPresent(result -> { + if (result instanceof IItemHandlerModifiable) { + cir.setReturnValue(new ItemHandlerInventoryWrapper((IItemHandlerModifiable) result)); + } + }); + } + } + } + } + + @Inject(method = "transfer(Lnet/minecraft/inventory/Inventory;Lnet/minecraft/inventory/Inventory;Lnet/minecraft/item/ItemStack;ILnet/minecraft/util/math/Direction;)Lnet/minecraft/item/ItemStack;", at = @At("HEAD"), cancellable = true) + private static void onTransfer(Inventory from, Inventory to, ItemStack stack, int slot, Direction direction, CallbackInfoReturnable cir) { + IItemHandlerModifiable itemHandler; + + if (to instanceof ItemHandlerInventoryWrapper) { + itemHandler = ((ItemHandlerInventoryWrapper) to).getItemHandler(); + cir.setReturnValue(itemHandler.insertItem(slot, stack, false)); + } + } +} diff --git a/patchwork-items/src/main/resources/assets/patchwork-items/icon.png b/patchwork-items/src/main/resources/assets/patchwork-items/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-items/src/main/resources/fabric.mod.json b/patchwork-items/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..1e0f461c --- /dev/null +++ b/patchwork-items/src/main/resources/fabric.mod.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "id": "patchwork-items", + "version": "${version}", + "name": "Patchwork Items", + "description": "A reimplementation of the Minecraft Forge item handling APIs.", + "authors": [ + "coderbot" + ], + "license": "LGPL-2.1-only", + "icon": "assets/patchwork-items/icon.png", + "environment": "*", + "depends": { + "fabricloader": ">=0.8.4", + "fabric": "*" + }, + "mixins": [ + "patchwork-items.mixins.json" + ], + "entrypoints": { + "main": ["net.patchworkmc.impl.items.PatchworkItems"] + }, + "custom": { + "modmenu:api": true, + "modmenu:parent": "patchwork" + } +} diff --git a/patchwork-items/src/main/resources/patchwork-items.mixins.json b/patchwork-items/src/main/resources/patchwork-items.mixins.json new file mode 100644 index 00000000..edf8c6d6 --- /dev/null +++ b/patchwork-items/src/main/resources/patchwork-items.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.items", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinDropperBlock", + "MixinHopperBlockEntity" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/settings.gradle b/settings.gradle index 03a12707..3da056d2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,6 +30,7 @@ include 'patchwork-extensions-shearing' include 'patchwork-fml' include 'patchwork-god-classes' include 'patchwork-gui' +include 'patchwork-items' include 'patchwork-key-bindings' include 'patchwork-level-generators' include 'patchwork-loot' From e936b614198814dce2c32014c9c9f64b5e113895 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Tue, 11 Aug 2020 12:14:28 -0500 Subject: [PATCH 45/73] Hotfix: another memory leak involving ThreadLocal --- .../mixin/event/entity/MixinFishingBobberEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFishingBobberEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFishingBobberEntity.java index 24731ac2..9b5d6213 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFishingBobberEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinFishingBobberEntity.java @@ -66,7 +66,7 @@ private void onRodDamage(ItemStack itemStack, CallbackInfoReturnable ci if (damage != -1) { cir.setReturnValue(damage); - rodDamage.set(-1); + rodDamage.remove(); } } } From 8437561c668c6bc5eb6b03cb5648353985da770c Mon Sep 17 00:00:00 2001 From: Walker Knapp <30479917+WalkerKnapp@users.noreply.github.com> Date: Fri, 14 Aug 2020 17:13:48 -0400 Subject: [PATCH 46/73] Implement ClientPlayerNetworkEvent (#177) * Implement ClientPlayerNetworkEvent * Only use MixinMinecraftClient on the client * Move ClientHooks to patchwork-god-classes --- patchwork-god-classes/build.gradle | 1 + .../fml/client/ClientHooks.java | 40 +++++++ .../event/ClientPlayerNetworkEvent.java | 104 ++++++++++++++++++ .../networking/ClientNetworkingEvents.java | 41 +++++++ .../client/MixinMinecraftClient.java | 47 ++++++++ .../MixinClientPlayNetworkHandler.java | 22 ++++ .../src/main/resources/fabric.mod.json | 1 + .../patchwork-networking.client.mixins.json | 11 ++ 8 files changed, 267 insertions(+) create mode 100644 patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/ClientHooks.java create mode 100644 patchwork-networking/src/main/java/net/minecraftforge/client/event/ClientPlayerNetworkEvent.java create mode 100644 patchwork-networking/src/main/java/net/patchworkmc/impl/networking/ClientNetworkingEvents.java create mode 100644 patchwork-networking/src/main/java/net/patchworkmc/mixin/networking/client/MixinMinecraftClient.java create mode 100644 patchwork-networking/src/main/resources/patchwork-networking.client.mixins.json diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 27e9eb18..196740c8 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -11,4 +11,5 @@ dependencies { implementation project(path: ':patchwork-events-rendering', configuration: 'dev') implementation project(path: ':patchwork-events-world', configuration: 'dev') implementation project(path: ':patchwork-loot', configuration: 'dev') + implementation project(path: ':patchwork-networking', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/ClientHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/ClientHooks.java new file mode 100644 index 00000000..cb087f9c --- /dev/null +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/ClientHooks.java @@ -0,0 +1,40 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.client; + +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.network.ClientConnection; + +import net.patchworkmc.impl.networking.ClientNetworkingEvents; + +public class ClientHooks { + public static void firePlayerLogin(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity player, final ClientConnection clientConnection) { + ClientNetworkingEvents.firePlayerLogin(interactionManager, player, clientConnection); + } + + public static void firePlayerLogout(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity player) { + ClientNetworkingEvents.firePlayerLogout(interactionManager, player); + } + + public static void firePlayerRespawn(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity oldPlayer, final ClientPlayerEntity newPlayer, final ClientConnection clientConnection) { + ClientNetworkingEvents.firePlayerRespawn(interactionManager, oldPlayer, newPlayer, clientConnection); + } +} diff --git a/patchwork-networking/src/main/java/net/minecraftforge/client/event/ClientPlayerNetworkEvent.java b/patchwork-networking/src/main/java/net/minecraftforge/client/event/ClientPlayerNetworkEvent.java new file mode 100644 index 00000000..a6c90336 --- /dev/null +++ b/patchwork-networking/src/main/java/net/minecraftforge/client/event/ClientPlayerNetworkEvent.java @@ -0,0 +1,104 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.event; + +import net.minecraftforge.eventbus.api.Event; + +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.network.ClientConnection; + +/** + * Client-side events fired on changes to player connectivity. + */ +public class ClientPlayerNetworkEvent extends Event { + private final ClientPlayerInteractionManager playerInteractionManager; + private final ClientPlayerEntity player; + private final ClientConnection clientConnection; + + ClientPlayerNetworkEvent(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity player, final ClientConnection clientConnection) { + this.playerInteractionManager = interactionManager; + this.player = player; + this.clientConnection = clientConnection; + } + + /** + * @return The ClientPlayerInteractionManager instance for the client side. + */ + public ClientPlayerInteractionManager getController() { + return this.playerInteractionManager; + } + + /** + * @return The player instance, if present (otherwise, returns null). + */ + public ClientPlayerEntity getPlayer() { + return this.player; + } + + /** + * @return The network connection, if present (otherwise, returns null). + */ + public ClientConnection getNetworkManager() { + return this.clientConnection; + } + + /** + * Fired when the player logs out. + * + *

Note: This might also be fired when a new integrated server is being created.

+ */ + public static class LoggedInEvent extends ClientPlayerNetworkEvent { + public LoggedInEvent(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity player, final ClientConnection clientConnection) { + super(interactionManager, player, clientConnection); + } + } + + /** + * Fired when the player logs out. + * + *

Note: This might also fire when a new integrated server is being created.

+ */ + public static class LoggedOutEvent extends ClientPlayerNetworkEvent { + public LoggedOutEvent(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity player, final ClientConnection clientConnection) { + super(interactionManager, player, clientConnection); + } + } + + /** + * Fired when the player object respawns, such as dimension changes. + */ + public static class RespawnEvent extends ClientPlayerNetworkEvent { + private final ClientPlayerEntity oldPlayer; + + public RespawnEvent(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity oldPlayer, final ClientPlayerEntity newPlayer, final ClientConnection clientConnection) { + super(interactionManager, newPlayer, clientConnection); + this.oldPlayer = oldPlayer; + } + + public ClientPlayerEntity getOldPlayer() { + return this.oldPlayer; + } + + public ClientPlayerEntity getNewPlayer() { + return super.getPlayer(); + } + } +} diff --git a/patchwork-networking/src/main/java/net/patchworkmc/impl/networking/ClientNetworkingEvents.java b/patchwork-networking/src/main/java/net/patchworkmc/impl/networking/ClientNetworkingEvents.java new file mode 100644 index 00000000..2545045a --- /dev/null +++ b/patchwork-networking/src/main/java/net/patchworkmc/impl/networking/ClientNetworkingEvents.java @@ -0,0 +1,41 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.networking; + +import net.minecraftforge.client.event.ClientPlayerNetworkEvent; +import net.minecraftforge.common.MinecraftForge; + +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.network.ClientConnection; + +public class ClientNetworkingEvents { + public static void firePlayerLogin(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity player, final ClientConnection clientConnection) { + MinecraftForge.EVENT_BUS.post(new ClientPlayerNetworkEvent.LoggedInEvent(interactionManager, player, clientConnection)); + } + + public static void firePlayerLogout(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity player) { + MinecraftForge.EVENT_BUS.post(new ClientPlayerNetworkEvent.LoggedOutEvent(interactionManager, player, player != null ? player.networkHandler != null ? player.networkHandler.getConnection() : null : null)); + } + + public static void firePlayerRespawn(final ClientPlayerInteractionManager interactionManager, final ClientPlayerEntity oldPlayer, final ClientPlayerEntity newPlayer, final ClientConnection clientConnection) { + MinecraftForge.EVENT_BUS.post(new ClientPlayerNetworkEvent.RespawnEvent(interactionManager, oldPlayer, newPlayer, clientConnection)); + } +} diff --git a/patchwork-networking/src/main/java/net/patchworkmc/mixin/networking/client/MixinMinecraftClient.java b/patchwork-networking/src/main/java/net/patchworkmc/mixin/networking/client/MixinMinecraftClient.java new file mode 100644 index 00000000..0a541d38 --- /dev/null +++ b/patchwork-networking/src/main/java/net/patchworkmc/mixin/networking/client/MixinMinecraftClient.java @@ -0,0 +1,47 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.networking.client; + +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.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; + +import net.patchworkmc.impl.networking.ClientNetworkingEvents; + +@Mixin(MinecraftClient.class) +public class MixinMinecraftClient { + @Shadow + public ClientPlayerInteractionManager interactionManager; + + @Shadow + public ClientPlayerEntity player; + + @Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;reset()V", shift = At.Shift.AFTER)) + public void patchwork$hookDisconnect(CallbackInfo ci) { + ClientNetworkingEvents.firePlayerLogout(this.interactionManager, this.player); + } +} diff --git a/patchwork-networking/src/main/java/net/patchworkmc/mixin/networking/handler/MixinClientPlayNetworkHandler.java b/patchwork-networking/src/main/java/net/patchworkmc/mixin/networking/handler/MixinClientPlayNetworkHandler.java index 812e17a5..4fcd7104 100644 --- a/patchwork-networking/src/main/java/net/patchworkmc/mixin/networking/handler/MixinClientPlayNetworkHandler.java +++ b/patchwork-networking/src/main/java/net/patchworkmc/mixin/networking/handler/MixinClientPlayNetworkHandler.java @@ -26,13 +26,23 @@ 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.LocalCapture; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.network.ClientConnection; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket; +import net.minecraft.world.dimension.DimensionType; + +import net.patchworkmc.impl.networking.ClientNetworkingEvents; @Mixin(ClientPlayNetworkHandler.class) public abstract class MixinClientPlayNetworkHandler { + @Shadow + private MinecraftClient client; + @Shadow public abstract ClientConnection getConnection(); @@ -42,4 +52,16 @@ public abstract class MixinClientPlayNetworkHandler { callback.cancel(); } } + + @Inject(method = "onGameJoin", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/GameJoinS2CPacket;getEntityId()I")) + public void patchwork$hookGameJoin(CallbackInfo ci) { + ClientNetworkingEvents.firePlayerLogin(this.client.interactionManager, this.client.player, this.client.getNetworkHandler().getConnection()); + } + + @Inject(method = "onPlayerRespawn", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;addPlayer(ILnet/minecraft/client/network/AbstractClientPlayerEntity;)V"), + locals = LocalCapture.CAPTURE_FAILHARD) + public void patchwork$hookPlayerRespawn(PlayerRespawnS2CPacket packet, CallbackInfo ci, DimensionType dimensionType, ClientPlayerEntity clientPlayerEntity, int i, String string, ClientPlayerEntity clientPlayerEntity2) { + ClientNetworkingEvents.firePlayerRespawn(this.client.interactionManager, clientPlayerEntity, clientPlayerEntity2, clientPlayerEntity2.networkHandler.getConnection()); + } } diff --git a/patchwork-networking/src/main/resources/fabric.mod.json b/patchwork-networking/src/main/resources/fabric.mod.json index 458a68e7..f5a3fbdc 100644 --- a/patchwork-networking/src/main/resources/fabric.mod.json +++ b/patchwork-networking/src/main/resources/fabric.mod.json @@ -18,6 +18,7 @@ }, "mixins": [ "patchwork-networking.accessor.mixins.json", + "patchwork-networking.client.mixins.json", "patchwork-networking.handler.mixins.json", "patchwork-networking.packet.mixins.json" ], diff --git a/patchwork-networking/src/main/resources/patchwork-networking.client.mixins.json b/patchwork-networking/src/main/resources/patchwork-networking.client.mixins.json new file mode 100644 index 00000000..3eb9d42c --- /dev/null +++ b/patchwork-networking/src/main/resources/patchwork-networking.client.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.networking.client", + "compatibilityLevel": "JAVA_8", + "client": [ + "MixinMinecraftClient" + ], + "injectors": { + "defaultRequire": 1 + } +} From 72a45a34b0c2a3009b5a8c809e19991ea73dcc0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Sat, 15 Aug 2020 10:35:19 +1000 Subject: [PATCH 47/73] Add ChunkEvent (#176) * Add ChunkEvent * Update patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEventsClient.java Co-authored-by: Glitch Co-authored-by: Glitch --- .../event/world/ChunkEvent.java | 93 +++++++++++++++++++ .../impl/event/world/WorldEvents.java | 21 +++++ .../impl/event/world/WorldEventsClient.java | 45 +++++++++ .../world/MixinThreadedAnvilChunkStorage.java | 19 ++++ .../src/main/resources/fabric.mod.json | 8 ++ 5 files changed, 186 insertions(+) create mode 100644 patchwork-events-world/src/main/java/net/minecraftforge/event/world/ChunkEvent.java create mode 100644 patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEventsClient.java diff --git a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/ChunkEvent.java b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/ChunkEvent.java new file mode 100644 index 00000000..3d81bf29 --- /dev/null +++ b/patchwork-events-world/src/main/java/net/minecraftforge/event/world/ChunkEvent.java @@ -0,0 +1,93 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.world; + +import net.minecraftforge.common.MinecraftForge; + +import net.minecraft.world.IWorld; +import net.minecraft.world.chunk.Chunk; + +import net.patchworkmc.impl.event.world.WorldEvents; + +/** + * ChunkEvent is fired when an event involving a chunk occurs.
+ * If a method utilizes this {@link net.minecraftforge.eventbus.api.Event} as + * its parameter, the method will receive every child event of this class.
+ *
+ * {@link #Chunk} contains the Chunk this event is affecting.
+ *
+ * All children of this event are fired on the + * {@link MinecraftForge#EVENT_BUS}.
+ */ +public class ChunkEvent extends WorldEvent { + private final Chunk chunk; + + public ChunkEvent(Chunk chunk) { + super(WorldEvents.getWorldForChunk(chunk)); + this.chunk = chunk; + } + + public ChunkEvent(Chunk chunk, IWorld world) { + super(world); + this.chunk = chunk; + } + + public Chunk getChunk() { + return chunk; + } + + /** + * ChunkEvent.Load is fired when vanilla Minecraft attempts to load a Chunk into + * the world.
+ * This event is fired during chunk loading in
+ * {@link ChunkProviderClient#loadChunk(int, int)},
+ * Chunk.onChunkLoad().
+ *
+ * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.
+ *
+ * This event does not have a result. {@link HasResult}
+ *
+ * This event is fired on the {@link MinecraftForge#EVENT_BUS}.
+ */ + public static class Load extends ChunkEvent { + public Load(Chunk chunk) { + super(chunk); + } + } + + /** + * ChunkEvent.Unload is fired when vanilla Minecraft attempts to unload a Chunk + * from the world.
+ * This event is fired during chunk unloading in
+ * Chunk.onChunkUnload().
+ *
+ * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.
+ *
+ * This event does not have a result. {@link HasResult}
+ *
+ * This event is fired on the {@link MinecraftForge#EVENT_BUS}.
+ */ + public static class Unload extends ChunkEvent { + public Unload(Chunk chunk) { + super(chunk); + } + } +} + diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index 4b33e3a3..f8672377 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -22,8 +22,11 @@ import java.util.Collections; import java.util.List; +import javax.annotation.Nullable; + import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.ChunkWatchEvent; import net.minecraftforge.event.world.WorldEvent; @@ -39,10 +42,13 @@ import net.minecraft.util.math.ChunkPos; import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.level.LevelInfo; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; public class WorldEvents implements ModInitializer { @@ -87,6 +93,16 @@ public static void fireChunkWatch(boolean watch, ServerPlayerEntity entity, Chun } } + /** + * Called by ChunkEvent. + * @return the IWorld instance holding the given chunk, null if not applicable. + */ + @Nullable + public static IWorld getWorldForChunk(Chunk chunk) { + // replaces IForgeChunk.getWorldForge() + return chunk instanceof WorldChunk ? ((WorldChunk) chunk).getWorld() : null; + } + @Override public void onInitialize() { ServerWorldEvents.LOAD.register((server, world) -> { @@ -96,5 +112,10 @@ public void onInitialize() { onWorldLoad(world); } }); + + // Fire ChunkEvent.Load on server side, the other location is in MixinThreadedAnvilChunkStorage + ServerChunkEvents.CHUNK_LOAD.register((server, chunk) -> MinecraftForge.EVENT_BUS.post(new ChunkEvent.Load(chunk))); + // Fire ChunkEvent.Unload on server side + ServerChunkEvents.CHUNK_UNLOAD.register((server, chunk) -> MinecraftForge.EVENT_BUS.post(new ChunkEvent.Unload(chunk))); } } diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEventsClient.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEventsClient.java new file mode 100644 index 00000000..17e69d10 --- /dev/null +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEventsClient.java @@ -0,0 +1,45 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.event.world; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkEvent; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents; + +public class WorldEventsClient implements ClientModInitializer { + @Override + public void onInitializeClient() { + /////////////////////////////////////////////// + /// ChunkEvent.Load and Unload on client side + /////////////////////////////////////////////// + ClientChunkEvents.CHUNK_LOAD.register((server, chunk) -> MinecraftForge.EVENT_BUS.post(new ChunkEvent.Load(chunk))); + ClientChunkEvents.CHUNK_UNLOAD.register((server, chunk) -> MinecraftForge.EVENT_BUS.post(new ChunkEvent.Unload(chunk))); + // Fabric fires the chunk unload event after it's been removed from the client's chunk graph. This probably won't cause any issues. + /* ClientChunkManager.unload(II)V + * if (method_20181(chunk, x, z)) { + * net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.ChunkEvent.Unload(chunk)); + * this.chunks.method_20183(i, chunk, (WorldChunk)null); + * ClientChunkEvents.CHUNK_UNLOAD + * } + */ + } +} diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java index 91e2404b..bc3bc70d 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java @@ -22,14 +22,21 @@ 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.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.Packet; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ThreadedAnvilChunkStorage; import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.Chunk; import net.patchworkmc.impl.event.world.WorldEvents; @@ -44,4 +51,16 @@ private void fireWatchEvents(ServerPlayerEntity player, ChunkPos pos, Packet[ WorldEvents.fireChunkWatch(withinViewDistance, player, pos, this.world); } } + + // Lambda in "private CompletableFuture> method_20619(ChunkPos chunkPos)" + // chunk.setLastSaveTime(this.world.getTime()); + // + MinecraftForge.EVENT_BUS.post(new ChunkEvent.Load(chunk)); + // return Either.left(chunk); + @SuppressWarnings("rawtypes") + @Inject(method = "method_17256", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", shift = Shift.AFTER, ordinal = 0, target = + "net/minecraft/world/chunk/Chunk.setLastSaveTime(J)V")) + public void onServerChunkLoad(ChunkPos chunkPos, CallbackInfoReturnable cir, CompoundTag compoundTag, boolean bl, Chunk chunk) { + // Fire ChunkEvent.Load on server side + MinecraftForge.EVENT_BUS.post(new ChunkEvent.Load(chunk)); + } } diff --git a/patchwork-events-world/src/main/resources/fabric.mod.json b/patchwork-events-world/src/main/resources/fabric.mod.json index 509b8176..412740f3 100644 --- a/patchwork-events-world/src/main/resources/fabric.mod.json +++ b/patchwork-events-world/src/main/resources/fabric.mod.json @@ -15,6 +15,14 @@ "depends": { "patchwork-api-base": "*" }, + "entrypoints": { + "main": [ + "net.patchworkmc.impl.event.world.WorldEvents" + ], + "client": [ + "net.patchworkmc.impl.event.world.WorldEventsClient" + ] + }, "mixins": [ "patchwork-events-world.mixins.json" ], From 146f43b16a108c55e11e808775aad192a9cb2ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Mon, 17 Aug 2020 05:38:43 +1000 Subject: [PATCH 48/73] Feature/block harvest (#174) * Impl removedByPlayer and canHarvestBlock in IForgeBlock * Apply kitlith's suggestions * Fix ThreadLocal memory leakage * Apply suggestions * Remove unneeded dependency * Disable an unnecessary 1.15 patch * Move BlockEvent from events-world to extensions-block. This removes a unnecessary dependency. * Replace a redirect with injection * Apply suggestions * Merge remote-tracking branch 'origin/master' into feature/block-harvest Conflicts: patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java Co-authored-by: TheGlitch76 --- .../impl/event/world/WorldEvents.java | 13 -- .../MixinServerPlayerInteractionManager.java | 101 ---------- .../patchwork-events-world.mixins.json | 3 +- patchwork-extensions-block/build.gradle | 1 + .../common/extensions/IForgeBlock.java | 28 +-- .../common/extensions/IForgeBlockState.java | 15 +- .../event/world/BlockEvent.java | 19 +- .../impl/extensions/block/BlockContext.java | 22 +-- .../extensions/block/BlockHarvestManager.java | 173 ++++++++++++++++++ .../impl/extensions/block/PatchworkBlock.java | 26 +++ .../mixin/extensions/block/MixinBlock.java | 14 ++ .../block/flammable/MixinWorld.java | 49 +++++ .../block/harvest/MixinOreBlock.java | 42 +++++ .../block/harvest/MixinRedstoneOreBlock.java | 36 ++++ .../MixinServerPlayerInteractionManager.java | 149 +++++++++++++++ .../block/harvest/MixinSpawnerBlock.java | 36 ++++ .../src/main/resources/fabric.mod.json | 5 +- ...ork-extensions-block-flammable.mixins.json | 11 ++ ...hwork-extensions-block-harvest.mixins.json | 14 ++ .../patchwork-extensions-block.accesswidener | 2 + patchwork-god-classes/build.gradle | 1 + .../net/minecraftforge/common/ForgeHooks.java | 9 + .../event/ForgeEventFactory.java | 6 +- .../src/main/resources/fabric.mod.json | 3 + 24 files changed, 622 insertions(+), 156 deletions(-) delete mode 100644 patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java rename {patchwork-events-world => patchwork-extensions-block}/src/main/java/net/minecraftforge/event/world/BlockEvent.java (90%) create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java create mode 100644 patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java create mode 100644 patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json create mode 100644 patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index f8672377..d20a4a49 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -25,16 +25,10 @@ import javax.annotation.Nullable; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.ChunkWatchEvent; import net.minecraftforge.event.world.WorldEvent; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.DefaultedList; -import net.minecraft.world.World; import net.minecraft.entity.EntityCategory; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; @@ -78,13 +72,6 @@ public static void onWorldSave(IWorld world) { MinecraftForge.EVENT_BUS.post(new WorldEvent.Save(world)); } - // TODO: Leaving this unfired is intentional. See: https://github.com/MinecraftForge/MinecraftForge/issues/5828 - public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { - BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(world, pos, state, fortune, dropChance, drops, player, silkTouch); - MinecraftForge.EVENT_BUS.post(event); - return event.getDropChance(); - } - public static void fireChunkWatch(boolean watch, ServerPlayerEntity entity, ChunkPos chunkpos, ServerWorld world) { if (watch) { MinecraftForge.EVENT_BUS.post(new ChunkWatchEvent.Watch(entity, chunkpos, world)); diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java deleted file mode 100644 index 7b62fa81..00000000 --- a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinServerPlayerInteractionManager.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.event.world; - -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.world.BlockEvent; -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.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.network.ServerPlayerInteractionManager; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.EmptyBlockView; -import net.minecraft.world.GameMode; - -@Mixin(ServerPlayerInteractionManager.class) -public class MixinServerPlayerInteractionManager { - @Shadow - public ServerWorld world; - @Shadow - public ServerPlayerEntity player; - @Shadow - private GameMode gameMode; - - @Inject(method = "tryBreakBlock", at = @At("HEAD"), cancellable = true) - private void hookBreakBlock(BlockPos pos, CallbackInfoReturnable callback) { - boolean preCancelEvent = false; - - ItemStack itemstack = player.getMainHandStack(); - - if (!itemstack.isEmpty() && !itemstack.getItem().canMine(world.getBlockState(pos), world, pos, player)) { - preCancelEvent = true; - } - - // method_21701 => canMine - // Isn't the function really canNotMine? - - if (player.method_21701(world, pos, gameMode)) { - preCancelEvent = true; - } - - // Tell client the block is gone immediately then process events - if (world.getBlockEntity(pos) == null) { - player.networkHandler.sendPacket(new BlockUpdateS2CPacket(EmptyBlockView.INSTANCE, pos)); - } - - // Post the block break event - BlockState state = world.getBlockState(pos); - BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player); - event.setCanceled(preCancelEvent); - MinecraftForge.EVENT_BUS.post(event); - - // Handle if the event is canceled - if (event.isCanceled()) { - // Let the client know the block still exists - player.networkHandler.sendPacket(new BlockUpdateS2CPacket(world, pos)); - - // Update any block entity data for this block - BlockEntity entity = world.getBlockEntity(pos); - - if (entity != null) { - BlockEntityUpdateS2CPacket packet = entity.toUpdatePacket(); - - if (packet != null) { - player.networkHandler.sendPacket(packet); - } - } - - callback.setReturnValue(false); - } else if (event.getExpToDrop() != 0) { - // TODO: Drop experience - throw new UnsupportedOperationException("Cannot drop exp from a BreakEvent yet"); - } - } -} diff --git a/patchwork-events-world/src/main/resources/patchwork-events-world.mixins.json b/patchwork-events-world/src/main/resources/patchwork-events-world.mixins.json index c05375cc..6a959e02 100644 --- a/patchwork-events-world/src/main/resources/patchwork-events-world.mixins.json +++ b/patchwork-events-world/src/main/resources/patchwork-events-world.mixins.json @@ -5,10 +5,9 @@ "mixins": [ "MixinChunkGenerator", "MixinMinecraftServer", - "MixinServerPlayerInteractionManager", "MixinServerWorld", "MixinSpawnHelper", - "MixinThreadedAnvilChunkStorage", + "MixinThreadedAnvilChunkStorage" ], "client": [ "MixinClientWorld", diff --git a/patchwork-extensions-block/build.gradle b/patchwork-extensions-block/build.gradle index 6bdfc305..94c92392 100644 --- a/patchwork-extensions-block/build.gradle +++ b/patchwork-extensions-block/build.gradle @@ -4,6 +4,7 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') implementation project(path: ':patchwork-enum-hacks', configuration: 'dev') + implementation project(path: ':patchwork-extensions-item', configuration: 'dev') implementation project(path: ':patchwork-tooltype', configuration: 'dev') } diff --git a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java index 4c540345..2a860bff 100644 --- a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java +++ b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlock.java @@ -27,6 +27,7 @@ import javax.annotation.Nullable; import net.minecraftforge.common.IPlantable; +import net.minecraftforge.common.ToolType; import net.minecraft.block.BedBlock; import net.minecraft.block.Block; @@ -82,10 +83,12 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; +import net.patchworkmc.impl.extensions.block.PatchworkBlock; import net.patchworkmc.mixin.extensions.block.FireBlockAccessor; import net.patchworkmc.mixin.extensions.block.PlantBlockAccessor; -public interface IForgeBlock { +public interface IForgeBlock extends PatchworkBlock { default Block getBlock() { return (Block) this; } @@ -204,7 +207,7 @@ default BlockEntity createTileEntity(BlockState state, BlockView world) { return null; } - /* TODO IForgeBlock#canHarvestBlock indirectly requires ToolType (via ForgeHooks#canHarvestBlock) + /* TODO IForgeBlock#canHarvestBlock indirectly requires ToolType (via ForgeHooks#canHarvestBlock) */ /** * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed. * @@ -212,10 +215,10 @@ default BlockEntity createTileEntity(BlockState state, BlockView world) { * @param pos The block's current position * @param player The player damaging the block * @return True to spawn the drops - * + */ default boolean canHarvestBlock(BlockState state, BlockView world, BlockPos pos, PlayerEntity player) { - return ForgeHooks.canHarvestBlock(state, player, world, pos); - }*/ + return BlockHarvestManager.canHarvestBlock(state, player, world, pos); + } // TODO Call locations: Patches: ServerPlayerInteractionManager* /** @@ -240,7 +243,7 @@ default boolean canHarvestBlock(BlockState state, BlockView world, BlockPos pos, */ default boolean removedByPlayer(BlockState state, World world, BlockPos pos, PlayerEntity player, boolean willHarvest, FluidState fluid) { getBlock().onBreak(world, pos, state, player); - return world.removeBlock(pos, false); + return world.setBlockState(pos, fluid.getBlockState(), world.isClient ? 11 : 3); } // TODO Call locations: Patches: LivingEntity*, PlayerEntity*, Forge classes: ForgeEventFactory (called from LivingEntity patch) @@ -645,6 +648,7 @@ default boolean isBeaconBase(BlockState state, CollisionView world, BlockPos pos // TODO Call locations: Forge classes: BreakEvent* /** * Gathers how much experience this block drops when broken. + * TODO: there's no equivalent callback in Fabric API, so for now Fabric mods should always return 0 here. * * @param state The current state * @param world The world @@ -778,12 +782,12 @@ default boolean getWeakChanges(BlockState state, CollisionView world, BlockPos p return false; } - /* TODO IForgeBlock#getHarvestTool needs ToolType + /* TODO IForgeBlock#getHarvestTool needs ToolType */ /** * Queries the class of tool required to harvest this block, if null is returned * we assume that anything can harvest this block. - * - ToolType getHarvestTool(BlockState state);*/ + */ + ToolType getHarvestTool(BlockState state); // TODO Call locations: Patches: PickaxeItem*, Forge classes: ForgeHooks* /** @@ -793,18 +797,18 @@ default boolean getWeakChanges(BlockState state, CollisionView world, BlockPos p */ int getHarvestLevel(BlockState state); - /* TODO IForgeBlock#isToolEffective needs ToolType + /* TODO IForgeBlock#isToolEffective needs ToolType */ /** * Checks if the specified tool type is efficient on this block, * meaning that it digs at full speed. - * + */ default boolean isToolEffective(BlockState state, ToolType tool) { if (tool == ToolType.PICKAXE && (this.getBlock() == Blocks.REDSTONE_ORE || this.getBlock() == Blocks.REDSTONE_LAMP || this.getBlock() == Blocks.OBSIDIAN)) { return false; } return tool == getHarvestTool(state); - }*/ + } // TODO Call locations: Forge classes: ForgeHooksClient /** diff --git a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java index 55e94ee2..0f0c4182 100644 --- a/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java +++ b/patchwork-extensions-block/src/main/java/net/minecraftforge/common/extensions/IForgeBlockState.java @@ -25,6 +25,7 @@ import javax.annotation.Nullable; import net.minecraftforge.common.IPlantable; +import net.minecraftforge.common.ToolType; import net.minecraft.block.Block; import net.minecraft.block.BlockEntityProvider; @@ -149,7 +150,7 @@ default BlockEntity createTileEntity(BlockView world) { return patchwork$getForgeBlock().createTileEntity(getBlockState(), world); } - /* TODO IForgeBlockState#canHarvestBlock indirectly requires ToolType + /* TODO IForgeBlockState#canHarvestBlock indirectly requires ToolType */ /** * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed. * @@ -157,10 +158,10 @@ default BlockEntity createTileEntity(BlockView world) { * @param pos The block's current position * @param player The player damaging the block * @return True to spawn the drops - * + */ default boolean canHarvestBlock(BlockView world, BlockPos pos, PlayerEntity player) { return patchwork$getForgeBlock().canHarvestBlock(getBlockState(), world, pos, player); - }*/ + } /** * Called when a player removes a block. This is responsible for @@ -582,14 +583,14 @@ default boolean getWeakChanges(CollisionView world, BlockPos pos) { return patchwork$getForgeBlock().getWeakChanges(getBlockState(), world, pos); } - /* TODO IForgeBlockState#getHarvestTool needs ToolType + /* TODO IForgeBlockState#getHarvestTool needs ToolType */ /** * Queries the class of tool required to harvest this block, if null is returned * we assume that anything can harvest this block. - * + */ default ToolType getHarvestTool() { return patchwork$getForgeBlock().getHarvestTool(getBlockState()); - }*/ + } default int getHarvestLevel() { return patchwork$getForgeBlock().getHarvestLevel(getBlockState()); @@ -605,6 +606,7 @@ default boolean isToolEffective(ToolType tool) { }*/ /** + * TODO: do not bother implementing hooks, deprecated since 1.13 * Can return IExtendedBlockState. */ default BlockState getExtendedState(BlockView world, BlockPos pos) { @@ -612,6 +614,7 @@ default BlockState getExtendedState(BlockView world, BlockPos pos) { } /** + * TODO: do not bother implementing hooks, deprecated since 1.15 * Queries if this block should render in a given layer. * A custom {@link net.minecraft.client.render.model.BakedModel} can use {@link net.minecraftforge.client.MinecraftForgeClient#getRenderLayer()} to alter the model based on layer. */ diff --git a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java b/patchwork-extensions-block/src/main/java/net/minecraftforge/event/world/BlockEvent.java similarity index 90% rename from patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java rename to patchwork-extensions-block/src/main/java/net/minecraftforge/event/world/BlockEvent.java index 57308dd5..a46a5aef 100644 --- a/patchwork-events-world/src/main/java/net/minecraftforge/event/world/BlockEvent.java +++ b/patchwork-extensions-block/src/main/java/net/minecraftforge/event/world/BlockEvent.java @@ -21,16 +21,21 @@ import java.util.List; +import net.minecraftforge.common.extensions.IForgeBlockState; import net.minecraftforge.eventbus.api.Event; import net.minecraft.item.ItemStack; import net.minecraft.util.DefaultedList; import net.minecraft.block.BlockState; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; import net.minecraft.world.World; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; + public class BlockEvent extends Event { private final IWorld world; private final BlockPos pos; @@ -73,17 +78,14 @@ public BreakEvent(World world, BlockPos pos, BlockState state, PlayerEntity play this.player = player; this.exp = 0; - // TODO: BlockState#getExpDrop - - /* // Handle empty block or player unable to break block scenario - if (state == null || !ForgeHooks.canHarvestBlock(state, player, world, pos)) { + if (state == null || !BlockHarvestManager.canHarvestBlock(state, player, world, pos)) { this.exp = 0; } else { - int bonusLevel = EnchantmentHelper.getLevel(Enchantments.FORTUNE, player.getHeldItemMainhand()); - int silklevel = EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, player.getHeldItemMainhand()); - this.exp = state.getExpDrop(world, pos, bonusLevel, silklevel); - }*/ + int bonusLevel = EnchantmentHelper.getLevel(Enchantments.FORTUNE, player.getMainHandStack()); + int silklevel = EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, player.getMainHandStack()); + this.exp = ((IForgeBlockState) state).getExpDrop(world, pos, bonusLevel, silklevel); + } } public PlayerEntity getPlayer() { @@ -123,6 +125,7 @@ public boolean isCancelable() { * *

{@link #isSilkTouching} is set if this is considered a silk touch harvesting operation, vs a normal harvesting operation. Act accordingly.

*/ + @Deprecated public static class HarvestDropsEvent extends BlockEvent { private final int fortuneLevel; private final DefaultedList drops; diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java index 5f06ae28..be0317d9 100644 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockContext.java @@ -40,30 +40,30 @@ public static ThreadLocal createContext() { return ThreadLocal.withInitial(() -> BlockContext.CLEAN_MARKER); } - public static void setContext(ThreadLocal stack, Object value) { - Object oldValue = stack.get(); + public static void setContext(ThreadLocal context, Object value) { + Object oldValue = context.get(); if (oldValue != CLEAN_MARKER) { throw new IllegalStateException("The context is not clean."); } - stack.set(value); + context.set(value); } @SuppressWarnings("unchecked") - public static T getContext(ThreadLocal stack) { - Object oldValue = stack.get(); + public static T getContext(ThreadLocal context) { + Object oldValue = context.get(); if (oldValue == CLEAN_MARKER) { throw new IllegalStateException("The context is not set."); } - return (T) stack.get(); + return (T) context.get(); } @SuppressWarnings("unchecked") - public static T getContextOr(ThreadLocal stack, T defaultValue) { - Object value = stack.get(); + public static T getContextOr(ThreadLocal context, T defaultValue) { + Object value = context.get(); if (value == CLEAN_MARKER) { return defaultValue; @@ -73,14 +73,14 @@ public static T getContextOr(ThreadLocal stack, T defaultValue) { } @SuppressWarnings("unchecked") - public static T releaseContext(ThreadLocal stack) { - Object oldValue = stack.get(); + public static T releaseContext(ThreadLocal context) { + Object oldValue = context.get(); if (oldValue == CLEAN_MARKER) { throw new IllegalStateException("The context is not set."); } - stack.set(CLEAN_MARKER); + context.remove(); return (T) oldValue; } diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java new file mode 100644 index 00000000..349cd9a9 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/BlockHarvestManager.java @@ -0,0 +1,173 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.extensions.block; + +import java.util.Stack; + +import javax.annotation.Nonnull; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.ToolType; +import net.minecraftforge.common.extensions.IForgeBlockState; +import net.minecraftforge.common.extensions.IForgeItem; +import net.minecraftforge.event.world.BlockEvent; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.OreBlock; +import net.minecraft.block.RedstoneOreBlock; +import net.minecraft.block.SpawnerBlock; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.DefaultedList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; +import net.minecraft.world.EmptyBlockView; +import net.minecraft.world.GameMode; +import net.minecraft.world.World; + +public class BlockHarvestManager { + private static final ThreadLocal> expDrops = ThreadLocal.withInitial(Stack::new); + + private static void checkExpDropStack() { + if (expDrops.get().isEmpty()) { + throw new IllegalStateException("Patchwork's experience drop stack is not balanced!"); + } + } + + public static void pushExpDropStack(int exp) { + expDrops.get().push(exp); + } + + public static int getLastExpDrop() { + checkExpDropStack(); + return expDrops.get().lastElement(); + } + + public static int popExpDropStack() { + checkExpDropStack(); + return expDrops.get().pop(); + } + + /** + * Called by Mixins and ForgeHooks.canHarvestBlock, + * Requires harvest levels. + */ + @SuppressWarnings("unused") + public static boolean canHarvestBlock(@Nonnull BlockState state, @Nonnull PlayerEntity player, @Nonnull BlockView world, @Nonnull BlockPos pos) { + // state = state.getActualState(world, pos); + if (state.getMaterial().canBreakByHand()) { + return true; + } + + ItemStack stack = player.getMainHandStack(); + ToolType tool = null; // TODO: Unimplemented: ((IForgeBlockState) state).getHarvestTool(); + + if (stack.isEmpty() || tool == null) { + return player.isUsingEffectiveTool(state); + } + + int toolLevel = ((IForgeItem) stack.getItem()).getHarvestLevel(stack, tool, player, state); + + if (toolLevel < 0) { + return player.isUsingEffectiveTool(state); + } + + return toolLevel >= ((IForgeBlockState) state).getHarvestLevel(); + } + + public static boolean isVanillaBlock(Block block) { + if (block instanceof OreBlock || block instanceof RedstoneOreBlock) { + return true; + } + + if (block instanceof SpawnerBlock) { + return true; + } + + return false; + } + + /** + * Called by Mixin and ForgeHooks. + * @return experience dropped, -1 = block breaking is cancelled. + */ + public static int onBlockBreakEvent(World world, GameMode gameMode, ServerPlayerEntity player, BlockPos pos) { + // Logic from tryHarvestBlock for pre-canceling the event + boolean preCancelEvent = false; + + ItemStack itemstack = player.getMainHandStack(); + + if (!itemstack.isEmpty() && !itemstack.getItem().canMine(world.getBlockState(pos), world, pos, player)) { + preCancelEvent = true; + } + + // method_21701 => canMine + // Isn't the function really canNotMine? + + if (player.method_21701(world, pos, gameMode)) { + preCancelEvent = true; + } + + // Tell client the block is gone immediately then process events + if (world.getBlockEntity(pos) == null) { + player.networkHandler.sendPacket(new BlockUpdateS2CPacket(EmptyBlockView.INSTANCE, pos)); + } + + // Post the block break event + BlockState state = world.getBlockState(pos); + BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player); + event.setCanceled(preCancelEvent); + MinecraftForge.EVENT_BUS.post(event); + + // Handle if the event is canceled + if (event.isCanceled()) { + // Let the client know the block still exists + player.networkHandler.sendPacket(new BlockUpdateS2CPacket(world, pos)); + + // Update any block entity data for this block + BlockEntity entity = world.getBlockEntity(pos); + + if (entity != null) { + BlockEntityUpdateS2CPacket packet = entity.toUpdatePacket(); + + if (packet != null) { + player.networkHandler.sendPacket(packet); + } + } + + return -1; // Cancelled + } else { + return event.getExpToDrop(); + } + } + + // TODO: Leaving this unfired is intentional. See: https://github.com/MinecraftForge/MinecraftForge/issues/5828 + @Deprecated + public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { + BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(world, pos, state, fortune, dropChance, drops, player, silkTouch); + MinecraftForge.EVENT_BUS.post(event); + return event.getDropChance(); + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java new file mode 100644 index 00000000..68bd014e --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/impl/extensions/block/PatchworkBlock.java @@ -0,0 +1,26 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.extensions.block; + +import java.util.Random; + +public interface PatchworkBlock { + Random getRandom(); +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java index a93ee87d..7db399eb 100644 --- a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/MixinBlock.java @@ -21,12 +21,14 @@ import java.util.HashSet; import java.util.Map; +import java.util.Random; import java.util.Set; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import net.minecraftforge.common.ToolType; import net.minecraftforge.common.extensions.IForgeBlock; import net.minecraft.block.Block; @@ -40,6 +42,8 @@ @Mixin(Block.class) public class MixinBlock implements IForgeBlock { + protected Random RANDOM = new Random(); + @Shadow @Final private float slipperiness; @@ -54,6 +58,11 @@ public float getSlipperiness(BlockState state, CollisionView world, BlockPos pos return slipperiness; } + @Override + public ToolType getHarvestTool(BlockState state) { + throw new UnsupportedOperationException("Harvest levels not yet implemented"); // TODO implement getHarvestLevel + } + @Override public int getHarvestLevel(BlockState state) { throw new UnsupportedOperationException("Harvest levels not yet implemented"); // TODO implement getHarvestLevel, really sucks for vanilla blocks so i'm putting it off @@ -75,4 +84,9 @@ public Set getTags() { return this.cachedTags; } + + @Override + public Random getRandom() { + return RANDOM; + } } diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java new file mode 100644 index 00000000..5399b00a --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/flammable/MixinWorld.java @@ -0,0 +1,49 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.flammable; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import net.minecraftforge.common.extensions.IForgeBlockState; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.patchworkmc.impl.extensions.block.Signatures; + +@Mixin(World.class) +public abstract class MixinWorld { + //////////////////////////////////////////////////////// + /// doesAreaContainFireSource - IForgeBlock.isBurning + /// In 1.16.1, this patch is moved to Entity. + //////////////////////////////////////////////////////// + // This really should be included in the Fabric API! + // Block block = this.getBlockState(pooledMutable.set(o, p, q)).getBlock(); + // if (block == Blocks.FIRE || block == Blocks.LAVA) { + @Redirect(method = "doesAreaContainFireSource", at = @At(value = "INVOKE", target = Signatures.World_getBlockState, ordinal = 0)) + private BlockState patchwork_doesAreaContainFireSource_getBlockState(World world, BlockPos blockPos) { + BlockState blockState = world.getBlockState(blockPos); + boolean isBurning = ((IForgeBlockState) blockState).isBurning(world, blockPos); + return isBurning ? Blocks.FIRE.getDefaultState() : Blocks.WATER.getDefaultState(); + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java new file mode 100644 index 00000000..92640771 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinOreBlock.java @@ -0,0 +1,42 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +import java.util.Random; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import net.minecraftforge.common.extensions.IForgeBlock; + +import net.minecraft.block.BlockState; +import net.minecraft.block.OreBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.CollisionView; + +@Mixin(OreBlock.class) +public abstract class MixinOreBlock implements IForgeBlock { + @Shadow + protected abstract int getExperienceWhenMined(Random random); + + @Override + public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { + return silktouch == 0 ? getExperienceWhenMined(getRandom()) : 0; + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java new file mode 100644 index 00000000..fcaaab76 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinRedstoneOreBlock.java @@ -0,0 +1,36 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +import org.spongepowered.asm.mixin.Mixin; +import net.minecraftforge.common.extensions.IForgeBlock; + +import net.minecraft.block.BlockState; +import net.minecraft.block.RedstoneOreBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.CollisionView; + +@Mixin(RedstoneOreBlock.class) +public abstract class MixinRedstoneOreBlock implements IForgeBlock { + @Override + public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { + return silktouch == 0 ? 1 + getRandom().nextInt(5) : 0; + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java new file mode 100644 index 00000000..b3a3c19c --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinServerPlayerInteractionManager.java @@ -0,0 +1,149 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +import javax.annotation.Nullable; + +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import net.minecraftforge.common.extensions.IForgeBlockState; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.network.ServerPlayerInteractionManager; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.GameMode; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; + +import net.patchworkmc.impl.extensions.block.BlockContext; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; +import net.patchworkmc.impl.extensions.block.Signatures; + +@Mixin(ServerPlayerInteractionManager.class) +public abstract class MixinServerPlayerInteractionManager { + // removedByPlayer, canHarvestBlock + + @Unique + private boolean patchwork$removeBlock(BlockPos pos, boolean canHarvest) { + ServerPlayerInteractionManager me = (ServerPlayerInteractionManager) (Object) this; + BlockState state = me.world.getBlockState(pos); + boolean removed = ((IForgeBlockState) state).removedByPlayer(me.world, pos, me.player, canHarvest, me.world.getFluidState(pos)); + + if (removed) { + state.getBlock().onBroken(me.world, pos, state); + } + + return removed; + } + + ///////////////////////////////////// + /// Fire BlockEvent.BreakEvent, + /// get the amount of exp to drop. + ///////////////////////////////////// + @Shadow + public ServerWorld world; + @Shadow + public ServerPlayerEntity player; + @Shadow + private GameMode gameMode; + + @Inject(method = "tryBreakBlock", at = @At("HEAD"), cancellable = true) + private void hookBreakBlock(BlockPos pos, CallbackInfoReturnable callback) { + int exp = BlockHarvestManager.onBlockBreakEvent(world, gameMode, player, pos); + + if (exp < 0) { + callback.setReturnValue(false); + } else { + BlockHarvestManager.pushExpDropStack(exp); + } + } + + ///////////////////////////////////// + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_onBreak, ordinal = 0)) + private void patchwork$tryBreakBlock_onBreak(Block block, World world, BlockPos pos, BlockState state, PlayerEntity player) { + // Suppress this call + } + + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.ServerWorld_removeBlock, ordinal = 0)) + private boolean patchwork$tryBreakBlock_removeBlock(ServerWorld world, BlockPos pos, boolean bool) { + return true; // bypass if (bl && bl2) { + } + + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_onBroken, ordinal = 0)) + private void patchwork$tryBreakBlock_onBroken(Block block, IWorld world, BlockPos pos, BlockState state) { + // Suppress this call + } + + @Inject(method = "tryBreakBlock", at = @At(value = "JUMP", ordinal = 0, opcode = Opcodes.IFEQ, shift = Shift.AFTER), + slice = @Slice(from = @At(value = "INVOKE", target = Signatures.ServerPlayerInteractionManager_isCreative))) + private void patchwork$tryBreakBlock_isCreative(BlockPos pos, CallbackInfoReturnable cir) { + patchwork$removeBlock(pos, false); + } + + @Unique + private static final ThreadLocal tryBreakBlock_canHarvest = BlockContext.createContext(); // flag1 + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.ServerPlayerEntity_isUsingEffectiveTool, ordinal = 0)) + private boolean patchwork$tryBreakBlock_isUsingEffectiveTool(ServerPlayerEntity player, BlockState blockState, BlockPos pos) { + ServerPlayerInteractionManager me = (ServerPlayerInteractionManager) (Object) this; + boolean canHarvest = ((IForgeBlockState) blockState).canHarvestBlock(me.world, pos, player); + BlockContext.setContext(tryBreakBlock_canHarvest, canHarvest); + return true; // bypass if (bl && bl2) { + } + + @Redirect(method = "tryBreakBlock", at = @At(value = "INVOKE", target = Signatures.Block_afterBreak, ordinal = 0)) + private void patchwork$tryBreakBlock_afterBreak(Block block, World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) { + boolean canHarvest = BlockContext.releaseContext(tryBreakBlock_canHarvest); + boolean removed = patchwork$removeBlock(pos, canHarvest); + + if (removed && canHarvest) { + block.afterBreak(world, player, pos, state, blockEntity, stack); + } + + int exp = BlockHarvestManager.getLastExpDrop(); + + // isVanillaBlock exp Action + // Vanilla true xxx Let the vanilla method do the orb drop + // Fabric mod false == 0 Let the vanilla method do the orb drop + // Forge mod false >0 Do orb drop here + // Forge mod false <=0 Do nothing + if (removed && exp > 0 && !BlockHarvestManager.isVanillaBlock(block)) { + state.getBlock().dropExperience(world, pos, exp); + } + } + + @Inject(method = "tryBreakBlock", at = @At("RETURN")) + private void tryBreakBlock_return(BlockPos pos, CallbackInfoReturnable callback) { + BlockHarvestManager.popExpDropStack(); // Pop the expDrop stack at ALL return paths. + } +} diff --git a/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java new file mode 100644 index 00000000..40100d06 --- /dev/null +++ b/patchwork-extensions-block/src/main/java/net/patchworkmc/mixin/extensions/block/harvest/MixinSpawnerBlock.java @@ -0,0 +1,36 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.block.harvest; + +import org.spongepowered.asm.mixin.Mixin; +import net.minecraftforge.common.extensions.IForgeBlock; + +import net.minecraft.block.BlockState; +import net.minecraft.block.SpawnerBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.CollisionView; + +@Mixin(SpawnerBlock.class) +public abstract class MixinSpawnerBlock implements IForgeBlock { + @Override + public int getExpDrop(BlockState state, CollisionView world, BlockPos pos, int fortune, int silktouch) { + return 15 + getRandom().nextInt(15) + getRandom().nextInt(15); + } +} diff --git a/patchwork-extensions-block/src/main/resources/fabric.mod.json b/patchwork-extensions-block/src/main/resources/fabric.mod.json index 7ccd29e1..f1f22b18 100644 --- a/patchwork-extensions-block/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-block/src/main/resources/fabric.mod.json @@ -13,11 +13,14 @@ "depends": { "patchwork-api-base": "*", "patchwork-enum-hacks": "*", + "patchwork-extensions-item": "*", "patchwork-tooltype": "*" }, "mixins": [ "patchwork-extensions-block.mixins.json", - "patchwork-extensions-block-blockentity.mixins.json" + "patchwork-extensions-block-blockentity.mixins.json", + "patchwork-extensions-block-flammable.mixins.json", + "patchwork-extensions-block-harvest.mixins.json" ], "accessWidener": "patchwork-extensions-block.accesswidener", "custom": { diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json new file mode 100644 index 00000000..973ae16c --- /dev/null +++ b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-flammable.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.extensions.block.flammable", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinWorld" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json new file mode 100644 index 00000000..ee5c9c9c --- /dev/null +++ b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block-harvest.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.extensions.block.harvest", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinOreBlock", + "MixinRedstoneOreBlock", + "MixinServerPlayerInteractionManager", + "MixinSpawnerBlock" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener index 2188fab7..4b314a92 100644 --- a/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener +++ b/patchwork-extensions-block/src/main/resources/patchwork-extensions-block.accesswidener @@ -9,3 +9,5 @@ accessible field net/minecraft/item/AxeItem STRIPPED_BLOCKS Ljava/util/Map; # accessible method net/minecraft/block/PressurePlateBlock (Lnet/minecraft/block/PressurePlateBlock$ActivationRule;Lnet/minecraft/Block$Settings;)V accessible method net/minecraft/class_2440 (Lnet/minecraft/class_2440$class_2441;Lnet/minecraft/class_2248$class_2251;)V + +accessible method net/minecraft/block/Block dropExperience (Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;I)V diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 196740c8..df70a8cd 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -10,6 +10,7 @@ dependencies { implementation project(path: ':patchwork-events-lifecycle', configuration: 'dev') implementation project(path: ':patchwork-events-rendering', configuration: 'dev') implementation project(path: ':patchwork-events-world', configuration: 'dev') + implementation project(path: ':patchwork-extensions-block', configuration: 'dev') implementation project(path: ':patchwork-loot', configuration: 'dev') implementation project(path: ':patchwork-networking', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java index b2e22539..32463d2a 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -37,13 +37,18 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.loot.LootManager; import net.minecraft.loot.LootTable; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.GameMode; import net.minecraft.world.IWorld; import net.minecraft.world.MobSpawnerLogic; +import net.minecraft.world.World; import net.patchworkmc.impl.event.entity.EntityEvents; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; import net.patchworkmc.impl.loot.LootHooks; /* @@ -105,6 +110,10 @@ public static boolean onPlayerAttackTarget(PlayerEntity player, Entity target) { return EntityEvents.attackEntity(player, target); } + public static int onBlockBreakEvent(World world, GameMode gameType, ServerPlayerEntity entityPlayer, BlockPos pos) { + return BlockHarvestManager.onBlockBreakEvent(world, gameType, entityPlayer, pos); + } + @SuppressWarnings({ "rawtypes", "unused" }) private static ThreadLocal lootContext = LootHooks.lootContext; diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 27cd34c2..a7745064 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -48,7 +48,7 @@ import net.patchworkmc.impl.capability.CapabilityEvents; import net.patchworkmc.impl.event.entity.EntityEvents; import net.patchworkmc.impl.event.loot.LootEvents; -import net.patchworkmc.impl.event.world.WorldEvents; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. @@ -85,8 +85,10 @@ public static LootTable loadLootTable(Identifier name, LootTable table, LootMana return LootEvents.loadLootTable(name, table, lootTableManager); } + // Forge might remove BlockEvent.HarvestDropsEvent, which is replaced by the new loot modifier. + @Deprecated public static float fireBlockHarvesting(DefaultedList drops, World world, BlockPos pos, BlockState state, int fortune, float dropChance, boolean silkTouch, PlayerEntity player) { - return WorldEvents.fireBlockHarvesting(drops, world, pos, state, fortune, dropChance, silkTouch, player); + return BlockHarvestManager.fireBlockHarvesting(drops, world, pos, state, fortune, dropChance, silkTouch, player); } public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) { diff --git a/patchwork-god-classes/src/main/resources/fabric.mod.json b/patchwork-god-classes/src/main/resources/fabric.mod.json index 4fc551a4..48b20d56 100644 --- a/patchwork-god-classes/src/main/resources/fabric.mod.json +++ b/patchwork-god-classes/src/main/resources/fabric.mod.json @@ -18,9 +18,12 @@ "patchwork-api-base": "*", "patchwork-fml": "*", "patchwork-capabilities": "*", + "patchwork-events-entity": "*", "patchwork-events-input": "*", "patchwork-events-lifecycle": "*", "patchwork-events-rendering": "*", + "patchwork-events-world": "*", + "patchwork-extensions-block": "*", "patchwork-loot": "*" }, "custom": { From a86a1329043aa9ba7f81bfcac5b77296ebc3b178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Mon, 17 Aug 2020 05:41:20 +1000 Subject: [PATCH 49/73] Bugfix/mod init (#173) * Construct Forge mods at the correct place * Remove the unused Fabric mod entry * Remove debug outputs & add comments * Fix the order of events on client * Fix crashing on dedicated server * Fix FMLServerStartingEvent to accommodate the new mod loading procedure * Fix a mixin applied on the wrong side --- patchwork-dispatcher/build.gradle | 1 - .../java/net/patchworkmc/impl/Patchwork.java | 96 +++++++++++------ .../impl/PatchworkClientModLoader.java | 100 ++++++++++++++++++ .../mixin/MixinMinecraftClient.java | 54 ++++++++++ .../mixin/MixinMinecraftDedicatedServer.java | 28 +++-- .../src/main/resources/fabric.mod.json | 11 +- .../patchwork-dispatcher.mixins.json | 15 +++ .../impl/event/lifecycle/LifecycleEvents.java | 22 ++-- .../lifecycle/MixinIntegratedServer.java | 7 ++ .../event/lifecycle/MixinMinecraftClient.java | 5 - .../MixinMinecraftDedicatedServer.java | 8 +- .../patchwork-events-lifecycle.mixins.json | 1 - patchwork-events-rendering/build.gradle | 1 + .../impl/event/render/RenderEvents.java | 17 +-- .../src/main/resources/fabric.mod.json | 3 +- .../net/minecraftforge/fml/ModContainer.java | 4 + .../modelloader/ModelEventDispatcher.java | 10 -- 17 files changed, 290 insertions(+), 93 deletions(-) create mode 100644 patchwork-dispatcher/src/main/java/net/patchworkmc/impl/PatchworkClientModLoader.java create mode 100644 patchwork-dispatcher/src/main/java/net/patchworkmc/mixin/MixinMinecraftClient.java rename patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftServerSubclass.java => patchwork-dispatcher/src/main/java/net/patchworkmc/mixin/MixinMinecraftDedicatedServer.java (52%) create mode 100644 patchwork-dispatcher/src/main/resources/patchwork-dispatcher.mixins.json diff --git a/patchwork-dispatcher/build.gradle b/patchwork-dispatcher/build.gradle index e42a016b..db3030b2 100644 --- a/patchwork-dispatcher/build.gradle +++ b/patchwork-dispatcher/build.gradle @@ -6,6 +6,5 @@ dependencies { implementation project(path: ':patchwork-fml', configuration: 'dev') implementation project(path: ':patchwork-registries', configuration: 'dev') implementation project(path: ':patchwork-events-lifecycle', configuration: 'dev') - implementation project(path: ':patchwork-events-rendering', configuration: 'dev') implementation project(path: ':patchwork-model-loader', configuration: 'dev') } diff --git a/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java b/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java index f6a0b20b..0c05c5eb 100644 --- a/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java +++ b/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/Patchwork.java @@ -19,23 +19,23 @@ package net.patchworkmc.impl; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLDedicatedServerSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; @@ -45,40 +45,37 @@ import net.minecraftforge.fml.javafmlmod.FMLModContainer; import net.minecraftforge.registries.ForgeRegistries; -import net.minecraft.client.MinecraftClient; import net.minecraft.server.dedicated.DedicatedServer; -import net.fabricmc.api.ModInitializer; import net.fabricmc.loader.api.FabricLoader; import net.patchworkmc.api.ForgeInitializer; -import net.patchworkmc.impl.event.lifecycle.LifecycleEvents; -import net.patchworkmc.impl.event.render.RenderEvents; -import net.patchworkmc.impl.modelloader.ModelEventDispatcher; import net.patchworkmc.impl.registries.RegistryEventDispatcher; -public class Patchwork implements ModInitializer { +public class Patchwork { private static final Logger LOGGER = LogManager.getLogger(Patchwork.class); - private static void dispatch(Map mods, Event event) { + private static void dispatch(Collection mods, Event event) { dispatch(mods, container -> event); } - private static void dispatch(Map mods, Function provider) { - for (FMLModContainer container : mods.values()) { + /** + * Fire the specific event for all ModContainers on the {@link Mod.EventBusSubscriber.Bus.MOD} Event bus. + */ + private static void dispatch(Collection mods, Function provider) { + for (FMLModContainer container : mods) { ModLoadingContext.get().setActiveContainer(container, new FMLJavaModLoadingContext(container)); Event event = provider.apply(container); LOGGER.debug("Firing event for modid {} : {}", container.getModId(), event.toString()); - container.getEventBus().post(event); + container.patchwork$acceptEvent(event); LOGGER.debug("Fired event for modid {} : {}", container.getModId(), event.toString()); ModLoadingContext.get().setActiveContainer(null, "minecraft"); } } - @Override - public void onInitialize() { + public static void gatherAndInitializeMods() { ForgeRegistries.init(); Map mods = new HashMap<>(); @@ -102,6 +99,7 @@ public void onInitialize() { ModLoadingContext.get().setActiveContainer(container, new FMLJavaModLoadingContext(container)); try { + // TODO: Supposed to call "container.setMod()" here, but this requires a WIP Patchwork-Patcher feature. initializer.onForgeInitialize(); } catch (Throwable t) { if (error == null) { @@ -150,27 +148,65 @@ public void onInitialize() { ModList.get().setLoadedMods(mods.values()); // Send initialization events - dispatch(mods, new RegistryEvent.NewRegistry()); - RegistryEventDispatcher.dispatchRegistryEvents(event -> dispatch(mods, event)); - dispatch(mods, FMLCommonSetupEvent::new); - - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { - ModelEventDispatcher.fireModelRegistryEvent(); - dispatch(mods, container -> new FMLClientSetupEvent(MinecraftClient::getInstance, container)); - RenderEvents.registerEventDispatcher(event -> dispatch(mods, event)); - }); + dispatch(mods.values(), new RegistryEvent.NewRegistry()); + RegistryEventDispatcher.dispatchRegistryEvents(event -> dispatch(mods.values(), event)); + } - DistExecutor.runWhenOn(Dist.DEDICATED_SERVER, () -> () -> { - Object gameInstance = FabricLoader.getInstance().getGameInstance(); - Supplier supplier = () -> (DedicatedServer) gameInstance; + /** + * This is called on the ResourceLoader's thread when a resource loading happens, i.e. during client start-up or F3+T is pressed. + * Forge fires the FMLCommonSetupEvent and LifeCycleEvents(FMLClientSetupEvent and FMLDedicatedServerSetupEvent) on its own thread in parallel. Sequence cannot be guaranteed. + * IMPORTANT: In Patchwork, we fire all events on the main thread (Client Thread or Server Thread). + * @param lifeCycleEvent + * @param preSidedRunnable Fired before the LifeCycleEvent, on the main thread. Sequence cannot be guaranteed. + * @param postSidedRunnable Fired after the LifeCycleEvent, on the main thread. Sequence cannot be guaranteed. + */ + public static void loadMods(Function lifeCycleEvent, Consumer>> preSidedRunnable, Consumer>> postSidedRunnable) { + List mods = ModList.get().applyForEachModContainer(m -> (FMLModContainer) m).collect(Collectors.toList()); + + // Loading mod config + // TODO: Load client and common configs here + + // Mod setup: SETUP + dispatch(mods, FMLCommonSetupEvent::new); + // Mod setup: SIDED SETUP + preSidedRunnable.accept(c -> dispatch(mods, c.get())); + dispatch(mods, lifeCycleEvent); + postSidedRunnable.accept(c -> dispatch(mods, c.get())); + // Mod setup complete + } - dispatch(mods, container -> new FMLDedicatedServerSetupEvent(supplier, container)); - }); + /** + * In Patchwork, we fire all of following events on the main thread (Client Thread or Server Thread). + */ + public static void finishMods() { + List mods = ModList.get().applyForEachModContainer(m -> (FMLModContainer) m).collect(Collectors.toList()); + // Mod setup: ENQUEUE IMC dispatch(mods, InterModEnqueueEvent::new); + // Mod setup: PROCESS IMC dispatch(mods, InterModProcessEvent::new); - LifecycleEvents.setLoadCompleteCallback(() -> dispatch(mods, FMLLoadCompleteEvent::new)); + // Mod setup: Final completion + dispatch(mods, FMLLoadCompleteEvent::new); + // Freezing data, TODO: do we need freezing? + // GameData.freezeData(); + // NetworkRegistry.lock(); + } + + public static void beginServerModLoading() { + Object gameInstance = FabricLoader.getInstance().getGameInstance(); + Supplier supplier = () -> (DedicatedServer) gameInstance; + + LOGGER.debug("Patchwork Dedicated Server Mod Loader: Start mod loading."); + Patchwork.gatherAndInitializeMods(); + Patchwork.loadMods(container -> new FMLDedicatedServerSetupEvent(supplier, container), dummy -> { }, dummy -> { }); + } + + public static void endOfServerModLoading() { + LOGGER.debug("Patchwork Dedicated Server Mod Loader: Finish mod loading."); + Patchwork.finishMods(); + LOGGER.debug("Patchwork Dedicated Server Mod Loader: Complete mod loading"); + // Assume there's no error. MinecraftForge.EVENT_BUS.start(); } } diff --git a/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/PatchworkClientModLoader.java b/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/PatchworkClientModLoader.java new file mode 100644 index 00000000..6adb4ba3 --- /dev/null +++ b/patchwork-dispatcher/src/main/java/net/patchworkmc/impl/PatchworkClientModLoader.java @@ -0,0 +1,100 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; + +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourceReloadListener; +import net.minecraft.util.profiler.Profiler; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.resource.ClientBuiltinResourcePackProvider; +import net.minecraft.client.resource.ClientResourcePackProfile; +import net.minecraft.resource.ReloadableResourceManager; +import net.minecraft.resource.ResourcePackManager; + +public class PatchworkClientModLoader { + private static final Logger LOGGER = LogManager.getLogger(PatchworkClientModLoader.class); + private static boolean loading; + private static MinecraftClient mc; + + public static void begin(final MinecraftClient minecraft, final ResourcePackManager defaultResourcePacks, + final ReloadableResourceManager mcResourceManager, ClientBuiltinResourcePackProvider metadataSerializer) { + loading = true; + PatchworkClientModLoader.mc = minecraft; + Patchwork.gatherAndInitializeMods(); + mcResourceManager.registerListener(PatchworkClientModLoader::onReload); + } + + /** + * @param syncExecutor The main thread executor + */ + private static CompletableFuture onReload(final ResourceReloadListener.Synchronizer stage, final ResourceManager resourceManager, + final Profiler prepareProfiler, final Profiler executeProfiler, final Executor asyncExecutor, final Executor syncExecutor) { + return CompletableFuture.runAsync(() -> startModLoading(syncExecutor), asyncExecutor) + .thenCompose(stage::whenPrepared) + .thenRunAsync(() -> finishModLoading(syncExecutor), asyncExecutor); + } + + private static void startModLoading(Executor mainThreadExecutor) { + LOGGER.debug("Patchwork Client Mod Loader: Start mod loading."); + mainThreadExecutor.execute(() -> Patchwork.loadMods(container -> new FMLClientSetupEvent(() -> PatchworkClientModLoader.mc, container), + PatchworkClientModLoader::preSidedRunnable, PatchworkClientModLoader::postSidedRunnable)); + } + + private static void preSidedRunnable(Consumer> perModContainerEventProcessor) { + perModContainerEventProcessor.accept(ModelRegistryEvent::new); + } + + private static void postSidedRunnable(Consumer> perModContainerEventProcessor) { + } + + private static void finishModLoading(Executor executor) { + LOGGER.debug("Patchwork Client Mod Loader: Finish mod loading."); + Patchwork.finishMods(); + loading = false; + // reload game settings on main thread + executor.execute(() -> mc.options.load()); + } + + /** + * @return true if an error occurred so that we can cancel the normal title screen. + */ + public static boolean completeModLoading() { + LOGGER.debug("Patchwork Client Mod Loader: Complete mod loading"); + // Assume there's no error. + MinecraftForge.EVENT_BUS.start(); + return false; + } + + // TODO: Reserved for future use + public static void onResourceReloadComplete(boolean errorFree) { + } +} diff --git a/patchwork-dispatcher/src/main/java/net/patchworkmc/mixin/MixinMinecraftClient.java b/patchwork-dispatcher/src/main/java/net/patchworkmc/mixin/MixinMinecraftClient.java new file mode 100644 index 00000000..633c7532 --- /dev/null +++ b/patchwork-dispatcher/src/main/java/net/patchworkmc/mixin/MixinMinecraftClient.java @@ -0,0 +1,54 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin; + +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.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.resource.ReloadableResourceManager; + +import net.patchworkmc.impl.PatchworkClientModLoader; + +@Mixin(MinecraftClient.class) +public abstract class MixinMinecraftClient { + @Shadow + private ReloadableResourceManager resourceManager; + + @Inject(method = "init", at = @At(value = "INVOKE", shift = Shift.BEFORE, ordinal = 0, target = "net/minecraft/resource/ResourcePackManager.scanPacks()V")) + private void initForgeModsOnClient(CallbackInfo ci) { + MinecraftClient me = (MinecraftClient) (Object) this; + PatchworkClientModLoader.begin(me, me.getResourcePackManager(), resourceManager, me.getResourcePackDownloader()); + } + + // this.setOverlay(new SplashScreen(this, this.resourceManager.beginInitialMonitoredReload(SystemUtil.getServerWorkerExecutor(), this, voidFuture), () -> { + // if (SharedConstants.isDevelopment) this.checkGameData(); + // + if (net.minecraftforge.fml.client.ClientModLoader.completeModLoading()) return; // Do not overwrite the error sceen + // + // Show either ConnectScreen or TitleScreen + // } + @Inject(method = "method_18504", at = @At("RETURN")) + private void onResourceReloadComplete(CallbackInfo ci) { + PatchworkClientModLoader.onResourceReloadComplete(!PatchworkClientModLoader.completeModLoading()); + } +} diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftServerSubclass.java b/patchwork-dispatcher/src/main/java/net/patchworkmc/mixin/MixinMinecraftDedicatedServer.java similarity index 52% rename from patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftServerSubclass.java rename to patchwork-dispatcher/src/main/java/net/patchworkmc/mixin/MixinMinecraftDedicatedServer.java index ec0edf93..f2f873cf 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftServerSubclass.java +++ b/patchwork-dispatcher/src/main/java/net/patchworkmc/mixin/MixinMinecraftDedicatedServer.java @@ -17,29 +17,27 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.patchworkmc.mixin.event.lifecycle; +package net.patchworkmc.mixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.MinecraftDedicatedServer; -import net.minecraft.server.integrated.IntegratedServer; -import net.patchworkmc.impl.event.lifecycle.LifecycleEvents; +import net.patchworkmc.impl.Patchwork; -/** - * Mixes into {@link IntegratedServer} and {@link MinecraftDedicatedServer} in order to implement - * {@link net.minecraftforge.fml.event.server.FMLServerStartingEvent}. This event fires right before the implementations - * return true from setupServer. Returning false from the callback cancels the - * server's startup, however, it's important to note that this event isn't actually cancellable in Forge! - */ -@Mixin({IntegratedServer.class, MinecraftDedicatedServer.class}) -public class MixinMinecraftServerSubclass { - @Inject(method = "setupServer", at = @At("RETURN")) - private void hookSetupEnd(CallbackInfoReturnable callback) { - LifecycleEvents.handleServerStarting((MinecraftServer) (Object) this); +@Mixin(MinecraftDedicatedServer.class) +public abstract class MixinMinecraftDedicatedServer { + @Inject(method = "setupServer", at = @At(value = "INVOKE", shift = Shift.AFTER, ordinal = 0, target = "org/apache/logging/log4j/Logger.info(Ljava/lang/String;)V")) + private void initForgeModsOnServer(CallbackInfoReturnable ci) { + Patchwork.beginServerModLoading(); + } + + @Inject(method = "setupServer", at = @At(value = "NEW", shift = Shift.BEFORE, ordinal = 0, target = "net/minecraft/server/dedicated/DedicatedPlayerManager")) + private void endOfModLoading(CallbackInfoReturnable ci) { + Patchwork.endOfServerModLoading(); } } diff --git a/patchwork-dispatcher/src/main/resources/fabric.mod.json b/patchwork-dispatcher/src/main/resources/fabric.mod.json index 5cd7f2a2..9fec4d55 100644 --- a/patchwork-dispatcher/src/main/resources/fabric.mod.json +++ b/patchwork-dispatcher/src/main/resources/fabric.mod.json @@ -10,17 +10,16 @@ "license": "LGPL-2.1-only", "icon": "assets/patchwork-dispatcher/icon.png", "environment": "*", - "entrypoints": { - "main": [ - "net.patchworkmc.impl.Patchwork" - ] - }, "depends": { "patchwork-api-base": "*", "patchwork-fml": "*", "patchwork-registries": "*", - "patchwork-events-lifecycle": "*" + "patchwork-events-lifecycle": "*", + "patchwork-model-loader": "*" }, + "mixins": [ + "patchwork-dispatcher.mixins.json" + ], "custom": { "modmenu:api": true, "modmenu:parent": "patchwork" diff --git a/patchwork-dispatcher/src/main/resources/patchwork-dispatcher.mixins.json b/patchwork-dispatcher/src/main/resources/patchwork-dispatcher.mixins.json new file mode 100644 index 00000000..90025d4b --- /dev/null +++ b/patchwork-dispatcher/src/main/resources/patchwork-dispatcher.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin", + "compatibilityLevel": "JAVA_8", + "server": [ + "MixinMinecraftDedicatedServer" + ], + "client": [ + "MixinMinecraftClient" + ], + "injectors": { + "defaultRequire": 1, + "maxShiftBy": 2 + } +} diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java index 1e4646f4..b1bc0e4e 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/impl/event/lifecycle/LifecycleEvents.java @@ -37,6 +37,8 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.MinecraftDedicatedServer; +import net.minecraft.server.integrated.IntegratedServer; import net.minecraft.world.World; import net.fabricmc.api.ModInitializer; @@ -45,8 +47,6 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; public class LifecycleEvents implements ModInitializer { - private static Runnable loadCompleteCallback; - public static void fireWorldTickEvent(TickEvent.Phase phase, World world) { LogicalSide side = world.isClient() ? LogicalSide.CLIENT : LogicalSide.SERVER; TickEvent.WorldTickEvent event = new TickEvent.WorldTickEvent(side, phase, world); @@ -71,12 +71,20 @@ public static void firePlayerTickEvent(TickEvent.Phase phase, PlayerEntity playe MinecraftForge.EVENT_BUS.post(new TickEvent.PlayerTickEvent(phase, player)); } - public static void handleServerStarting(final MinecraftServer server) { + /** + * Mixes into {@link IntegratedServer} and {@link MinecraftDedicatedServer} in order to implement + * {@link net.minecraftforge.fml.event.server.FMLServerStartingEvent}. This event fires right before the implementations + * return true from setupServer. Returning false from the callback cancels the + * server's startup, however, it's important to note that this event isn't actually cancellable in Forge! + */ + public static boolean handleServerStarting(final MinecraftServer server) { // TODO: Forge loads language data here. I haven't found any mods that use this behavior. if (MinecraftForge.EVENT_BUS.post(new FMLServerStartingEvent(server))) { throw new UnsupportedOperationException("FMLServerStartingEvent is not cancellable!"); } + + return true; } public static void handleServerStarted(final MinecraftServer server) { @@ -97,14 +105,6 @@ private static Path getServerConfigPath(final MinecraftServer server) { return serverConfig; } - public static void setLoadCompleteCallback(Runnable callback) { - loadCompleteCallback = callback; - } - - public static void handleLoadComplete() { - loadCompleteCallback.run(); - } - public static void handleServerStopped(final MinecraftServer server) { MinecraftForge.EVENT_BUS.post(new FMLServerStoppedEvent(server)); ServerLifecycleHooks.currentServer = null; diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinIntegratedServer.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinIntegratedServer.java index 7ad7fcd9..aee17cf2 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinIntegratedServer.java +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinIntegratedServer.java @@ -22,6 +22,7 @@ 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.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.server.MinecraftServer; @@ -35,4 +36,10 @@ public class MixinIntegratedServer { private void onServerAboutToStart(CallbackInfoReturnable cir) { LifecycleEvents.handleServerAboutToStart((MinecraftServer) (Object) this); } + + @Inject(method = "setupServer", at = @At(value = "RETURN", ordinal = 0), cancellable = true, slice = + @Slice(from = @At(value = "INVOKE", target = "net/minecraft/server/MinecraftServer.setMotd(Ljava/lang/String;)V"))) + private void handleServerStarting(CallbackInfoReturnable cir) { + cir.setReturnValue(LifecycleEvents.handleServerStarting((MinecraftServer) (Object) this)); + } } diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftClient.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftClient.java index 8e51e2f6..88bd6bf4 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftClient.java +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftClient.java @@ -51,11 +51,6 @@ private void hookClientTickEnd(CallbackInfo info) { LifecycleEvents.fireClientTickEvent(TickEvent.Phase.END); } - @Inject(method = "init", at = @At("RETURN")) - private void hookClientInit(CallbackInfo ci) { - LifecycleEvents.handleLoadComplete(); - } - @Shadow @Final private RenderTickCounter renderTickCounter; diff --git a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftDedicatedServer.java b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftDedicatedServer.java index 777948bc..b0b51ed3 100644 --- a/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftDedicatedServer.java +++ b/patchwork-events-lifecycle/src/main/java/net/patchworkmc/mixin/event/lifecycle/MixinMinecraftDedicatedServer.java @@ -22,6 +22,7 @@ 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.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.server.MinecraftServer; @@ -33,7 +34,12 @@ public class MixinMinecraftDedicatedServer { @Inject(method = "setupServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/UserCache;setUseRemote(Z)V", shift = At.Shift.AFTER)) private void onServerAboutToStart(CallbackInfoReturnable cir) { - LifecycleEvents.handleLoadComplete(); // This is a "multithreaded" event that would be called around this time. LifecycleEvents.handleServerAboutToStart((MinecraftServer) (Object) this); } + + @Inject(method = "setupServer", at = @At(value = "RETURN", ordinal = 0), cancellable = true, slice = + @Slice(from = @At(value = "INVOKE", target = "net/minecraft/item/Item.appendStacks(Lnet/minecraft/item/ItemGroup;Lnet/minecraft/util/DefaultedList;)V"))) + private void handleServerStarting(CallbackInfoReturnable cir) { + cir.setReturnValue(LifecycleEvents.handleServerStarting((MinecraftServer) (Object) this)); + } } diff --git a/patchwork-events-lifecycle/src/main/resources/patchwork-events-lifecycle.mixins.json b/patchwork-events-lifecycle/src/main/resources/patchwork-events-lifecycle.mixins.json index 3aeabb4d..91c77547 100644 --- a/patchwork-events-lifecycle/src/main/resources/patchwork-events-lifecycle.mixins.json +++ b/patchwork-events-lifecycle/src/main/resources/patchwork-events-lifecycle.mixins.json @@ -3,7 +3,6 @@ "package": "net.patchworkmc.mixin.event.lifecycle", "compatibilityLevel": "JAVA_8", "mixins": [ - "MixinMinecraftServerSubclass", "MixinPlayerEntity", "MixinServerWorld" ], diff --git a/patchwork-events-rendering/build.gradle b/patchwork-events-rendering/build.gradle index 68e8173b..16784a5e 100644 --- a/patchwork-events-rendering/build.gradle +++ b/patchwork-events-rendering/build.gradle @@ -3,4 +3,5 @@ version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-fml', configuration: 'dev') } diff --git a/patchwork-events-rendering/src/main/java/net/patchworkmc/impl/event/render/RenderEvents.java b/patchwork-events-rendering/src/main/java/net/patchworkmc/impl/event/render/RenderEvents.java index e70e9b83..c00d6e3f 100644 --- a/patchwork-events-rendering/src/main/java/net/patchworkmc/impl/event/render/RenderEvents.java +++ b/patchwork-events-rendering/src/main/java/net/patchworkmc/impl/event/render/RenderEvents.java @@ -20,13 +20,12 @@ package net.patchworkmc.impl.event.render; import java.util.Set; -import java.util.function.Consumer; import net.minecraftforge.client.event.ColorHandlerEvent; import net.minecraftforge.client.event.DrawBlockHighlightEvent; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.ModLoader; import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.color.item.ItemColors; @@ -39,26 +38,20 @@ import net.minecraft.util.hit.HitResult; public class RenderEvents { - private static Consumer eventDispatcher; - - public static void registerEventDispatcher(Consumer dispatcher) { - eventDispatcher = dispatcher; - } - public static void onBlockColorsInit(BlockColors blockColors) { - eventDispatcher.accept(new ColorHandlerEvent.Block(blockColors)); + ModLoader.get().postEvent(new ColorHandlerEvent.Block(blockColors)); } public static void onItemColorsInit(ItemColors itemColors, BlockColors blockColors) { - eventDispatcher.accept(new ColorHandlerEvent.Item(itemColors, blockColors)); + ModLoader.get().postEvent(new ColorHandlerEvent.Item(itemColors, blockColors)); } public static void onTextureStitchPre(SpriteAtlasTexture spriteAtlasTexture, Set set) { - eventDispatcher.accept(new TextureStitchEvent.Pre(spriteAtlasTexture, set)); + ModLoader.get().postEvent(new TextureStitchEvent.Pre(spriteAtlasTexture, set)); } public static void onTextureStitchPost(SpriteAtlasTexture spriteAtlasTexture) { - eventDispatcher.accept(new TextureStitchEvent.Post(spriteAtlasTexture)); + ModLoader.get().postEvent(new TextureStitchEvent.Post(spriteAtlasTexture)); } /** diff --git a/patchwork-events-rendering/src/main/resources/fabric.mod.json b/patchwork-events-rendering/src/main/resources/fabric.mod.json index 8ad3995c..d8f37a2d 100644 --- a/patchwork-events-rendering/src/main/resources/fabric.mod.json +++ b/patchwork-events-rendering/src/main/resources/fabric.mod.json @@ -13,7 +13,8 @@ "PatchworkMC" ], "depends": { - "patchwork-api-base": "*" + "patchwork-api-base": "*", + "patchwork-fml": "*" }, "mixins": [ "patchwork-events-rendering.mixins.json" diff --git a/patchwork-fml/src/main/java/net/minecraftforge/fml/ModContainer.java b/patchwork-fml/src/main/java/net/minecraftforge/fml/ModContainer.java index 2a4ad48f..447aed30 100644 --- a/patchwork-fml/src/main/java/net/minecraftforge/fml/ModContainer.java +++ b/patchwork-fml/src/main/java/net/minecraftforge/fml/ModContainer.java @@ -85,4 +85,8 @@ public final net.fabricmc.loader.api.ModContainer getParent() { protected void acceptEvent(Event e) { } + + public final void patchwork$acceptEvent(Event e) { + this.acceptEvent(e); + } } diff --git a/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/ModelEventDispatcher.java b/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/ModelEventDispatcher.java index 1924e55c..1afc38d1 100644 --- a/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/ModelEventDispatcher.java +++ b/patchwork-model-loader/src/main/java/net/patchworkmc/impl/modelloader/ModelEventDispatcher.java @@ -22,7 +22,6 @@ import java.util.Map; import net.minecraftforge.client.event.ModelBakeEvent; -import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.fml.ModLoader; @@ -31,15 +30,6 @@ import net.minecraft.util.Identifier; public class ModelEventDispatcher { - /** - * In Forge, ModelRegistryEvent is fired in parallel with FMLClientSetupEvent. - * Here we fire ModelRegistryEvent before FMLClientSetupEvent. - * The official forge does not set the ModLoadingContext here, so this should be fine. - */ - public static void fireModelRegistryEvent() { - ModLoader.get().postEvent(new ModelRegistryEvent()); - } - public static void onModelBake(BakedModelManager modelManager, Map modelRegistry, ModelLoader modelLoader) { ModLoader.get().postEvent(new ModelBakeEvent(modelManager, modelRegistry, modelLoader)); modelLoader.onPostBakeEvent(modelRegistry); From 494367dbb33cfa5db1f3e58b5981ed863faf6021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Tue, 18 Aug 2020 07:14:37 +1000 Subject: [PATCH 50/73] Feature/extensions blockentity (#162) * Add extensions-blockentity module * implements IForgeTileEntity.onLoad and onChunkUnloaded * Impl IForgeTileEntity.getTileData() * Implements IForgeTileEntity.getRenderBoundingBox and canRenderBreaking * Add FastTESR support and Forge's BER registration method * Add BlockEntityRender register method to the god class, Add readme * Fix potential ThreadLocal memory leakage * Update patchwork-extensions-blockentity/src/main/java/net/minecraftforge/common/extensions/IForgeTileEntity.java Co-authored-by: Glitch * Apply suggestions * Revert "Apply suggestions" This reverts commit 51886131bf789f3d37d36c546564dd49f3437440. * Apply suggestions Co-authored-by: Glitch --- patchwork-extensions-blockentity/build.gradle | 6 + patchwork-extensions-blockentity/readme.md | 4 + .../animation/TileEntityRendererFast.java | 96 +++++++++ .../common/extensions/IForgeTileEntity.java | 200 ++++++++++++++++++ .../ForgeBlockEntityRenderDispatcher.java | 30 +++ .../blockentity/ForgeBlockEntityRenderer.java | 29 +++ .../blockentity/MixinBlockEntity.java | 65 ++++++ .../MixinBlockEntityRenderDispatcher.java | 43 ++++ .../blockentity/MixinBlockEntityRenderer.java | 32 +++ .../MixinClientPlayNetworkHandler.java | 121 +++++++++++ .../extensions/blockentity/MixinWorld.java | 178 ++++++++++++++++ .../blockentity/MixinWorldRenderer.java | 99 +++++++++ .../patchwork-extensions-block/icon.png | Bin 0 -> 22738 bytes .../src/main/resources/fabric.mod.json | 23 ++ ...tchwork-extensions-blockentity.mixins.json | 18 ++ patchwork-god-classes/build.gradle | 1 + .../fml/client/registry/ClientRegistry.java | 40 ++++ settings.gradle | 1 + 18 files changed, 986 insertions(+) create mode 100644 patchwork-extensions-blockentity/build.gradle create mode 100644 patchwork-extensions-blockentity/readme.md create mode 100644 patchwork-extensions-blockentity/src/main/java/net/minecraftforge/client/model/animation/TileEntityRendererFast.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/minecraftforge/common/extensions/IForgeTileEntity.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderDispatcher.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderer.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntity.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderDispatcher.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderer.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinClientPlayNetworkHandler.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinWorld.java create mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinWorldRenderer.java create mode 100644 patchwork-extensions-blockentity/src/main/resources/assets/patchwork-extensions-block/icon.png create mode 100644 patchwork-extensions-blockentity/src/main/resources/fabric.mod.json create mode 100644 patchwork-extensions-blockentity/src/main/resources/patchwork-extensions-blockentity.mixins.json create mode 100644 patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java diff --git a/patchwork-extensions-blockentity/build.gradle b/patchwork-extensions-blockentity/build.gradle new file mode 100644 index 00000000..500f2044 --- /dev/null +++ b/patchwork-extensions-blockentity/build.gradle @@ -0,0 +1,6 @@ +archivesBaseName = "patchwork-extensions-blockentity" +version = getSubprojectVersion(project, "0.1.0") + +dependencies { + compile project(path: ':patchwork-capabilities', configuration: 'dev') +} diff --git a/patchwork-extensions-blockentity/readme.md b/patchwork-extensions-blockentity/readme.md new file mode 100644 index 00000000..0db3d657 --- /dev/null +++ b/patchwork-extensions-blockentity/readme.md @@ -0,0 +1,4 @@ +This module implements: +1. Everything in `IForgeTileEntity` +2. Hooks for BlockEntityRenderer registration. (We cannot reuse Fabric hooks for this, the Fabric registration event is fired much earlier than Forge's) +3. FastTESR in 1.14.4, will be removed and replaced with vanilla BlockEntityRenderer in 1.15 and above. \ No newline at end of file diff --git a/patchwork-extensions-blockentity/src/main/java/net/minecraftforge/client/model/animation/TileEntityRendererFast.java b/patchwork-extensions-blockentity/src/main/java/net/minecraftforge/client/model/animation/TileEntityRendererFast.java new file mode 100644 index 00000000..f68041d9 --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/minecraftforge/client/model/animation/TileEntityRendererFast.java @@ -0,0 +1,96 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.model.animation; + +import com.mojang.blaze3d.platform.GlStateManager; +import org.lwjgl.opengl.GL11; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.DiffuseLighting; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.block.entity.BlockEntity; + +import net.patchworkmc.impl.extensions.blockentity.ForgeBlockEntityRenderer; + +/** + * TODO: The FastTESR is removed in 1.15. + * The new vanilla BlockEntityRender is identical to Forge's FastTESR, see the "Disadvantages" section. + * Patchwork API will not implement proper batch rendering for FastTESR, + * however, FastTESRs can still be displayed. + * + *

A special case which can be batched with other + * renderers that are also instances of this class. + * + *

Advantages: + *

    + *
  • All batched renderers are drawn with a single draw call
  • + *
  • Renderers have their vertices depth sorted for better translucency + * support
  • + *
+ * + *

Disadvantages: + *

    + *
  • OpenGL operations are not permitted
  • + *
  • All renderers must use the same {@link VertexFormat} + * ({@link VertexFormats#POSITION_COLOR_TEXTURE_LIGHT_NORMAL})
  • + *
+ * + * @param The type of {@link BlockEntity} being rendered. + */ +@Deprecated +public abstract class TileEntityRendererFast extends BlockEntityRenderer implements ForgeBlockEntityRenderer { + @Override + public final void render(T te, double x, double y, double z, float partialTicks, int destroyStage) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + this.bindTexture(SpriteAtlasTexture.BLOCK_ATLAS_TEX); + DiffuseLighting.disable(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableBlend(); + GlStateManager.disableCull(); + + if (MinecraftClient.isAmbientOcclusionEnabled()) { + GlStateManager.shadeModel(GL11.GL_SMOOTH); + } else { + GlStateManager.shadeModel(GL11.GL_FLAT); + } + + buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR_UV_LMAP); + + renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer); + buffer.setOffset(0, 0, 0); + + tessellator.draw(); + + DiffuseLighting.enable(); + } + + /** + * Draw this renderer to the passed {@link BufferBuilder}. DO + * NOT draw to any buffers other than the one passed, or use any OpenGL + * operations as they will not be applied when this renderer is batched. + */ + @Override + public abstract void renderTileEntityFast(T te, double x, double y, double z, float partialTicks, int destroyStage, BufferBuilder buffer); +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/minecraftforge/common/extensions/IForgeTileEntity.java b/patchwork-extensions-blockentity/src/main/java/net/minecraftforge/common/extensions/IForgeTileEntity.java new file mode 100644 index 00000000..206cd314 --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/minecraftforge/common/extensions/IForgeTileEntity.java @@ -0,0 +1,200 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.common.extensions; + +import net.minecraftforge.common.capabilities.ICapabilitySerializable; + +import net.minecraft.block.AbstractSignBlock; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.ChestBlock; +import net.minecraft.block.EnderChestBlock; +import net.minecraft.block.SkullBlock; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +public interface IForgeTileEntity extends ICapabilitySerializable { + /** + * Sometimes default render bounding box: infinite in scope. Used to control rendering on {@link TileEntitySpecialRenderer}. + */ + Box INFINITE_EXTENT_AABB = new Box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + + default BlockEntity getTileEntity() { + return (BlockEntity) this; + } + + @Override + default void deserializeNBT(CompoundTag nbt) { + getTileEntity().fromTag(nbt); + } + + @Override + default CompoundTag serializeNBT() { + CompoundTag ret = new CompoundTag(); + getTileEntity().toTag(ret); + return ret; + } + + /** + * Called when you receive a TileEntityData packet for the location this + * TileEntity is currently in. On the client, the NetworkManager will always + * be the remote server. On the server, it will be whomever is responsible for + * sending the packet. + * + * @param net The NetworkManager the packet originated from + * @param pkt The data packet + */ + default void onDataPacket(ClientConnection net, BlockEntityUpdateS2CPacket pkt) { + } + + /** + * Called when the chunk's TE update tag, gotten from {@link #getUpdateTag()}, is received on the client. + * + *

Used to handle this tag in a special way. By default this simply calls {@link #readFromNBT(NBTTagCompound)}. + * + * @param tag The {@link NBTTagCompound} sent from {@link #getUpdateTag()} + */ + default void handleUpdateTag(CompoundTag tag) { + getTileEntity().fromTag(tag); + } + + /** + * Gets a {@link NBTTagCompound} that can be used to store custom data for this tile entity. + * It will be written, and read from disc, so it persists over world saves. + * + * @return A compound tag for custom data + */ + CompoundTag getTileData(); + + default void onChunkUnloaded() { + } + + /** + * Called when this is first added to the world (by {@link World#addTileEntity(TileEntity)}). + * Override instead of adding {@code if (firstTick)} stuff in update. + */ + default void onLoad() { + requestModelDataUpdate(); + } + + /** + * Return an {@link AxisAlignedBB} that controls the visible scope of a {@link TileEntitySpecialRenderer} associated with this {@link TileEntity} + * Defaults to the collision bounding box {@link Block#getCollisionBoundingBoxFromPool(World, int, int, int)} associated with the block + * at this location. + * + * @return an appropriately size {@link AxisAlignedBB} for the {@link TileEntity} + */ + @Environment(EnvType.CLIENT) + default Box getRenderBoundingBox() { + Box bb = INFINITE_EXTENT_AABB; + BlockState state = getTileEntity().getCachedState(); + Block block = state.getBlock(); + BlockPos pos = getTileEntity().getPos(); + + if (block == Blocks.ENCHANTING_TABLE) { + bb = new Box(pos, pos.add(1, 1, 1)); + } else if (block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { + bb = new Box(pos.add(-1, 0, -1), pos.add(2, 2, 2)); + } else if (block == Blocks.STRUCTURE_BLOCK) { + bb = INFINITE_EXTENT_AABB; + } else if (block != null && block != Blocks.BEACON) { + Box cbb = null; + + try { + cbb = state.getCollisionShape(getTileEntity().getWorld(), pos).getBoundingBox().offset(pos); + } catch (Exception e) { + // We have to capture any exceptions that may occur here because BUKKIT servers like to send + // the tile entity data BEFORE the chunk data, you know, the OPPOSITE of what vanilla does! + // So we can not GUARANTEE that the world state is the real state for the block... + // So, once again in the long line of US having to accommodate BUKKIT breaking things, + // here it is, assume that the TE is only 1 cubic block. Problem with this is that it may + // cause the TileEntity renderer to error further down the line! But alas, nothing we can do. + cbb = new Box(pos.add(-1, 0, -1), pos.add(1, 1, 1)); + } + + if (cbb != null) { + bb = cbb; + } + } + + return bb; + } + + /** + * Checks if this tile entity knows how to render its 'breaking' overlay effect. + * If this returns true, The TileEntitySpecialRenderer will be called again with break progress set. + * + * @return True to re-render tile with breaking effect. + */ + default boolean canRenderBreaking() { + Block block = getTileEntity().getCachedState().getBlock(); + return (block instanceof ChestBlock + || block instanceof EnderChestBlock + || block instanceof AbstractSignBlock + || block instanceof SkullBlock); + } + + /** + * TODO: Deprecated, in Patchwork API 1.14.4, vanilla 1.15 and above, + * this is never called. See {@link net.minecraftforge.client.model.animation.TileEntityRendererFast}. + * + *

If the TileEntitySpecialRenderer associated with this TileEntity can be batched in with another renderers, and won't access the GL state. + * If TileEntity returns true, then TESR should have the same functionality as (and probably extend) the FastTESR class. + */ + @Deprecated + default boolean hasFastRenderer() { + return false; + } + + /** + * Requests a refresh for the model data of your TE + * Call this every time your {@link #getModelData()} changes. + */ + default void requestModelDataUpdate() { + BlockEntity te = getTileEntity(); + World world = te.getWorld(); + + if (world != null && world.isClient) { + // ModelDataManager.requestModelDataRefresh(te); + } + } + + /** + * Allows you to return additional model data. + * This data can be used to provide additional functionality in your {@link net.minecraft.client.renderer.model.IBakedModel} + * You need to schedule a refresh of you model data via {@link #requestModelDataUpdate()} if the result of this function changes. + * Note that this method may be called on a chunk render thread instead of the main client thread + * + * @return Your model data + */ + //@Nonnull + //default IModelData getModelData() { + // return EmptyModelData.INSTANCE; + //} +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderDispatcher.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderDispatcher.java new file mode 100644 index 00000000..cb0bf57a --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderDispatcher.java @@ -0,0 +1,30 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.extensions.blockentity; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; + +public interface ForgeBlockEntityRenderDispatcher { + /** + * Forge Internal, Do not call, Use ClientRegistry. + */ + void setSpecialRenderer(Class clsBlockEntity, BlockEntityRenderer ber); +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderer.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderer.java new file mode 100644 index 00000000..aef2209b --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderer.java @@ -0,0 +1,29 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.extensions.blockentity; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.render.BufferBuilder; + +@Deprecated +public interface ForgeBlockEntityRenderer { + default void renderTileEntityFast(T te, double x, double y, double z, float partialTicks, int destroyStage, BufferBuilder buffer) { + } +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntity.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntity.java new file mode 100644 index 00000000..6d642335 --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntity.java @@ -0,0 +1,65 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.blockentity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import net.minecraftforge.common.extensions.IForgeTileEntity; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.nbt.CompoundTag; + +@Mixin(BlockEntity.class) +public abstract class MixinBlockEntity implements IForgeTileEntity { + @Unique + private CompoundTag customTileData; + + @Inject(method = "fromTag", at = @At("RETURN")) + private void readForgeData(CompoundTag tag, CallbackInfo ci) { + if (tag.contains("ForgeData")) { + customTileData = tag.getCompound("ForgeData"); + } + } + + @Inject(method = "writeIdentifyingData", at = @At("RETURN")) + private void saveForgeData(CompoundTag tag, CallbackInfoReturnable ci) { + if (customTileData != null) { + tag.put("ForgeData", customTileData); + } + } + + @Inject(method = "markRemoved", at = @At("RETURN")) + private void markRemoved(CallbackInfo ci) { + requestModelDataUpdate(); + } + + @Override + public CompoundTag getTileData() { + if (customTileData == null) { + customTileData = new CompoundTag(); + } + + return customTileData; + } +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderDispatcher.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderDispatcher.java new file mode 100644 index 00000000..f9fc5300 --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderDispatcher.java @@ -0,0 +1,43 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.blockentity; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; + +import net.patchworkmc.impl.extensions.blockentity.ForgeBlockEntityRenderDispatcher; + +@Mixin(BlockEntityRenderDispatcher.class) +public abstract class MixinBlockEntityRenderDispatcher implements ForgeBlockEntityRenderDispatcher { + @Shadow + @Final + private Map, BlockEntityRenderer> renderers; + + public synchronized void setSpecialRenderer(Class clsBlockEntity, BlockEntityRenderer ber) { + renderers.put(clsBlockEntity, ber); + } +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderer.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderer.java new file mode 100644 index 00000000..5a76e8ef --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderer.java @@ -0,0 +1,32 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.blockentity; + +import org.spongepowered.asm.mixin.Mixin; + +import net.minecraft.client.render.block.entity.BlockEntityRenderer; + +import net.patchworkmc.impl.extensions.blockentity.ForgeBlockEntityRenderer; + +@SuppressWarnings("rawtypes") +@Mixin(BlockEntityRenderer.class) +@Deprecated // No longer required in 1.15 and above +public abstract class MixinBlockEntityRenderer implements ForgeBlockEntityRenderer { +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinClientPlayNetworkHandler.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinClientPlayNetworkHandler.java new file mode 100644 index 00000000..f1e6be22 --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinClientPlayNetworkHandler.java @@ -0,0 +1,121 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.blockentity; + +import java.util.Iterator; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import net.minecraftforge.common.extensions.IForgeTileEntity; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; +import net.minecraft.util.math.BlockPos; + +import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; + +/** + * TODO: This Mixin can be less hacky if we can talk to the Fabric API team. + * + *

This Mixin implements {@link IForgeTileEntity#handleUpdateTag(CompoundTag)} + * and {@link IForgeTileEntity#onDataPacket(net.minecraft.network.ClientConnection, BlockEntityUpdateS2CPacket)}. + */ +@Mixin(ClientPlayNetworkHandler.class) +public abstract class MixinClientPlayNetworkHandler { + /////////////////////////////////////////////////////////////// + /// onChunkData -> IForgeTileEntity.handleUpdateTag + /////////////////////////////////////////////////////////////// + @Unique + private static final ThreadLocal onChunkData_BETag = ThreadLocal.withInitial(() -> null); + @Unique + private static final String ClientWorld_getBlockEntity = "net/minecraft/client/world/ClientWorld.getBlockEntity(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/entity/BlockEntity;"; + + @Inject(method = "onChunkData", locals = LocalCapture.CAPTURE_FAILHARD, + at = @At(value = "INVOKE", shift = Shift.BEFORE, target = ClientWorld_getBlockEntity)) + private void onChunkData_CollectBETag(ChunkDataS2CPacket packet, CallbackInfo ci, + @SuppressWarnings("rawtypes") Iterator blockEntityTagListIterator, CompoundTag blockEntityTag, BlockPos blockPos) { + if (onBlockEntityUpdate_BlockEntity.get() != null) { + throw new IllegalStateException("State of ClientPlayNetworkHandler.onChunkData() is not clean, incompatible Mixins might be the cause!"); + } + + onChunkData_BETag.set(blockEntityTag); + } + + @Redirect(method = "onChunkData", at = @At(value = "INVOKE", target = ClientWorld_getBlockEntity)) + private BlockEntity onChunkData_world_getBlockEntity(ClientWorld clientWorld, BlockPos blockPos) { + CompoundTag blockEntityTag = onChunkData_BETag.get(); + onChunkData_BETag.remove(); + + ClientPlayNetworkHandler me = (ClientPlayNetworkHandler) (Object) this; + BlockEntity blockEntity = me.getWorld().getBlockEntity(blockPos); + + if (blockEntity != null && !(blockEntity instanceof BlockEntityClientSerializable)) { + // Non-Fabric BlockEntity, redirect to IForgeTileEntity.handleUpdateTag, + // which then calls the vanilla BlockEntity.fromTag method. + ((IForgeTileEntity) blockEntity).handleUpdateTag(blockEntityTag); + return null; // Skip Fabric's patch + } else { + return blockEntity; // Fabric BlockEntity, let Fabric API process it. + } + } + + /////////////////////////////////////////////////////////////// + /// onBlockEntityUpdate -> IForgeTileEntity.onDataPacket + /////////////////////////////////////////////////////////////// + @Unique + private static final ThreadLocal onBlockEntityUpdate_BlockEntity = ThreadLocal.withInitial(() -> null); + + @Inject(method = "onBlockEntityUpdate", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", ordinal = 0, shift = Shift.AFTER, + target = "net/minecraft/network/packet/s2c/play/BlockEntityUpdateS2CPacket.getBlockEntityType()I")) + private void onBlockEntityUpdate_getBlockEntityType(BlockEntityUpdateS2CPacket packet, CallbackInfo ci, BlockEntity blockEntity) { + if (onBlockEntityUpdate_BlockEntity.get() != null) { + throw new IllegalStateException("State of ClientPlayNetworkHandler.onBlockEntityUpdate() is not clean, incompatible Mixins might be the cause!"); + } + + onBlockEntityUpdate_BlockEntity.set(blockEntity); + } + + @Inject(method = "onBlockEntityUpdate", at = @At(value = "INVOKE", ordinal = 0, shift = Shift.BEFORE, + target = "net/minecraft/block/entity/BlockEntity.fromTag(Lnet/minecraft/nbt/CompoundTag;)V")) + private void onBlockEntityUpdate_fromTag(CallbackInfo ci) { + onBlockEntityUpdate_BlockEntity.remove(); + } + + @Inject(method = "onBlockEntityUpdate", at = @At(value = "RETURN")) + private void onBlockEntityUpdate_Return(BlockEntityUpdateS2CPacket packet, CallbackInfo ci) { + BlockEntity blockEntity = onBlockEntityUpdate_BlockEntity.get(); + + if (blockEntity != null && !(blockEntity instanceof BlockEntityClientSerializable)) { + onBlockEntityUpdate_BlockEntity.remove(); + ClientPlayNetworkHandler me = (ClientPlayNetworkHandler) (Object) this; + ((IForgeTileEntity) blockEntity).onDataPacket(me.getConnection(), packet); + } + } +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinWorld.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinWorld.java new file mode 100644 index 00000000..0fb2ad3c --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinWorld.java @@ -0,0 +1,178 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.blockentity; + +import java.util.Iterator; +import java.util.List; + +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import net.minecraftforge.common.extensions.IForgeTileEntity; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.Tickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.profiler.Profiler; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; + +/** + * This Mixin implements {@link IForgeTileEntity#onLoad()} and {@link IForgeTileEntity#onChunkUnloaded()}. + */ +@Mixin(World.class) +public class MixinWorld { + ///////////////////////////////////// + /// addBlockEntity() + ///////////////////////////////////// + @Inject(method = "addBlockEntity", at = @At("HEAD")) + private void onAddBlockEntity(BlockEntity blockEntity, CallbackInfoReturnable ci) { + World me = (World) (Object) this; + + if (blockEntity.getWorld() != me) { + // Forge - set the world early as vanilla doesn't set it until next tick + blockEntity.setWorld(me); + } + } + + @Shadow + @Final + protected List pendingBlockEntities; + + @Inject(method = "addBlockEntity", cancellable = true, + at = @At(value = "INVOKE", ordinal = 0, shift = Shift.AFTER, remap = false, + target = "org/apache/logging/log4j/Logger.error(Ljava/lang/String;[Lorg/apache/logging/log4j/util/Supplier;)V")) + private void onBlockEntityAdding(BlockEntity blockEntity, CallbackInfoReturnable cir) { + // Forge: wait to add new TE if we're currently processing existing ones + cir.setReturnValue(pendingBlockEntities.add(blockEntity)); + } + + @Inject(method = "addBlockEntity", at = @At(value = "FIELD", ordinal = 0, shift = Shift.BEFORE, + target = "net/minecraft/world/World.isClient:Z", opcode = Opcodes.GETFIELD)) + private void onBlockEntityAdded(BlockEntity blockEntity, CallbackInfoReturnable cir) { + // We cannot use Fabric events because Forge's onLoad() is also called on the client side. + ((IForgeTileEntity) blockEntity).onLoad(); + } + + ///////////////////////////////////// + /// tickBlockEntities() + ///////////////////////////////////// + @Shadow + protected boolean iteratingTickingBlockEntities; + + @Inject(method = "tickBlockEntities", at = @At(value = "INVOKE", ordinal = 0, shift = Shift.AFTER, + target = "net/minecraft/util/profiler/Profiler.push(Ljava/lang/String;)V")) + private void onTickBlockEntitiesStart(CallbackInfo ci) { + // Forge: Move above remove to prevent CocurrentModificationException + iteratingTickingBlockEntities = true; + } + + @Shadow + @Final + protected List unloadedBlockEntities; + + @Inject(method = "tickBlockEntities", at = @At(value = "INVOKE", ordinal = 0, shift = Shift.BEFORE, + target = "java/util/List.removeAll(Ljava/util/Collection;)Z")) + private void onBlockEntitiesRemoved(CallbackInfo ci) { + for (BlockEntity blockEntity: unloadedBlockEntities) { + ((IForgeTileEntity) blockEntity).onChunkUnloaded(); + } + } + + @Unique + private static final ThreadLocal onBlockEntitiesRemoved_BlockEntity = ThreadLocal.withInitial(() -> null); + @Unique + private static final String WorldChunk_removeBlockEntity = "net/minecraft/world/chunk/WorldChunk.removeBlockEntity(Lnet/minecraft/util/math/BlockPos;)V"; + + @Inject(method = "tickBlockEntities", locals = LocalCapture.CAPTURE_FAILHARD, + at = @At(value = "INVOKE", ordinal = 0, shift = Shift.BEFORE, target = WorldChunk_removeBlockEntity)) + private void onBlockEntitiesRemoved_CaptureVars(CallbackInfo ci, + Profiler profiler, @SuppressWarnings("rawtypes") Iterator iterator, BlockEntity blockEntity) { + if (onBlockEntitiesRemoved_BlockEntity.get() != null) { + throw new IllegalStateException("State of World.onBlockEntitiesRemoved() is not clean, incompatible Mixins might be the cause!"); + } + + onBlockEntitiesRemoved_BlockEntity.set(blockEntity); + } + + @Redirect(method = "tickBlockEntities", at = @At(value = "INVOKE", ordinal = 0, target = WorldChunk_removeBlockEntity)) + private void onBlockEntitiesRemoved(WorldChunk chunk, BlockPos pos) { + BlockEntity blockEntity = onBlockEntitiesRemoved_BlockEntity.get(); + onBlockEntitiesRemoved_BlockEntity.remove(); + + //Forge: Bugfix: If we set the tile entity it immediately sets it in the chunk, so we could be desyned + if (chunk.getBlockEntity(pos, WorldChunk.CreationType.CHECK) == blockEntity) { + chunk.removeBlockEntity(pos); + } + } + + ///////////////////////////////////// + /// setBlockEntity() + ///////////////////////////////////// + @ModifyVariable(method = "setBlockEntity", at = @At("HEAD")) + private BlockPos makeBlockPosImmutable(BlockPos pos) { + // Forge - prevent mutable BlockPos leaks + return pos.toImmutable(); + } + + @Inject(method = "setBlockEntity", at = @At(value = "INVOKE", ordinal = 0, shift = Shift.BEFORE, + target = "java/util/List.iterator()Ljava/util/Iterator;")) + private void setWorldEarly(BlockPos pos, BlockEntity blockEntity, CallbackInfo ci) { + World me = (World) (Object) this; + + if (blockEntity.getWorld() != me) { + // Forge - set the world early as vanilla doesn't set it until next tick + blockEntity.setWorld(me); + } + } + + @Redirect(method = "setBlockEntity", at = @At(value = "INVOKE", ordinal = 0, + target = "net/minecraft/world/chunk/WorldChunk.setBlockEntity(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/entity/BlockEntity;)V")) + private void checkChunkAndSetBlockEntity(WorldChunk chunk, BlockPos pos, BlockEntity blockEntity) { + // Forge adds this to prevent a null-pointer exception + if (chunk != null) { + chunk.setBlockEntity(pos, blockEntity); + } + } + + ///////////////////////////////////// + /// removeBlockEntity() + ///////////////////////////////////// + @Inject(method = "removeBlockEntity", locals = LocalCapture.CAPTURE_FAILHARD, + at = @At(value = "INVOKE", ordinal = 0, shift = Shift.AFTER, + target = "java/util/List.remove(Ljava/lang/Object;)Z")) + private void removeTickableBlockEntity(BlockPos pos, CallbackInfo ci, BlockEntity blockEntity) { + if (!(blockEntity instanceof Tickable)) { + //Forge: If they are not tickable they wont be removed in the update loop. + World me = (World) (Object) this; + me.blockEntities.remove(blockEntity); + } + } +} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinWorldRenderer.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinWorldRenderer.java new file mode 100644 index 00000000..5629a61d --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinWorldRenderer.java @@ -0,0 +1,99 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.blockentity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.Redirect; +import net.minecraftforge.common.extensions.IForgeTileEntity; + +import net.minecraft.block.ChestBlock; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.render.BlockBreakingInfo; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.VisibleRegion; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.BlockPos; + +/** + * Implements {@link IForgeTileEntity#getRenderBoundingBox()} and + * {@link IForgeTileEntity#canRenderBreaking()}. + */ +@Mixin(WorldRenderer.class) +public class MixinWorldRenderer { + ///////////////////////////////////// + /// renderEntities() + ///////////////////////////////////// + // Redirect two calls. + @Redirect(method = "renderEntities", at = @At(value = "INVOKE", + target = "net/minecraft/client/render/block/entity/BlockEntityRenderDispatcher.render(Lnet/minecraft/block/entity/BlockEntity;FI)V")) + private void renderBlockEntityIfVisible(BlockEntityRenderDispatcher dispatcher, BlockEntity blockEntity, float tickDelta, int blockBreakStage, + Camera camera, VisibleRegion visibleRegion, float tickDeltaParam) { + IForgeTileEntity te = (IForgeTileEntity) blockEntity; + + if (visibleRegion.intersects(te.getRenderBoundingBox())) { + dispatcher.render(blockEntity, tickDeltaParam, blockBreakStage); + } + } + + ///////////////////////////////////// + /// renderPartiallyBrokenBlocks() + ///////////////////////////////////// + @Shadow + private ClientWorld world; + @Unique + private static final ThreadLocal blockPosParam = ThreadLocal.withInitial(() -> null); + + @Redirect(method = "renderPartiallyBrokenBlocks", at = @At(value = "INVOKE", ordinal = 0, + target = "net/minecraft/client/render/BlockBreakingInfo.getPos()Lnet/minecraft/util/math/BlockPos;")) + private BlockPos captureBlockPos(BlockBreakingInfo bbi) { + if (blockPosParam.get() != null) { + throw new IllegalStateException("State of WorldRenderer.renderPartiallyBrokenBlocks() is not clean, incompatible Mixins might be the cause!"); + } + + BlockPos pos = bbi.getPos(); + blockPosParam.set(pos); + return pos; + } + + @ModifyConstant(method = "renderPartiallyBrokenBlocks", constant = @Constant(classValue = ChestBlock.class)) + private boolean skipNormalPartialDamageRendering(Object objIn, Class clsChestBlock) { + BlockPos pos = blockPosParam.get(); + blockPosParam.remove(); + + if (clsChestBlock.isAssignableFrom(objIn.getClass())) { + return true; // objIn instanceof clsChestBlock + } + + BlockEntity blockEntity = world.getBlockEntity(pos); + + if (blockEntity == null) { + return false; // Render partial damage for normal blocks + } + + return ((IForgeTileEntity) blockEntity).canRenderBreaking(); + } +} diff --git a/patchwork-extensions-blockentity/src/main/resources/assets/patchwork-extensions-block/icon.png b/patchwork-extensions-blockentity/src/main/resources/assets/patchwork-extensions-block/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-extensions-blockentity/src/main/resources/fabric.mod.json b/patchwork-extensions-blockentity/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..dd6c5ed2 --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/resources/fabric.mod.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 1, + "id": "patchwork-extensions-blockentity", + "version": "${version}", + "icon": "assets/patchwork-enum-hacks/icon.png", + "name": "Patchwork Extensions Block", + "description": "Implementation of Forge's blockentity extensions (IForgeTileEntity)", + "authors": [ + "PatchworkMC" + ], + "license": "LGPL-2.1-only", + "environment": "*", + "depends": { + "fabricloader": ">=0.8.4" + }, + "mixins": [ + "patchwork-extensions-blockentity.mixins.json" + ], + "custom": { + "modmenu:api": true, + "modmenu:parent": "patchwork" + } +} diff --git a/patchwork-extensions-blockentity/src/main/resources/patchwork-extensions-blockentity.mixins.json b/patchwork-extensions-blockentity/src/main/resources/patchwork-extensions-blockentity.mixins.json new file mode 100644 index 00000000..a9b886fa --- /dev/null +++ b/patchwork-extensions-blockentity/src/main/resources/patchwork-extensions-blockentity.mixins.json @@ -0,0 +1,18 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.extensions.blockentity", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinBlockEntity", + "MixinWorld" + ], + "client": [ + "MixinClientPlayNetworkHandler", + "MixinBlockEntityRenderDispatcher", + "MixinBlockEntityRenderer", + "MixinWorldRenderer" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index df70a8cd..4454ff43 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -11,6 +11,7 @@ dependencies { implementation project(path: ':patchwork-events-rendering', configuration: 'dev') implementation project(path: ':patchwork-events-world', configuration: 'dev') implementation project(path: ':patchwork-extensions-block', configuration: 'dev') + implementation project(path: ':patchwork-extensions-blockentity', configuration: 'dev') implementation project(path: ':patchwork-loot', configuration: 'dev') implementation project(path: ':patchwork-networking', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java new file mode 100644 index 00000000..fa253e5c --- /dev/null +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java @@ -0,0 +1,40 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.client.registry; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; + +import net.patchworkmc.impl.extensions.blockentity.ForgeBlockEntityRenderDispatcher; + +public class ClientRegistry { + /** + * Registers a Tile Entity renderer. Call this during + * {@link net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent}. This + * method is safe to call during parallel mod loading. + */ + public static synchronized void bindTileEntityRenderer( + Class clsBlockEntity, BlockEntityRenderer specialRenderer) { + ((ForgeBlockEntityRenderDispatcher) BlockEntityRenderDispatcher.INSTANCE).setSpecialRenderer(clsBlockEntity, + specialRenderer); + specialRenderer.setRenderManager(BlockEntityRenderDispatcher.INSTANCE); + } +} diff --git a/settings.gradle b/settings.gradle index 3da056d2..4e7df63e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -25,6 +25,7 @@ include 'patchwork-events-rendering' include 'patchwork-events-world' include 'patchwork-extensions' include 'patchwork-extensions-block' +include 'patchwork-extensions-blockentity' include 'patchwork-extensions-item' include 'patchwork-extensions-shearing' include 'patchwork-fml' From 547331d5edc9dd25d8b4bb9e0f1e35d406662d5e Mon Sep 17 00:00:00 2001 From: William Bradford Larcombe Date: Tue, 18 Aug 2020 03:36:02 +0000 Subject: [PATCH 51/73] Add FakePlayer API (#178) * Add FakePlayer * Add FakePlayerFactory * Invoke FakePlayerFactory#unloadWorld * Fix license * Improve code quality of `FakePlayerFactory`: - Make some private static fields final - Remove an explicit generic type that was inferrable - Simplify logic in `unloadWorld` to mirror the logic in `getMinecraft` - Add javadoc for `unloadWorld` * Fix formatting in a couple of comments * Improve `FakePlayerFactory#get`: - username -> profile (shouldn't break anything) - switch to using computeIfAbsent * Move fake players into a new module * Update fake players unloading to use `fabric-lifecycle-events-v1` * Fix style * Update patchwork-extensions/src/main/resources/fabric.mod.json * Update patchwork-fake-players/build.gradle Co-authored-by: qouteall Co-authored-by: Glitch --- patchwork-fake-players/build.gradle | 6 ++ .../common/util/FakePlayer.java | 81 ++++++++++++++++++ .../common/util/FakePlayerFactory.java | 70 +++++++++++++++ .../fakeplayers/PatchworkFakePlayers.java | 38 ++++++++ .../MixinPlayerAdvancementTracker.java | 44 ++++++++++ .../assets/patchwork-extensions/icon.png | Bin 0 -> 22738 bytes .../src/main/resources/fabric.mod.json | 29 +++++++ .../patchwork-extensions.mixins.json | 11 +++ settings.gradle | 1 + 9 files changed, 280 insertions(+) create mode 100644 patchwork-fake-players/build.gradle create mode 100644 patchwork-fake-players/src/main/java/net/minecraftforge/common/util/FakePlayer.java create mode 100644 patchwork-fake-players/src/main/java/net/minecraftforge/common/util/FakePlayerFactory.java create mode 100644 patchwork-fake-players/src/main/java/net/patchworkmc/impl/fakeplayers/PatchworkFakePlayers.java create mode 100644 patchwork-fake-players/src/main/java/net/patchworkmc/mixin/fakeplayers/MixinPlayerAdvancementTracker.java create mode 100644 patchwork-fake-players/src/main/resources/assets/patchwork-extensions/icon.png create mode 100644 patchwork-fake-players/src/main/resources/fabric.mod.json create mode 100644 patchwork-fake-players/src/main/resources/patchwork-extensions.mixins.json diff --git a/patchwork-fake-players/build.gradle b/patchwork-fake-players/build.gradle new file mode 100644 index 00000000..e18ff318 --- /dev/null +++ b/patchwork-fake-players/build.gradle @@ -0,0 +1,6 @@ +archivesBaseName = "patchwork-fake-players" +version = getSubprojectVersion(project, "0.1.0") + +dependencies { + implementation project(path: ':patchwork-api-base', configuration: 'dev') +} diff --git a/patchwork-fake-players/src/main/java/net/minecraftforge/common/util/FakePlayer.java b/patchwork-fake-players/src/main/java/net/minecraftforge/common/util/FakePlayer.java new file mode 100644 index 00000000..2408f660 --- /dev/null +++ b/patchwork-fake-players/src/main/java/net/minecraftforge/common/util/FakePlayer.java @@ -0,0 +1,81 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.common.util; + +import com.mojang.authlib.GameProfile; + +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.c2s.play.ClientSettingsC2SPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.network.ServerPlayerInteractionManager; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.stat.Stat; +import net.minecraft.text.Text; +import net.minecraft.util.math.Vec3d; + +// Preliminary, simple Fake Player class +public class FakePlayer extends ServerPlayerEntity { + public FakePlayer(ServerWorld world, GameProfile profile) { + super(world.getServer(), world, profile, new ServerPlayerInteractionManager(world)); + } + + @Override + public Vec3d getPosVector() { + return new Vec3d(0, 0, 0); + } + + @Override + public void addChatMessage(Text text, boolean actionBar) { + } + + @Override + public void sendMessage(Text component) { + } + + @Override + public void increaseStat(Stat stat, int num) { + } + + @Override + public boolean isInvulnerableTo(DamageSource source) { + return true; + } + + @Override + public boolean shouldDamagePlayer(PlayerEntity player) { + return false; + } + + @Override + public void onDeath(DamageSource source) { + } + + @Override + public void tick() { + } + + @Override + public void setClientSettings(ClientSettingsC2SPacket packet) { + } + + // Forge also has this here: + // @Override @Nullable public MinecraftServer getServer() { return ServerLifecycleHooks.getCurrentServer(); } +} diff --git a/patchwork-fake-players/src/main/java/net/minecraftforge/common/util/FakePlayerFactory.java b/patchwork-fake-players/src/main/java/net/minecraftforge/common/util/FakePlayerFactory.java new file mode 100644 index 00000000..2403c7c2 --- /dev/null +++ b/patchwork-fake-players/src/main/java/net/minecraftforge/common/util/FakePlayerFactory.java @@ -0,0 +1,70 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.common.util; + +import java.lang.ref.WeakReference; +import java.util.Map; +import java.util.UUID; + +import com.google.common.collect.Maps; +import com.mojang.authlib.GameProfile; + +import net.minecraft.server.world.ServerWorld; + +public class FakePlayerFactory { + private static final GameProfile MINECRAFT = new GameProfile(UUID.fromString("41C82C87-7AfB-4024-BA57-13D2C99CAE77"), "[Minecraft]"); + // Map of all active fake player profiles to their entities + private static final Map fakePlayers = Maps.newHashMap(); + private static WeakReference MINECRAFT_PLAYER = null; + + public static FakePlayer getMinecraft(ServerWorld world) { + FakePlayer ret = MINECRAFT_PLAYER != null ? MINECRAFT_PLAYER.get() : null; + + if (ret == null) { + ret = FakePlayerFactory.get(world, MINECRAFT); + MINECRAFT_PLAYER = new WeakReference<>(ret); + } + + return ret; + } + + /** + * Get a fake player with a given profile. + * Mods should either hold weak references to the return value, or listen for a + * WorldEvent.Unload and kill all references to prevent worlds staying in memory. + */ + public static FakePlayer get(ServerWorld world, GameProfile profile) { + return fakePlayers.computeIfAbsent(profile, it -> new FakePlayer(world, it)); + } + + /** + * Used internally to clean up fake players when worlds are unloaded on server stop. + */ + public static void unloadWorld(ServerWorld world) { + fakePlayers.entrySet().removeIf(entry -> entry.getValue().world == world); + + // This shouldn't be strictly necessary, but let's be aggressive. + FakePlayer mc = MINECRAFT_PLAYER != null ? MINECRAFT_PLAYER.get() : null; + + if (mc != null && mc.world == world) { + MINECRAFT_PLAYER = null; + } + } +} diff --git a/patchwork-fake-players/src/main/java/net/patchworkmc/impl/fakeplayers/PatchworkFakePlayers.java b/patchwork-fake-players/src/main/java/net/patchworkmc/impl/fakeplayers/PatchworkFakePlayers.java new file mode 100644 index 00000000..1e9db443 --- /dev/null +++ b/patchwork-fake-players/src/main/java/net/patchworkmc/impl/fakeplayers/PatchworkFakePlayers.java @@ -0,0 +1,38 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.fakeplayers; + +import net.minecraftforge.common.util.FakePlayerFactory; + +import net.minecraft.server.world.ServerWorld; + +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.api.ModInitializer; + +public class PatchworkFakePlayers implements ModInitializer { + @Override + public void onInitialize() { + ServerLifecycleEvents.SERVER_STOPPED.register(server -> { + for (ServerWorld world : server.getWorlds()) { + FakePlayerFactory.unloadWorld(world); + } + }); + } +} diff --git a/patchwork-fake-players/src/main/java/net/patchworkmc/mixin/fakeplayers/MixinPlayerAdvancementTracker.java b/patchwork-fake-players/src/main/java/net/patchworkmc/mixin/fakeplayers/MixinPlayerAdvancementTracker.java new file mode 100644 index 00000000..3a101a98 --- /dev/null +++ b/patchwork-fake-players/src/main/java/net/patchworkmc/mixin/fakeplayers/MixinPlayerAdvancementTracker.java @@ -0,0 +1,44 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.fakeplayers; + +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.minecraftforge.common.util.FakePlayer; + +import net.minecraft.advancement.Advancement; +import net.minecraft.advancement.PlayerAdvancementTracker; +import net.minecraft.server.network.ServerPlayerEntity; + +@Mixin(PlayerAdvancementTracker.class) +public class MixinPlayerAdvancementTracker { + @Shadow + private ServerPlayerEntity owner; + + @Inject(method = "grantCriterion", at = @At("HEAD"), cancellable = true) + private void onGrantCriterion(Advancement advancement, String criterion, CallbackInfoReturnable cir) { + if (owner instanceof FakePlayer) { + cir.setReturnValue(false); + } + } +} diff --git a/patchwork-fake-players/src/main/resources/assets/patchwork-extensions/icon.png b/patchwork-fake-players/src/main/resources/assets/patchwork-extensions/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..de75d2fbe9467f986e4f3072e76fa751dbd72879 GIT binary patch literal 22738 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 literal 0 HcmV?d00001 diff --git a/patchwork-fake-players/src/main/resources/fabric.mod.json b/patchwork-fake-players/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..a544c018 --- /dev/null +++ b/patchwork-fake-players/src/main/resources/fabric.mod.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "id": "patchwork-fake-players", + "version": "${version}", + "name": "Patchwork Fake Players", + "description": "Implements the Minecraft Forge fake players API", + "authors": [ + "PatchworkMC" + ], + "license": "LGPL-2.1-only", + "icon": "assets/patchwork-fake-players/icon.png", + "environment": "*", + "depends": { + "patchwork-api-base": "*", + "fabric": "*" + }, + "mixins": [ + "patchwork-fake-players.mixins.json" + ], + "entrypoints": { + "main": [ + "net.patchworkmc.impl.fakeplayers.PatchworkFakePlayers" + ] + }, + "custom": { + "modmenu:api": true, + "modmenu:parent": "patchwork" + } +} diff --git a/patchwork-fake-players/src/main/resources/patchwork-extensions.mixins.json b/patchwork-fake-players/src/main/resources/patchwork-extensions.mixins.json new file mode 100644 index 00000000..27671806 --- /dev/null +++ b/patchwork-fake-players/src/main/resources/patchwork-extensions.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.fakeplayers", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinPlayerAdvancementTracker", + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/settings.gradle b/settings.gradle index 4e7df63e..015e7123 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,6 +28,7 @@ include 'patchwork-extensions-block' include 'patchwork-extensions-blockentity' include 'patchwork-extensions-item' include 'patchwork-extensions-shearing' +include 'patchwork-fake-players' include 'patchwork-fml' include 'patchwork-god-classes' include 'patchwork-gui' From d1ad8e1aad32a031031afdc18d939018b9057a03 Mon Sep 17 00:00:00 2001 From: William Bradford Larcombe Date: Wed, 19 Aug 2020 01:33:18 +0000 Subject: [PATCH 52/73] Fix invalid mixins json for fake players module (#181) --- ...xtensions.mixins.json => patchwork-fake-players.mixins.json} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename patchwork-fake-players/src/main/resources/{patchwork-extensions.mixins.json => patchwork-fake-players.mixins.json} (82%) diff --git a/patchwork-fake-players/src/main/resources/patchwork-extensions.mixins.json b/patchwork-fake-players/src/main/resources/patchwork-fake-players.mixins.json similarity index 82% rename from patchwork-fake-players/src/main/resources/patchwork-extensions.mixins.json rename to patchwork-fake-players/src/main/resources/patchwork-fake-players.mixins.json index 27671806..c6b3a60c 100644 --- a/patchwork-fake-players/src/main/resources/patchwork-extensions.mixins.json +++ b/patchwork-fake-players/src/main/resources/patchwork-fake-players.mixins.json @@ -3,7 +3,7 @@ "package": "net.patchworkmc.mixin.fakeplayers", "compatibilityLevel": "JAVA_8", "mixins": [ - "MixinPlayerAdvancementTracker", + "MixinPlayerAdvancementTracker" ], "injectors": { "defaultRequire": 1 From ea0ad1b943f83e618ba5dac61fc588085292241a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Wed, 19 Aug 2020 11:36:08 +1000 Subject: [PATCH 53/73] Feature/armor (#171) * Impl IForgeItem.getArmorTexture * Impl IForgeItem.onArmorTick * Fix getArmorModel not being called properly * Apply suggestions --- .../item/PatchworkArmorItemHandler.java | 63 ++++++ .../extensions/item/MixinPlayerInventory.java | 42 ++++ .../MixinArmorBipedFeatureRenderer.java | 39 ++++ .../client/MixinArmorFeatureRenderer.java | 185 ++++++++++++++++++ .../patchwork-extensions-item.mixins.json | 3 + patchwork-god-classes/build.gradle | 1 + .../client/ForgeHooksClient.java | 14 ++ .../src/main/resources/fabric.mod.json | 1 + 8 files changed, 348 insertions(+) create mode 100644 patchwork-extensions-item/src/main/java/net/patchworkmc/impl/extensions/item/PatchworkArmorItemHandler.java create mode 100644 patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/MixinPlayerInventory.java create mode 100644 patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/client/MixinArmorBipedFeatureRenderer.java create mode 100644 patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/client/MixinArmorFeatureRenderer.java diff --git a/patchwork-extensions-item/src/main/java/net/patchworkmc/impl/extensions/item/PatchworkArmorItemHandler.java b/patchwork-extensions-item/src/main/java/net/patchworkmc/impl/extensions/item/PatchworkArmorItemHandler.java new file mode 100644 index 00000000..1f8ab4dc --- /dev/null +++ b/patchwork-extensions-item/src/main/java/net/patchworkmc/impl/extensions/item/PatchworkArmorItemHandler.java @@ -0,0 +1,63 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.extensions.item; + +import javax.annotation.Nullable; + +import net.minecraftforge.common.extensions.IForgeItem; + +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.world.World; + +public interface PatchworkArmorItemHandler { + @SuppressWarnings("rawtypes") + BipedEntityModel getArmorModelHook(LivingEntity entity, ItemStack itemStack, EquipmentSlot slot, BipedEntityModel model); + + Identifier getArmorResource(Entity entity, ItemStack stack, EquipmentSlot slot, @Nullable String type); + + /** + * Called by mixins(MixinArmorFeatureRenderer) and ForgeHooksClient. + */ + static String patchwork$getArmorTexture(Entity entity, ItemStack itemStack, String defaultTexture, EquipmentSlot slot, String type) { + IForgeItem forgeItem = (IForgeItem) itemStack.getItem(); + String result = forgeItem.getArmorTexture(itemStack, entity, slot, type); + return result != null ? result : defaultTexture; + } + + static > A patchwork$getArmorModel(LivingEntity entityLiving, ItemStack itemStack, EquipmentSlot slot, A _default) { + IForgeItem forgeItem = (IForgeItem) itemStack.getItem(); + A model = forgeItem.getArmorModel(entityLiving, itemStack, slot, _default); + return model == null ? _default : model; + } + + /** + * Called by mixins(MixinPlayerInventory) and IForgeItemStack. + */ + static void patchwork$fireArmorTick(ItemStack itemStack, World world, PlayerEntity player) { + IForgeItem item = (IForgeItem) itemStack.getItem(); + item.onArmorTick(itemStack, world, player); + } +} diff --git a/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/MixinPlayerInventory.java b/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/MixinPlayerInventory.java new file mode 100644 index 00000000..52ddd1e3 --- /dev/null +++ b/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/MixinPlayerInventory.java @@ -0,0 +1,42 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.item; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.world.World; + +import net.patchworkmc.impl.extensions.item.PatchworkArmorItemHandler; + +@Mixin(PlayerInventory.class) +public abstract class MixinPlayerInventory { + @Inject(method = "updateItems", at = @At("RETURN")) + private void fireArmorTick(CallbackInfo ci) { + final PlayerInventory me = (PlayerInventory) (Object) this; + final PlayerEntity player = me.player; + final World world = player.world; + me.armor.forEach(itemStack -> PatchworkArmorItemHandler.patchwork$fireArmorTick(itemStack, world, player)); + } +} diff --git a/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/client/MixinArmorBipedFeatureRenderer.java b/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/client/MixinArmorBipedFeatureRenderer.java new file mode 100644 index 00000000..9918befb --- /dev/null +++ b/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/client/MixinArmorBipedFeatureRenderer.java @@ -0,0 +1,39 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.item.client; + +import org.spongepowered.asm.mixin.Mixin; + +import net.minecraft.client.render.entity.feature.ArmorBipedFeatureRenderer; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; + +import net.patchworkmc.impl.extensions.item.PatchworkArmorItemHandler; + +@Mixin(ArmorBipedFeatureRenderer.class) +public abstract class MixinArmorBipedFeatureRenderer implements PatchworkArmorItemHandler { + @SuppressWarnings("rawtypes") + @Override + public BipedEntityModel getArmorModelHook(LivingEntity entity, ItemStack itemStack, EquipmentSlot slot, BipedEntityModel defaultModel) { + return PatchworkArmorItemHandler.patchwork$getArmorModel(entity, itemStack, slot, defaultModel); + } +} diff --git a/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/client/MixinArmorFeatureRenderer.java b/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/client/MixinArmorFeatureRenderer.java new file mode 100644 index 00000000..fae66d0a --- /dev/null +++ b/patchwork-extensions-item/src/main/java/net/patchworkmc/mixin/extensions/item/client/MixinArmorFeatureRenderer.java @@ -0,0 +1,185 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.extensions.item.client; + +import java.util.Map; + +import javax.annotation.Nullable; + +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; + +import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ArmorItem; +import net.minecraft.item.DyeableArmorItem; +import net.minecraft.item.DyeableItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Identifier; + +import net.patchworkmc.impl.extensions.item.PatchworkArmorItemHandler; + +/** + * TODO: Check if any Fabric mods calls getArmorTexture and method_4174 directly, + * I don't think so because both are private. + */ +@Mixin(ArmorFeatureRenderer.class) +public abstract class MixinArmorFeatureRenderer implements PatchworkArmorItemHandler { + @Shadow + @Final + private static Map ARMOR_TEXTURE_CACHE; + + @Shadow + private boolean isLegs(EquipmentSlot equipmentSlot) { + return false; + } + + @SuppressWarnings("rawtypes") + @Redirect(method = "renderArmor", at = @At(value = "INVOKE", ordinal = 0, + target = "net/minecraft/client/render/entity/feature/ArmorFeatureRenderer.getArmor(Lnet/minecraft/entity/EquipmentSlot;)Lnet/minecraft/client/render/entity/model/BipedEntityModel;")) + private BipedEntityModel getArmorModel(ArmorFeatureRenderer me, EquipmentSlot equipmentSlot, + LivingEntity livingEntity, float f, float g, float h, float i, float j, float k, float l, EquipmentSlot equipmentSlot2) { + BipedEntityModel defaultModel = me.getArmor(equipmentSlot); + ItemStack itemStack = livingEntity.getEquippedStack(equipmentSlot); + return this.getArmorModelHook(livingEntity, itemStack, equipmentSlot, defaultModel); + } + + // In 1.15 and above, getArmorTexture(ArmorItem, boolean) is removed. + @SuppressWarnings("rawtypes") + @Redirect(method = "renderArmor", at = @At(value = "INVOKE", ordinal = 0, + target = "net/minecraft/client/render/entity/feature/ArmorFeatureRenderer.getArmorTexture(Lnet/minecraft/item/ArmorItem;Z)Lnet/minecraft/util/Identifier;")) + private Identifier getArmorTexture(ArmorFeatureRenderer me, ArmorItem armor, boolean bl, + LivingEntity livingEntity, float f, float g, float h, float i, float j, float k, float l, EquipmentSlot equipmentSlot) { + ItemStack itemStack = livingEntity.getEquippedStack(equipmentSlot); + return this.getArmorResource(livingEntity, itemStack, equipmentSlot, null); + } + + // In 1.15 and above, method_4174 is renamed to getArmorTexture. + @SuppressWarnings("rawtypes") + @Redirect(method = "renderArmor", at = @At(value = "INVOKE", ordinal = 0, + target = "net/minecraft/client/render/entity/feature/ArmorFeatureRenderer.method_4174(Lnet/minecraft/item/ArmorItem;ZLjava/lang/String;)Lnet/minecraft/util/Identifier;")) + private Identifier getArmorTexture(ArmorFeatureRenderer me, ArmorItem armor, boolean bl, String overlay, + LivingEntity livingEntity, float f, float g, float h, float i, float j, float k, float l, EquipmentSlot equipmentSlot) { + ItemStack itemStack = livingEntity.getEquippedStack(equipmentSlot); + return this.getArmorResource(livingEntity, itemStack, equipmentSlot, overlay); + } + + /* + * this.bindTexture(xxxxxxxx); // The first bindTexture() within renderArmor(). + * - if (armorItem instanceof DyeableArmorItem) { + * - int m = ((DyeableArmorItem)armorItem).getColor(itemStack); + * + if (armorItem instanceof DyeableItem) { + * + armorItem = hookBeforeTypeCast(armorItem); + * + int m = ((DyeableItem) armorItem).hookGetColor(armorItem, itemStack); + * + armorItem = restoreVar(xxxx); + * float n = (float) (m >> 16 & 255) / 255.0F; + */ + @SuppressWarnings("rawtypes") + @ModifyConstant(method = "renderArmor", constant = @Constant(classValue = DyeableArmorItem.class, ordinal = 0)) + private boolean isDyeableItem(Object obj, Class cls) { + return obj instanceof DyeableItem; // Allow this for anything, not only cloth + } + + @Unique + private static final String FeatureRenderer_bindTexture = "net/minecraft/client/render/entity/feature/FeatureRenderer.bindTexture(Lnet/minecraft/util/Identifier;)V"; + @Unique + private static final String DyeableArmorItem_getColor = "net/minecraft/item/DyeableArmorItem.getColor(Lnet/minecraft/item/ItemStack;)I"; + + @ModifyVariable(method = "renderArmor", ordinal = 0, at = @At(value = "JUMP", ordinal = 0, opcode = Opcodes.IFEQ, shift = Shift.AFTER), + slice = @Slice( + from = @At(value = "INVOKE", ordinal = 0, target = FeatureRenderer_bindTexture), + to = @At(value = "INVOKE", ordinal = 0, target = DyeableArmorItem_getColor) + )) + private ArmorItem hookBeforeTypeCast(ArmorItem armorItem) { + return (DyeableArmorItem) Items.LEATHER_HELMET; // Bypass the checkcast + } + + @Redirect(method = "renderArmor", at = @At(value = "INVOKE", ordinal = 0, target = DyeableArmorItem_getColor)) + private int hookGetColor(DyeableArmorItem dummy, ItemStack itemStack) { + return ((DyeableItem) itemStack.getItem()).getColor(itemStack); + } + + @ModifyVariable(method = "renderArmor", ordinal = 0, at = @At(value = "INVOKE", ordinal = 0, shift = Shift.AFTER, target = DyeableArmorItem_getColor)) + private ArmorItem restoreVar(ArmorItem armorItem, + LivingEntity livingEntity, float f, float g, float h, float i, float j, float k, float l, EquipmentSlot equipmentSlot) { + ItemStack itemStack = livingEntity.getEquippedStack(equipmentSlot); + return (ArmorItem) itemStack.getItem(); + } + + /*=================================== FORGE START =========================================*/ + /** + * Hook to allow item-sensitive armor model. for LayerBipedArmor. In Forge, this is protected. + */ + @SuppressWarnings("rawtypes") + @Override + public BipedEntityModel getArmorModelHook(LivingEntity entity, ItemStack itemStack, EquipmentSlot slot, BipedEntityModel model) { + return model; + } + + /** + * More generic ForgeHook version of the above function, it allows for Items to + * have more control over what texture they provide. + * + * @param entity Entity wearing the armor + * @param stack ItemStack for the armor + * @param slot Slot ID that the item is in + * @param type Subtype, can be null or "overlay" + * @return ResourceLocation pointing at the armor's texture + */ + @Override + public Identifier getArmorResource(Entity entity, ItemStack stack, EquipmentSlot slot, @Nullable String type) { + ArmorItem item = (ArmorItem) stack.getItem(); + String texture = item.getMaterial().getName(); + String domain = "minecraft"; + int idx = texture.indexOf(':'); + + if (idx != -1) { + domain = texture.substring(0, idx); + texture = texture.substring(idx + 1); + } + + String s1 = String.format("%s:textures/models/armor/%s_layer_%d%s.png", domain, texture, (isLegs(slot) ? 2 : 1), + type == null ? "" : String.format("_%s", type)); + + s1 = PatchworkArmorItemHandler.patchwork$getArmorTexture(entity, stack, s1, slot, type); + Identifier armorTextureIdentifier = (Identifier) ARMOR_TEXTURE_CACHE.get(s1); + + if (armorTextureIdentifier == null) { + armorTextureIdentifier = new Identifier(s1); + ARMOR_TEXTURE_CACHE.put(s1, armorTextureIdentifier); + } + + return armorTextureIdentifier; + } +} diff --git a/patchwork-extensions-item/src/main/resources/patchwork-extensions-item.mixins.json b/patchwork-extensions-item/src/main/resources/patchwork-extensions-item.mixins.json index 1de9eaae..055b178b 100644 --- a/patchwork-extensions-item/src/main/resources/patchwork-extensions-item.mixins.json +++ b/patchwork-extensions-item/src/main/resources/patchwork-extensions-item.mixins.json @@ -8,10 +8,13 @@ "MixinEnchantedBookItem", "MixinItem", "MixinItemSettings", + "MixinPlayerInventory", "MixinPotionItems", "MixinSpawnEggItem" ], "client": [ + "client.MixinArmorBipedFeatureRenderer", + "client.MixinArmorFeatureRenderer", "client.MixinItem", "client.MixinItemSettings" ], diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 4454ff43..3d7e5f8f 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -12,6 +12,7 @@ dependencies { implementation project(path: ':patchwork-events-world', configuration: 'dev') implementation project(path: ':patchwork-extensions-block', configuration: 'dev') implementation project(path: ':patchwork-extensions-blockentity', configuration: 'dev') + implementation project(path: ':patchwork-extensions-item', configuration: 'dev') implementation project(path: ':patchwork-loot', configuration: 'dev') implementation project(path: ':patchwork-networking', configuration: 'dev') } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index 2c48048d..213953b4 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -23,18 +23,32 @@ import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.color.item.ItemColors; +import net.minecraft.client.render.entity.model.BipedEntityModel; import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; import net.minecraft.client.Mouse; import net.patchworkmc.impl.event.input.InputEvents; import net.patchworkmc.impl.event.render.RenderEvents; +import net.patchworkmc.impl.extensions.item.PatchworkArmorItemHandler; /* * Note: this class is intended for mod use only, to dispatch to the implementations kept in their own modules. * Do not keep implementation details here, methods should be thin wrappers around methods in other modules. */ public class ForgeHooksClient { + public static String getArmorTexture(Entity entity, ItemStack armor, String defaultTexture, EquipmentSlot slot, String type) { + return PatchworkArmorItemHandler.patchwork$getArmorTexture(entity, armor, defaultTexture, slot, type); + } + + public static > A getArmorModel(LivingEntity livingEntity, ItemStack itemStack, EquipmentSlot slot, A defaultModel) { + return PatchworkArmorItemHandler.patchwork$getArmorModel(livingEntity, itemStack, slot, defaultModel); + } + public static void fireMouseInput(int button, int action, int mods) { InputEvents.fireMouseInput(button, action, mods); } diff --git a/patchwork-god-classes/src/main/resources/fabric.mod.json b/patchwork-god-classes/src/main/resources/fabric.mod.json index 48b20d56..30c69459 100644 --- a/patchwork-god-classes/src/main/resources/fabric.mod.json +++ b/patchwork-god-classes/src/main/resources/fabric.mod.json @@ -24,6 +24,7 @@ "patchwork-events-rendering": "*", "patchwork-events-world": "*", "patchwork-extensions-block": "*", + "patchwork-extensions-item": "*", "patchwork-loot": "*" }, "custom": { From 04cbc4c8544b6627dde0b2903e8ff505bf6e457e Mon Sep 17 00:00:00 2001 From: William Bradford Larcombe Date: Thu, 20 Aug 2020 22:32:43 +0000 Subject: [PATCH 54/73] Add forge energy (#180) * Add forge energy Pretty much exact from YarnForge, with formatting changes * Fix license * Update fabric.mod.json * Move energy to patchwork-capabilities * Remove patchwork-energy --- .../energy/CapabilityEnergy.java | 55 ++++++++++ .../minecraftforge/energy/EnergyStorage.java | 103 ++++++++++++++++++ .../minecraftforge/energy/IEnergyStorage.java | 74 +++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 patchwork-capabilities/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java create mode 100644 patchwork-capabilities/src/main/java/net/minecraftforge/energy/EnergyStorage.java create mode 100644 patchwork-capabilities/src/main/java/net/minecraftforge/energy/IEnergyStorage.java diff --git a/patchwork-capabilities/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java b/patchwork-capabilities/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java new file mode 100644 index 00000000..387831d5 --- /dev/null +++ b/patchwork-capabilities/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java @@ -0,0 +1,55 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.energy; + +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.Capability.IStorage; +import net.minecraftforge.common.capabilities.CapabilityInject; +import net.minecraftforge.common.capabilities.CapabilityManager; + +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.Tag; +import net.minecraft.util.math.Direction; + +public class CapabilityEnergy { + @CapabilityInject(IEnergyStorage.class) + public static Capability ENERGY = null; + + public static void register() { + CapabilityManager.INSTANCE.register(IEnergyStorage.class, new IStorage() { + @Override + public Tag writeNBT(Capability capability, IEnergyStorage instance, Direction side) { + return new IntTag(instance.getEnergyStored()); + } + + @Override + public void readNBT(Capability capability, IEnergyStorage instance, Direction side, Tag nbt) { + if (!(instance instanceof EnergyStorage)) { + throw new IllegalArgumentException("Can not deserialize to an instance that isn't the default implementation"); + } + + ((EnergyStorage) instance).energy = ((IntTag) nbt).getInt(); + } + }, + () -> new EnergyStorage(1000) + ); + } +} + diff --git a/patchwork-capabilities/src/main/java/net/minecraftforge/energy/EnergyStorage.java b/patchwork-capabilities/src/main/java/net/minecraftforge/energy/EnergyStorage.java new file mode 100644 index 00000000..d291cb52 --- /dev/null +++ b/patchwork-capabilities/src/main/java/net/minecraftforge/energy/EnergyStorage.java @@ -0,0 +1,103 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.energy; + +/** + *

Reference implementation of {@link IEnergyStorage}. Use/extend this or implement your own.

+ * + *

Derived from the Redstone Flux power system designed by King Lemming and originally utilized in Thermal Expansion and related mods. + * Created with consent and permission of King Lemming and Team CoFH. Released with permission under LGPL 2.1 when bundled with Forge.

+ */ +public class EnergyStorage implements IEnergyStorage { + protected int energy; + protected int capacity; + protected int maxReceive; + protected int maxExtract; + + public EnergyStorage(int capacity) { + this(capacity, capacity, capacity, 0); + } + + public EnergyStorage(int capacity, int maxTransfer) { + this(capacity, maxTransfer, maxTransfer, 0); + } + + public EnergyStorage(int capacity, int maxReceive, int maxExtract) { + this(capacity, maxReceive, maxExtract, 0); + } + + public EnergyStorage(int capacity, int maxReceive, int maxExtract, int energy) { + this.capacity = capacity; + this.maxReceive = maxReceive; + this.maxExtract = maxExtract; + this.energy = Math.max(0, Math.min(capacity, energy)); + } + + @Override + public int receiveEnergy(int maxReceive, boolean simulate) { + if (!canReceive()) { + return 0; + } + + int energyReceived = Math.min(capacity - energy, Math.min(this.maxReceive, maxReceive)); + + if (!simulate) { + energy += energyReceived; + } + + return energyReceived; + } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) { + if (!canExtract()) { + return 0; + } + + int energyExtracted = Math.min(energy, Math.min(this.maxExtract, maxExtract)); + + if (!simulate) { + energy -= energyExtracted; + } + + return energyExtracted; + } + + @Override + public int getEnergyStored() { + return energy; + } + + @Override + public int getMaxEnergyStored() { + return capacity; + } + + @Override + public boolean canExtract() { + return this.maxExtract > 0; + } + + @Override + public boolean canReceive() { + return this.maxReceive > 0; + } +} + diff --git a/patchwork-capabilities/src/main/java/net/minecraftforge/energy/IEnergyStorage.java b/patchwork-capabilities/src/main/java/net/minecraftforge/energy/IEnergyStorage.java new file mode 100644 index 00000000..e47b20dd --- /dev/null +++ b/patchwork-capabilities/src/main/java/net/minecraftforge/energy/IEnergyStorage.java @@ -0,0 +1,74 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.energy; + +/** + *

An energy storage is the unit of interaction with Energy inventories.

+ * + *

A reference implementation can be found at {@link EnergyStorage}.

+ * + *

Derived from the Redstone Flux power system designed by King Lemming and originally utilized in Thermal Expansion and related mods. + * Created with consent and permission of King Lemming and Team CoFH. Released with permission under LGPL 2.1 when bundled with Forge.

+ */ +public interface IEnergyStorage { + /** + * Adds energy to the storage. Returns quantity of energy that was accepted. + * + * @param maxReceive + * Maximum amount of energy to be inserted. + * @param simulate + * If TRUE, the insertion will only be simulated. + * @return Amount of energy that was (or would have been, if simulated) accepted by the storage. + */ + int receiveEnergy(int maxReceive, boolean simulate); + + /** + * Removes energy from the storage. Returns quantity of energy that was removed. + * + * @param maxExtract + * Maximum amount of energy to be extracted. + * @param simulate + * If TRUE, the extraction will only be simulated. + * @return Amount of energy that was (or would have been, if simulated) extracted from the storage. + */ + int extractEnergy(int maxExtract, boolean simulate); + + /** + * Returns the amount of energy currently stored. + */ + int getEnergyStored(); + + /** + * Returns the maximum amount of energy that can be stored. + */ + int getMaxEnergyStored(); + + /** + * Returns if this storage can have energy extracted. + * If this is false, then any calls to extractEnergy will return 0. + */ + boolean canExtract(); + + /** + * Used to determine if this storage can receive energy. + * If this is false, then any calls to receiveEnergy will return 0. + */ + boolean canReceive(); +} From b9a9155e94313af064801793b5f2cd170378ad45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rikka0=5F0=E5=B0=8F=E5=85=AD=E8=8A=B1?= <929513338@qq.com> Date: Sat, 22 Aug 2020 06:10:22 +1000 Subject: [PATCH 55/73] Impl RenderPlayerEvent (#183) --- .../client/event/RenderPlayerEvent.java | 79 +++++++++++++++++++ .../entity/MixinPlayerEntityRenderer.java | 50 ++++++++++++ .../src/main/resources/fabric.mod.json | 1 + .../patchwork-events-entity.mixins.json | 3 +- 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/client/event/RenderPlayerEvent.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinPlayerEntityRenderer.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/client/event/RenderPlayerEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/client/event/RenderPlayerEvent.java new file mode 100644 index 00000000..36346cd3 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/client/event/RenderPlayerEvent.java @@ -0,0 +1,79 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.event; + +import net.minecraftforge.event.entity.player.PlayerEvent; + +import net.minecraft.client.render.entity.PlayerEntityRenderer; +import net.minecraft.entity.player.PlayerEntity; + +public abstract class RenderPlayerEvent extends PlayerEvent { + private final PlayerEntityRenderer renderer; + private final float partialRenderTick; + private final double x; + private final double y; + private final double z; + + public RenderPlayerEvent(PlayerEntity player, PlayerEntityRenderer renderer, float partialRenderTick, double x, double y, double z) { + super(player); + this.renderer = renderer; + this.partialRenderTick = partialRenderTick; + this.x = x; + this.y = y; + this.z = z; + } + + public PlayerEntityRenderer getRenderer() { + return renderer; + } + + public float getPartialRenderTick() { + return partialRenderTick; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } + + public static class Pre extends RenderPlayerEvent { + public Pre(PlayerEntity player, PlayerEntityRenderer renderer, float tick, double x, double y, double z) { + super(player, renderer, tick, x, y, z); + } + + @Override + public boolean isCancelable() { + return true; + } + } + + public static class Post extends RenderPlayerEvent { + public Post(PlayerEntity player, PlayerEntityRenderer renderer, float tick, double x, double y, double z) { + super(player, renderer, tick, x, y, z); + } + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinPlayerEntityRenderer.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinPlayerEntityRenderer.java new file mode 100644 index 00000000..2096e1ed --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinPlayerEntityRenderer.java @@ -0,0 +1,50 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import net.minecraftforge.client.event.RenderPlayerEvent; +import net.minecraftforge.common.MinecraftForge; + +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.render.entity.PlayerEntityRenderer; + +@Mixin(PlayerEntityRenderer.class) +public class MixinPlayerEntityRenderer { + @Inject(method = "render", at = @At(value = "INVOKE", ordinal = 0, shift = Shift.BEFORE, + target = "net/minecraft/client/network/AbstractClientPlayerEntity.isInSneakingPose()Z"), cancellable = true) + private void preRender(AbstractClientPlayerEntity playerEntity, double x, double y, double z, float entityYaw, float partialTicks, CallbackInfo ci) { + PlayerEntityRenderer me = (PlayerEntityRenderer) (Object) this; + + if (MinecraftForge.EVENT_BUS.post(new RenderPlayerEvent.Pre(playerEntity, me, partialTicks, x, y, z))) { + ci.cancel(); + } + } + + @Inject(method = "render", at = @At("RETURN")) + private void postRender(AbstractClientPlayerEntity playerEntity, double x, double y, double z, float entityYaw, float partialTicks, CallbackInfo ci) { + PlayerEntityRenderer me = (PlayerEntityRenderer) (Object) this; + MinecraftForge.EVENT_BUS.post(new RenderPlayerEvent.Post(playerEntity, me, partialTicks, x, y, z)); + } +} diff --git a/patchwork-events-entity/src/main/resources/fabric.mod.json b/patchwork-events-entity/src/main/resources/fabric.mod.json index f3a9aaed..50574655 100644 --- a/patchwork-events-entity/src/main/resources/fabric.mod.json +++ b/patchwork-events-entity/src/main/resources/fabric.mod.json @@ -17,6 +17,7 @@ }, "depends": { "patchwork-api-base": "*", + "patchwork-extensions": "*", "patchwork-extensions-item": "*" }, "mixins": [ diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 55275923..57860500 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -31,7 +31,8 @@ "MixinClientPlayerEntity", "MixinClientWorld", "MixinItemStack", - "MixinOtherClientPlayerEntity" + "MixinOtherClientPlayerEntity", + "MixinPlayerEntityRenderer" ], "injectors": { "defaultRequire": 1 From c2edb122b29b31543265ffa09a2d17c5cf6b9049 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Sat, 22 Aug 2020 11:24:32 -0500 Subject: [PATCH 56/73] Add CODEOWNERS file. Any org member is encourage --- .github/CODEOWNERS | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..0a413089 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,8 @@ +# Current Lead +* @theglitch76 + +# Maintainers of specific modules. +# Add the current lead to the end of each, because specific overrules general. +# Any org member is encouraged to add themselves to this file when creating a new module, +# but it's not required. +/patchwork-enum-hacks/ @NuclearFarts @theglitch76 From dc6fe553739705a385e84a985bbff51d7fd992de Mon Sep 17 00:00:00 2001 From: William Bradford Larcombe Date: Mon, 31 Aug 2020 18:29:28 +0000 Subject: [PATCH 57/73] Add EntityItemPickupEvent and EntityTravelToDimensionEvent (#179) * Add EntityItemPickupEvent (It should really be named ItemEntityPickupEvent but w/e) * Add EntityTravelToDimensionEvent * Fix checkstyle * Add Forge behavioural change w.r.t teleporting `StorageMinecartEntity`s --- .../entity/EntityTravelToDimensionEvent.java | 56 +++++++++++++++++++ .../entity/player/EntityItemPickupEvent.java | 56 +++++++++++++++++++ .../impl/event/entity/EntityEvents.java | 20 +++++++ .../impl/event/entity/PlayerEvents.java | 12 ++++ .../mixin/event/entity/MixinEntity.java | 12 ++++ .../mixin/event/entity/MixinItemEntity.java | 23 +++++++- .../event/entity/MixinServerPlayerEntity.java | 32 ++++++++++- .../entity/StorageMinecartEntityAccessor.java | 31 ++++++++++ .../patchwork-events-entity.mixins.json | 3 +- .../net/minecraftforge/common/ForgeHooks.java | 5 ++ .../event/ForgeEventFactory.java | 6 ++ 11 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/EntityTravelToDimensionEvent.java create mode 100644 patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/EntityItemPickupEvent.java create mode 100644 patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/StorageMinecartEntityAccessor.java diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/EntityTravelToDimensionEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/EntityTravelToDimensionEvent.java new file mode 100644 index 00000000..104695f8 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/EntityTravelToDimensionEvent.java @@ -0,0 +1,56 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity; + +import net.minecraftforge.common.MinecraftForge; + +import net.minecraft.entity.Entity; +import net.minecraft.world.dimension.DimensionType; + +/** + *

EntityTravelToDimensionEvent is fired before an Entity travels to a dimension.

+ * + *

{@link #dimension} contains the id of the dimension the entity is traveling to.

+ * + *

This event is cancelable. + * If this event is canceled, the Entity does not travel to the dimension.

+ * + *

This event does not have a result.

+ * + *

This event is fired on the {@link MinecraftForge#EVENT_BUS}.

+ */ +public class EntityTravelToDimensionEvent extends EntityEvent { + private final DimensionType dimension; + + public EntityTravelToDimensionEvent(Entity entity, DimensionType dimension) { + super(entity); + this.dimension = dimension; + } + + public DimensionType getDimension() { + return dimension; + } + + @Override + public boolean isCancelable() { + return true; + } +} + diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/EntityItemPickupEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/EntityItemPickupEvent.java new file mode 100644 index 00000000..508e9b9c --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/EntityItemPickupEvent.java @@ -0,0 +1,56 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.player; + +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; + +/** + *

This event is called when a player collides with a EntityItem on the ground. + * The event can be canceled, and no further processing will be done.

+ * + *

You can set the result of this event to ALLOW which will trigger the + * processing of achievements, FML's event, play the sound, and kill the + * entity if all the items are picked up.

+ * + *

setResult(ALLOW) is the same as the old setHandled()

+ */ +public class EntityItemPickupEvent extends PlayerEvent { + private final ItemEntity item; + + public EntityItemPickupEvent(PlayerEntity player, ItemEntity item) { + super(player); + this.item = item; + } + + public ItemEntity getItem() { + return item; + } + + @Override + public boolean isCancelable() { + return true; + } + + @Override + public boolean hasResult() { + return true; + } +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index e2ee6208..39fc5e20 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -26,6 +26,7 @@ import net.minecraftforge.common.extensions.IForgeItem; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.EntityTravelToDimensionEvent; import net.minecraftforge.event.entity.ProjectileImpactEvent; import net.minecraftforge.event.entity.living.AnimalTameEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; @@ -60,6 +61,7 @@ import net.minecraft.entity.projectile.ExplosiveProjectileEntity; import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.entity.thrown.ThrownEntity; +import net.minecraft.entity.vehicle.StorageMinecartEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; @@ -68,11 +70,14 @@ import net.minecraft.world.IWorld; import net.minecraft.world.MobSpawnerLogic; import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.event.player.UseItemCallback; +import net.patchworkmc.mixin.event.entity.StorageMinecartEntityAccessor; + public class EntityEvents implements ModInitializer { private static final Logger LOGGER = LogManager.getLogger("patchwork-events-entity"); @@ -217,6 +222,21 @@ public static boolean onProjectileImpact(ThrownEntity throwable, HitResult ray) return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent.Throwable(throwable, ray)); } + public static boolean onTravelToDimension(Entity entity, DimensionType dimensionType) { + EntityTravelToDimensionEvent event = new EntityTravelToDimensionEvent(entity, dimensionType); + boolean result = !MinecraftForge.EVENT_BUS.post(event); + + if (!result) { + // Revert variable back to true as it would have been set to false + + if (entity instanceof StorageMinecartEntity) { + ((StorageMinecartEntityAccessor) entity).dropContentsWhenDead(true); + } + } + + return result; + } + @Override public void onInitialize() { UseItemCallback.EVENT.register((player, world, hand) -> { diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java index 2ae93f40..4180f018 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java @@ -20,7 +20,9 @@ package net.patchworkmc.impl.event.entity; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.eventbus.api.Event; import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.PlayerEntity; @@ -56,4 +58,14 @@ public static void firePlayerCraftingEvent(PlayerEntity player, ItemStack crafte public static void firePlayerSmeltedEvent(PlayerEntity player, ItemStack smelted) { MinecraftForge.EVENT_BUS.post(new PlayerEvent.ItemSmeltedEvent(player, smelted)); } + + /** + * + * @return -1 if the event was cancelled, 0 if the event was denied, 1 if the event was accepted + */ + public static int onItemPickup(PlayerEntity player, ItemEntity entityItem) { + Event event = new EntityItemPickupEvent(player, entityItem); + if (MinecraftForge.EVENT_BUS.post(event)) return -1; + return event.getResult() == Event.Result.ALLOW ? 1 : 0; + } } diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinEntity.java index 94513412..1731af44 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinEntity.java @@ -24,12 +24,14 @@ 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.entity.Entity; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityType; import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; import net.patchworkmc.impl.event.entity.EntityEvents; @@ -52,4 +54,14 @@ public void hookConstructor(EntityType type, World world, CallbackInfo ci) { EntityEvents.onEntityConstruct(entity); } + + @Inject(method = "changeDimension", + at = @At("HEAD"), + cancellable = true + ) + void patchwork_fireTravelToDimensionEventChangeDimension(DimensionType newDimension, CallbackInfoReturnable cir) { + if (!EntityEvents.onTravelToDimension((Entity) (Object) this, newDimension)) { + cir.setReturnValue(null); + } + } } diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java index 5f1fccc4..e4ad21b8 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java @@ -21,12 +21,15 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.At.Shift; import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; import net.patchworkmc.impl.event.entity.PlayerEvents; @@ -44,4 +47,22 @@ private void onPlayerPickUpItemEntity(PlayerEntity player, CallbackInfo ci) { ItemEntity me = (ItemEntity) (Object) this; PlayerEvents.firePlayerItemPickupEvent(player, me, me.getStack().copy()); } + + int eventResult; + + @Inject(method = "onPlayerCollision", + at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getCount()I"), + cancellable = true + ) + void patchwork_fireItemPickupEvent(PlayerEntity player, CallbackInfo ci) { + eventResult = PlayerEvents.onItemPickup(player, (ItemEntity) (Object) this); + if (eventResult != 1) ci.cancel(); + } + + @Redirect(method = "onPlayerCollision", + at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerInventory;insertStack(Lnet/minecraft/item/ItemStack;)Z") + ) + boolean patchwork_skipIfEventNotAllowed(PlayerInventory playerInventory, ItemStack stack) { + return eventResult == 1 || playerInventory.insertStack(stack); + } } diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java index 64585ce5..73066402 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java @@ -19,6 +19,7 @@ package net.patchworkmc.mixin.event.entity; +import com.mojang.authlib.GameProfile; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.PlayerEvent; import org.spongepowered.asm.mixin.Mixin; @@ -33,8 +34,10 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.level.LevelProperties; @@ -42,7 +45,11 @@ import net.patchworkmc.impl.event.entity.PlayerEvents; @Mixin(ServerPlayerEntity.class) -public class MixinServerPlayerEntity { +public abstract class MixinServerPlayerEntity extends PlayerEntity { + public MixinServerPlayerEntity(World world, GameProfile profile) { + super(world, profile); + } + @Inject(method = "onDeath", at = @At("HEAD"), cancellable = true) private void hookDeath(DamageSource source, CallbackInfo callback) { LivingEntity entity = (LivingEntity) (Object) this; @@ -59,6 +66,19 @@ private void hookCopyFromForCloneEvent(ServerPlayerEntity oldPlayer, boolean ali MinecraftForge.EVENT_BUS.post(new PlayerEvent.Clone(speThis, oldPlayer, !alive)); } + @Inject(method = "teleport", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/network/ServerPlayerEntity;getServerWorld()Lnet/minecraft/server/world/ServerWorld;" + ), + cancellable = true + ) + void patchwork_fireTravelToDimensionEventTeleport(ServerWorld targetWorld, double x, double y, double z, float yaw, float pitch, CallbackInfo ci) { + if (!EntityEvents.onTravelToDimension(this, targetWorld.dimension.getType())) { + ci.cancel(); + } + } + //////////////////////////////////// // PlayerChangedDimensionEvent //////////////////////////////////// @@ -79,6 +99,16 @@ private void teleport_sendInventory(ServerWorld targetWorld, double x, double y, @Unique private static final ThreadLocal changeDimension_from = new ThreadLocal<>(); + @Inject(method = "changeDimension", + at = @At("HEAD"), + cancellable = true + ) + void patchwork_fireTravelToDimensionEventChangeDimensionPlayer(DimensionType newDimension, CallbackInfoReturnable cir) { + if (!EntityEvents.onTravelToDimension(this, newDimension)) { + cir.setReturnValue(null); + } + } + @Inject(method = "changeDimension", at = @At( value = "INVOKE", diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/StorageMinecartEntityAccessor.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/StorageMinecartEntityAccessor.java new file mode 100644 index 00000000..7a36eb59 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/StorageMinecartEntityAccessor.java @@ -0,0 +1,31 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.entity.vehicle.StorageMinecartEntity; + +@Mixin(StorageMinecartEntity.class) +public interface StorageMinecartEntityAccessor { + @Accessor("field_7733") + void dropContentsWhenDead(boolean value); +} diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 57860500..895bcd44 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -25,7 +25,8 @@ "MixinShulkerBulletEntity", "MixinSpawnHelper", "MixinThrownEntity", - "MixinWorldChunk" + "MixinWorldChunk", + "StorageMinecartEntityAccessor" ], "client": [ "MixinClientPlayerEntity", diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java index 32463d2a..27c554a5 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -28,6 +28,7 @@ import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.eventbus.api.Event; +import net.minecraft.world.dimension.DimensionType; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; import net.minecraft.entity.LivingEntity; @@ -110,6 +111,10 @@ public static boolean onPlayerAttackTarget(PlayerEntity player, Entity target) { return EntityEvents.attackEntity(player, target); } + public static boolean onTravelToDimension(Entity entity, DimensionType dimensionType) { + return EntityEvents.onTravelToDimension(entity, dimensionType); + } + public static int onBlockBreakEvent(World world, GameMode gameType, ServerPlayerEntity entityPlayer, BlockPos pos) { return BlockHarvestManager.onBlockBreakEvent(world, gameType, entityPlayer, pos); } diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index a7745064..cca7bf8f 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -30,6 +30,7 @@ import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.projectile.ExplosiveProjectileEntity; import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.entity.thrown.ThrownEntity; @@ -47,6 +48,7 @@ import net.patchworkmc.impl.capability.CapabilityEvents; import net.patchworkmc.impl.event.entity.EntityEvents; +import net.patchworkmc.impl.event.entity.PlayerEvents; import net.patchworkmc.impl.event.loot.LootEvents; import net.patchworkmc.impl.extensions.block.BlockHarvestManager; @@ -110,4 +112,8 @@ public static boolean onProjectileImpact(ExplosiveProjectileEntity fireball, Hit public static boolean onProjectileImpact(ThrownEntity throwable, HitResult ray) { return EntityEvents.onProjectileImpact(throwable, ray); } + + public static int onItemPickup(ItemEntity item, PlayerEntity player) { + return PlayerEvents.onItemPickup(player, item); + } } From bb69d4e5ea623eee3f377e0a3e3f5f7fe4deda01 Mon Sep 17 00:00:00 2001 From: Glitch Date: Mon, 31 Aug 2020 16:49:56 -0500 Subject: [PATCH 58/73] Faster building, hopefully better actions workflow (#185) * Faster building, hopefully better actions workflow * More!!! * Another test * fix * Hopefully fix Bintray publishing while we're at it * Checkstyle doesn't need to wait until build is done anymore * One last oopsie and we're good for merge. --- .github/workflows/build.yml | 49 +++++-------- .github/workflows/publish.yml | 13 +--- build.gradle | 87 ++++++++++++++++-------- gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- patchwork-extensions-block/build.gradle | 2 +- patchwork-level-generators/build.gradle | 2 +- patchwork-registries/build.gradle | 2 +- patchwork-tags/build.gradle | 2 +- settings.gradle | 1 - 10 files changed, 88 insertions(+), 78 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2af9ce51..bc3ecef5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,57 +8,40 @@ on: jobs: build: + strategy: + matrix: + java-version: [1.8, 11, 14] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: 8 - # https://github.com/actions/cache/blob/master/examples.md#java---gradle - - uses: actions/cache@v2 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-build-${{ hashFiles('**/*.gradle*') }} - restore-keys: | - ${{ runner.os }}-gradle- + java-version: ${{ matrix.java-version }} - uses: eskatos/gradle-command-action@v1 with: + gradle-version: wrapper arguments: remapJar + dependencies-cache-enabled: true + configuration-cache-enabled: false # Artifact publishing - uses: actions/upload-artifact@v2 + # In theory we could publish the j11 or even j14 jar, but let's not take any chances + if: ${{ matrix.java-version == 1.8 }} with: + name: Jar Download path: ./build/libs/patchwork-api-?.?.?.jar - checkstyle: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 - with: - java-version: 8 - - uses: actions/cache@v2 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-checkstyle-${{ hashFiles('**/*.gradle*') }} - restore-keys: | - ${{ runner.os }}-gradle- - - uses: eskatos/gradle-command-action@v1 - with: - arguments: checkstyleMain - license: + check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: 8 - - uses: actions/cache@v2 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-license-${{ hashFiles('**/*.gradle*') }}-license - restore-keys: | - ${{ runner.os }}-gradle- + java-version: 11 - uses: eskatos/gradle-command-action@v1 with: - arguments: checkLicenses + gradle-version: wrapper + arguments: licenseCheck checkstyleMain + dependencies-cache-enabled: true + configuration-cache-enabled: false diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e765b8f6..06f09e04 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,16 +8,6 @@ env: bintray_key: ${{ secrets.bintray_key }} jobs: -# bintray: -# runs-on: ubuntu-latest -# steps: -# - uses: actions/checkout@v1 -# - uses: actions/setup-java@v1 -# with: -# java-version: 8 -# - uses: eskatos/gradle-command-action@v1 -# with: -# arguments: bintrayUpload release: runs-on: ubuntu-latest steps: @@ -43,4 +33,7 @@ jobs: java-version: 8 - uses: eskatos/gradle-command-action@v1 with: + gradle-version: wrapper arguments: bintrayUpload + dependencies-cache-enabled: true + configuration-cache-enabled: false diff --git a/build.gradle b/build.gradle index 16892af4..2b65f1d6 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id 'eclipse' id 'idea' id 'maven-publish' - id 'fabric-loom' version '0.4-SNAPSHOT' apply false + id 'fabric-loom' version '0.5-SNAPSHOT' apply false id 'net.minecrell.licenser' version '0.4.1' id "org.ajoberstar.grgit" version "3.1.1" id 'com.jfrog.bintray' version '1.8.4' @@ -52,6 +52,14 @@ allprojects { group = "net.patchworkmc.patchwork-api" + loom { + shareCaches = true + } + + repositories { + maven { url 'https://dl.bintray.com/patchworkmc/Patchwork-Maven/' } + } + dependencies { minecraft "com.mojang:minecraft:$Globals.mcVersion" mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}:v2" @@ -69,10 +77,6 @@ allprojects { dev } - repositories { - maven { url 'https://dl.bintray.com/patchworkmc/Patchwork-Maven/' } - } - jar { classifier = "dev" } @@ -113,7 +117,7 @@ allprojects { checkstyle { configFile = rootProject.file("checkstyle.xml") - toolVersion = '8.25' + toolVersion = '8.31' } } @@ -136,25 +140,41 @@ subprojects { publishing { publications { - mavenJava(MavenPublication) { - artifact(file("${project.buildDir}/libs/$archivesBaseName-${version}-maven.jar")) { - builtBy remapMavenJar - } - artifact(sourcesJar) { - builtBy remapSourcesJar + create("${archivesBaseName}_mavenJava", MavenPublication) { + afterEvaluate { + artifact(file("${project.buildDir}/libs/$archivesBaseName-${version}-maven.jar")) { + builtBy remapMavenJar + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } } } } + } - repositories { - maven { - url "http://mavenupload.modmuss50.me/" - if (project.hasProperty('mavenPass')) { - credentials { - username 'buildslave' - password project.getProperty('mavenPass') - } - } + bintray { + user = project.hasProperty('bintrayUser') ? project.getProperty('bintrayUser') : System.getenv('bintray_user') + key = project.hasProperty('bintrayKey') ? project.getProperty('bintrayKey') : System.getenv('bintray_key') + publish = true + override = true + publications = ["${archivesBaseName}_mavenJava"] + pkg { + repo = project.bintrayRepo + name = archivesBaseName + user = bintray.user + userOrg = project.repoOwner + licenses = [project.codeLicense] + desc = project.description + websiteUrl = "https://github.com/${project.repoOwner}/${project.repoName}" + issueTrackerUrl = "https://github.com/${project.repoOwner}/${project.repoName}/issues" + vcsUrl = "https://github.com/${project.repoOwner}/${project.repoName}.git" + publicDownloadNumbers = true + + githubRepo = "${project.repoOwner}/${project.repoName}" + version { + name = project.version + released = new Date() } } } @@ -162,13 +182,8 @@ subprojects { javadoc.enabled = false } -task remapMavenJar(type: net.fabricmc.loom.task.RemapJarTask, dependsOn: jar) { - afterEvaluate { - input = file("${project.buildDir}/libs/${archivesBaseName}-${version}-dev.jar") - archiveName = "${archivesBaseName}-${version}-maven.jar" - addNestedDependencies = false - } -} +subprojects.each { bintrayUpload.dependsOn("${it.path}:bintrayUpload") } + bintray { user = project.hasProperty('bintrayUser') ? project.getProperty('bintrayUser') : System.getenv('bintray_user') key = project.hasProperty('bintrayKey') ? project.getProperty('bintrayKey') : System.getenv('bintray_key') @@ -193,7 +208,18 @@ bintray { released = new Date() } } + + javadoc.enabled = false } + +task remapMavenJar(type: net.fabricmc.loom.task.RemapJarTask, dependsOn: jar) { + afterEvaluate { + input = file("${project.buildDir}/libs/${archivesBaseName}-${version}-dev.jar") + archiveName = "${archivesBaseName}-${version}-maven.jar" + addNestedDependencies = false + } +} + publishing { publications { mavenJava(MavenPublication) { @@ -220,6 +246,7 @@ publishing { task licenseFormatAll subprojects {p -> licenseFormatAll.dependsOn("${p.path}:licenseFormat")} subprojects.each {remapJar.dependsOn("${it.path}:remapJar")} + repositories { flatDir { dirs 'jars' @@ -265,6 +292,10 @@ dependencies { } } +loom { + shareCaches = true +} + version = Globals.baseVersion //+ "+" + (ENV.BUILD_NUMBER ? ("build." + ENV.BUILD_NUMBER) : "local") + "-" + getBranch() logger.lifecycle("Building Patchwork: " + version) diff --git a/gradle.properties b/gradle.properties index a4d4b72a..299ec9b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,8 @@ -org.gradle.jvmargs=-Xmx2G +# Gradle needs a lot of memory to build in parallel. +# If you're starved, you can reduce this to 1G and disable parallel building. +org.gradle.jvmargs=-Xmx3G +org.gradle.parallel=true +org.gradle.daemon=false repoName=patchwork-api repoOwner=patchworkmc bintrayRepo=Patchwork-Maven diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0800e755..42c2bc9d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip diff --git a/patchwork-extensions-block/build.gradle b/patchwork-extensions-block/build.gradle index 94c92392..5aa27099 100644 --- a/patchwork-extensions-block/build.gradle +++ b/patchwork-extensions-block/build.gradle @@ -8,6 +8,6 @@ dependencies { implementation project(path: ':patchwork-tooltype', configuration: 'dev') } -minecraft { +loom { accessWidener "src/main/resources/patchwork-extensions-block.accesswidener" } diff --git a/patchwork-level-generators/build.gradle b/patchwork-level-generators/build.gradle index a7cf6271..1f95fe0f 100644 --- a/patchwork-level-generators/build.gradle +++ b/patchwork-level-generators/build.gradle @@ -7,6 +7,6 @@ dependencies { implementation project(path: ':patchwork-events-world', configuration: 'dev') } -minecraft { +loom { accessWidener "src/main/resources/patchwork-level-generators.accesswidener" } diff --git a/patchwork-registries/build.gradle b/patchwork-registries/build.gradle index 7be4dbc8..9f39bae5 100644 --- a/patchwork-registries/build.gradle +++ b/patchwork-registries/build.gradle @@ -6,6 +6,6 @@ dependencies { implementation project(path: ':patchwork-fml', configuration: 'dev') } -minecraft { +loom { accessWidener "src/main/resources/patchwork-registries.accesswidener" } diff --git a/patchwork-tags/build.gradle b/patchwork-tags/build.gradle index 5d8ca819..966af4df 100644 --- a/patchwork-tags/build.gradle +++ b/patchwork-tags/build.gradle @@ -5,6 +5,6 @@ dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') } -minecraft { +loom { accessWidener "src/main/resources/patchwork-tags.accesswidener" } diff --git a/settings.gradle b/settings.gradle index 015e7123..da38dba2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -45,4 +45,3 @@ include 'patchwork-resource' include 'patchwork-tags' include 'patchwork-tooltype' include 'patchwork-vanilla-patches' - From f04a2d53e6e988d1400684e65cf781ac9362dc16 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Mon, 31 Aug 2020 16:54:21 -0500 Subject: [PATCH 59/73] Patchwork v0.9.0 For the full changelog see https://github.com/PatchworkMC/patchwork-api/compare/v0.8.0...v0.9.0 This release is notable for (hopefully) being the first version with a maven publication that isn't broken. Development pace has significantly slowed as school starts back up--don't expect to see a whole lot from us until winter. 1.15 will happen! It is currently waiting on some changes to Patcher to be written before we can start on API. If you'd like to contribute, please join our [discord](https://discord.gg/YYZtNBG) and we can get you started. --- build.gradle | 2 +- patchwork-capabilities/build.gradle | 2 +- patchwork-dispatcher/build.gradle | 2 +- patchwork-events-entity/build.gradle | 2 +- patchwork-events-lifecycle/build.gradle | 2 +- patchwork-events-rendering/build.gradle | 2 +- patchwork-events-world/build.gradle | 2 +- patchwork-extensions-block/build.gradle | 2 +- patchwork-extensions-item/build.gradle | 2 +- patchwork-fml/build.gradle | 2 +- patchwork-god-classes/build.gradle | 2 +- patchwork-model-loader/build.gradle | 2 +- patchwork-networking-messages/build.gradle | 2 +- patchwork-networking/build.gradle | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 2b65f1d6..4f59dbba 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ plugins { def ENV = System.getenv() class Globals { - static def baseVersion = "0.8.0" + static def baseVersion = "0.9.0" static def mcVersion = "1.14.4" static def yarnVersion = "+build.16" } diff --git a/patchwork-capabilities/build.gradle b/patchwork-capabilities/build.gradle index 0a376f19..d01ea5fd 100644 --- a/patchwork-capabilities/build.gradle +++ b/patchwork-capabilities/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-capabilities" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.4.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-dispatcher/build.gradle b/patchwork-dispatcher/build.gradle index db3030b2..34ec3ee5 100644 --- a/patchwork-dispatcher/build.gradle +++ b/patchwork-dispatcher/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-dispatcher" -version = getSubprojectVersion(project, "0.4.0") +version = getSubprojectVersion(project, "0.4.1") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-entity/build.gradle b/patchwork-events-entity/build.gradle index 60c8a0a1..a403607b 100644 --- a/patchwork-events-entity/build.gradle +++ b/patchwork-events-entity/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-events-entity" -version = getSubprojectVersion(project, "0.5.0") +version = getSubprojectVersion(project, "0.6.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-lifecycle/build.gradle b/patchwork-events-lifecycle/build.gradle index 6991be53..3ffddffa 100644 --- a/patchwork-events-lifecycle/build.gradle +++ b/patchwork-events-lifecycle/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-events-lifecycle" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.3.1") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-rendering/build.gradle b/patchwork-events-rendering/build.gradle index 16784a5e..adb09277 100644 --- a/patchwork-events-rendering/build.gradle +++ b/patchwork-events-rendering/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-client-colors" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.3.1") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-events-world/build.gradle b/patchwork-events-world/build.gradle index b8809b37..7f45ad89 100644 --- a/patchwork-events-world/build.gradle +++ b/patchwork-events-world/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-events-world" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.4.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-extensions-block/build.gradle b/patchwork-extensions-block/build.gradle index 5aa27099..69bbc8e6 100644 --- a/patchwork-extensions-block/build.gradle +++ b/patchwork-extensions-block/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-extensions-block" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.4.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-extensions-item/build.gradle b/patchwork-extensions-item/build.gradle index a7ef0341..8dbba5a0 100644 --- a/patchwork-extensions-item/build.gradle +++ b/patchwork-extensions-item/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-extensions-item" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.4.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-fml/build.gradle b/patchwork-fml/build.gradle index f4fcac45..4a4e6b27 100644 --- a/patchwork-fml/build.gradle +++ b/patchwork-fml/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-fml" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.4.0") dependencies { implementation 'com.electronwill.night-config:toml:3.6.2' diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 3d7e5f8f..9e6b8561 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-god-classes" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.3.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-model-loader/build.gradle b/patchwork-model-loader/build.gradle index 9c1c13d0..77fa2553 100644 --- a/patchwork-model-loader/build.gradle +++ b/patchwork-model-loader/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-model-loader" -version = getSubprojectVersion(project, "0.2.0") +version = getSubprojectVersion(project, "0.2.1") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-networking-messages/build.gradle b/patchwork-networking-messages/build.gradle index c88ad201..e1019e69 100644 --- a/patchwork-networking-messages/build.gradle +++ b/patchwork-networking-messages/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-networking-messages" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.3.1") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') diff --git a/patchwork-networking/build.gradle b/patchwork-networking/build.gradle index 3a995a3b..8598ae7f 100644 --- a/patchwork-networking/build.gradle +++ b/patchwork-networking/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "patchwork-networking" -version = getSubprojectVersion(project, "0.3.0") +version = getSubprojectVersion(project, "0.4.0") dependencies { implementation project(path: ':patchwork-api-base', configuration: 'dev') From a27cc352a048213422a685b4e8d17ee367884e8c Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Mon, 31 Aug 2020 17:14:23 -0500 Subject: [PATCH 60/73] Patchwork v0.9.1 This is a bugfix release, see https://github.com/PatchworkMC/patchwork-api/releases/tag/v0.9.0 for the changelog since the previous major release. This version fixes some errors involving publishing artifacts. --- .github/workflows/build.yml | 2 +- .github/workflows/publish.yml | 8 +++----- build.gradle | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc3ecef5..63e9c8da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: - uses: eskatos/gradle-command-action@v1 with: gradle-version: wrapper - arguments: remapJar + arguments: build dependencies-cache-enabled: true configuration-cache-enabled: false # Artifact publishing diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 06f09e04..5ee48a18 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,12 +17,10 @@ jobs: java-version: 8 - uses: eskatos/gradle-command-action@v1 with: - arguments: remapJar - - name: Delete -dev jar - run: rm ./build/libs/patchwork-api-*-dev.jar - - uses: ncipollo/release-action@v1.4.0 + arguments: build + - uses: ncipollo/release-action@v1 with: - artifacts: ./build/libs/patchwork-api-*.jar + artifacts: ./build/libs/patchwork-api-?.?.?.jar token: ${{ secrets.GITHUB_TOKEN }} bintray: runs-on: ubuntu-latest diff --git a/build.gradle b/build.gradle index 4f59dbba..ff9c2002 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ plugins { def ENV = System.getenv() class Globals { - static def baseVersion = "0.9.0" + static def baseVersion = "0.9.1" static def mcVersion = "1.14.4" static def yarnVersion = "+build.16" } @@ -46,7 +46,7 @@ allprojects { apply plugin: 'maven-publish' apply plugin: 'fabric-loom' apply plugin: 'net.minecrell.licenser' - + apply plugin: 'com.jfrog.bintray' sourceCompatibility = 1.8 targetCompatibility = 1.8 From daef992960d28407cfd83e677850639b81505f0b Mon Sep 17 00:00:00 2001 From: William Bradford Larcombe Date: Fri, 4 Sep 2020 18:13:29 +0100 Subject: [PATCH 61/73] Add @williambl as codeowner for fake-players (#187) --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0a413089..1c1dad22 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,3 +6,4 @@ # Any org member is encouraged to add themselves to this file when creating a new module, # but it's not required. /patchwork-enum-hacks/ @NuclearFarts @theglitch76 +/patchwork-fake-players/ @williambl @theglitch76 From 5ad67b2324240f78f2455939a54bcc1c09bf9701 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Sat, 5 Sep 2020 16:36:07 -0500 Subject: [PATCH 62/73] Patchwork v0.9.2 This is a bugfix release, see https://github.com/PatchworkMC/patchwork-api/releases/tag/v0.9.0 for the changelog since the previous major release. This version fixes the (hopefully) last publishing error, and some other issues in the Github Actions workflows. --- .github/workflows/build.yml | 2 +- build.gradle | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 63e9c8da..1d7687fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: - uses: eskatos/gradle-command-action@v1 with: gradle-version: wrapper - arguments: build + arguments: build -x check dependencies-cache-enabled: true configuration-cache-enabled: false # Artifact publishing diff --git a/build.gradle b/build.gradle index ff9c2002..2b51bcb6 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,9 @@ class Globals { static def mcVersion = "1.14.4" static def yarnVersion = "+build.16" } +version = Globals.baseVersion //+ "+" + (ENV.BUILD_NUMBER ? ("build." + ENV.BUILD_NUMBER) : "local") + "-" + getBranch() + +logger.lifecycle("Building Patchwork: " + version) def getSubprojectVersion(project, version) { if (grgit == null) { @@ -296,8 +299,4 @@ loom { shareCaches = true } -version = Globals.baseVersion //+ "+" + (ENV.BUILD_NUMBER ? ("build." + ENV.BUILD_NUMBER) : "local") + "-" + getBranch() - -logger.lifecycle("Building Patchwork: " + version) - apply from: 'https://github.com/FabricMC/fabric-docs/raw/master/gradle/ideconfig.gradle' From 56022985ab917f83ff1851112fa62ba7f153aa85 Mon Sep 17 00:00:00 2001 From: William Bradford Larcombe Date: Mon, 7 Sep 2020 15:43:40 +0100 Subject: [PATCH 63/73] Fix energy capability not being registered and mark `@CapabilityInject` as deprecated (#186) * Fix energy capability not being registered * Fix checkstyle + license * Mark `@CapabilityInject` as deprecated --- .../common/capabilities/CapabilityInject.java | 5 +++ .../energy/CapabilityEnergy.java | 6 ++-- .../capability/PatchworkCapabilities.java | 31 +++++++++++++++++++ .../src/main/resources/fabric.mod.json | 5 +++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/PatchworkCapabilities.java diff --git a/patchwork-capabilities/src/main/java/net/minecraftforge/common/capabilities/CapabilityInject.java b/patchwork-capabilities/src/main/java/net/minecraftforge/common/capabilities/CapabilityInject.java index eb6c4fc9..5fcb3a99 100644 --- a/patchwork-capabilities/src/main/java/net/minecraftforge/common/capabilities/CapabilityInject.java +++ b/patchwork-capabilities/src/main/java/net/minecraftforge/common/capabilities/CapabilityInject.java @@ -24,6 +24,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import net.patchworkmc.api.capability.CapabilityRegisteredCallback; + /** * When placed on a field, the field will be set to an * instance of {@link Capability} once that capability is registered. @@ -48,9 +50,12 @@ * * Warning: Capability injections are run in the thread that the capability is registered. * Due to parallel mod loading, this can potentially be off of the main thread. + * + * @deprecated Don't use this in patchwork - use {@link CapabilityRegisteredCallback}. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) +@Deprecated public @interface CapabilityInject { /** * The capability interface to listen for registration. diff --git a/patchwork-capabilities/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java b/patchwork-capabilities/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java index 387831d5..1f366d2c 100644 --- a/patchwork-capabilities/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java +++ b/patchwork-capabilities/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java @@ -21,18 +21,20 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability.IStorage; -import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraft.nbt.IntTag; import net.minecraft.nbt.Tag; import net.minecraft.util.math.Direction; +import net.patchworkmc.api.capability.CapabilityRegisteredCallback; + public class CapabilityEnergy { - @CapabilityInject(IEnergyStorage.class) public static Capability ENERGY = null; public static void register() { + CapabilityRegisteredCallback.event(IEnergyStorage.class).register(cap -> ENERGY = cap); + CapabilityManager.INSTANCE.register(IEnergyStorage.class, new IStorage() { @Override public Tag writeNBT(Capability capability, IEnergyStorage instance, Direction side) { diff --git a/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/PatchworkCapabilities.java b/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/PatchworkCapabilities.java new file mode 100644 index 00000000..0f27ddef --- /dev/null +++ b/patchwork-capabilities/src/main/java/net/patchworkmc/impl/capability/PatchworkCapabilities.java @@ -0,0 +1,31 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.impl.capability; + +import net.minecraftforge.energy.CapabilityEnergy; + +import net.fabricmc.api.ModInitializer; + +public class PatchworkCapabilities implements ModInitializer { + @Override + public void onInitialize() { + CapabilityEnergy.register(); + } +} diff --git a/patchwork-capabilities/src/main/resources/fabric.mod.json b/patchwork-capabilities/src/main/resources/fabric.mod.json index 09d3abf5..c690e4cf 100644 --- a/patchwork-capabilities/src/main/resources/fabric.mod.json +++ b/patchwork-capabilities/src/main/resources/fabric.mod.json @@ -18,6 +18,11 @@ "mixins": [ "patchwork-capabilities.mixins.json" ], + "entrypoints": { + "main": [ + "net.patchworkmc.impl.capability.PatchworkCapabilities" + ] + }, "description": "Implementation of the Forge Capabilities API", "custom": { "modmenu:api": true, From ccbaadd88280914d63a76f79ac8c78a6c8d241af Mon Sep 17 00:00:00 2001 From: Rikka0w0 <929513338@qq.com> Date: Tue, 8 Sep 2020 01:23:51 +1000 Subject: [PATCH 64/73] Fix issue #188 and rectify some fabric.mod.json problems --- patchwork-extensions-blockentity/build.gradle | 5 ++- .../ForgeBlockEntityRenderDispatcher.java | 30 ------------- .../MixinBlockEntityRenderDispatcher.java | 43 ------------------- .../src/main/resources/fabric.mod.json | 3 +- ...tchwork-extensions-blockentity.mixins.json | 1 - patchwork-god-classes/build.gradle | 1 - .../fml/client/registry/ClientRegistry.java | 40 ----------------- .../src/main/resources/fabric.mod.json | 3 +- .../fml/client/registry/ClientRegistry.java | 3 +- 9 files changed, 8 insertions(+), 121 deletions(-) delete mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderDispatcher.java delete mode 100644 patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderDispatcher.java delete mode 100644 patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java diff --git a/patchwork-extensions-blockentity/build.gradle b/patchwork-extensions-blockentity/build.gradle index 500f2044..461a47ad 100644 --- a/patchwork-extensions-blockentity/build.gradle +++ b/patchwork-extensions-blockentity/build.gradle @@ -1,6 +1,7 @@ archivesBaseName = "patchwork-extensions-blockentity" -version = getSubprojectVersion(project, "0.1.0") +version = getSubprojectVersion(project, "0.1.1") dependencies { - compile project(path: ':patchwork-capabilities', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-capabilities', configuration: 'dev') } diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderDispatcher.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderDispatcher.java deleted file mode 100644 index cb0bf57a..00000000 --- a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/impl/extensions/blockentity/ForgeBlockEntityRenderDispatcher.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.impl.extensions.blockentity; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.render.block.entity.BlockEntityRenderer; - -public interface ForgeBlockEntityRenderDispatcher { - /** - * Forge Internal, Do not call, Use ClientRegistry. - */ - void setSpecialRenderer(Class clsBlockEntity, BlockEntityRenderer ber); -} diff --git a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderDispatcher.java b/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderDispatcher.java deleted file mode 100644 index f9fc5300..00000000 --- a/patchwork-extensions-blockentity/src/main/java/net/patchworkmc/mixin/extensions/blockentity/MixinBlockEntityRenderDispatcher.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.patchworkmc.mixin.extensions.blockentity; - -import java.util.Map; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; -import net.minecraft.client.render.block.entity.BlockEntityRenderer; - -import net.patchworkmc.impl.extensions.blockentity.ForgeBlockEntityRenderDispatcher; - -@Mixin(BlockEntityRenderDispatcher.class) -public abstract class MixinBlockEntityRenderDispatcher implements ForgeBlockEntityRenderDispatcher { - @Shadow - @Final - private Map, BlockEntityRenderer> renderers; - - public synchronized void setSpecialRenderer(Class clsBlockEntity, BlockEntityRenderer ber) { - renderers.put(clsBlockEntity, ber); - } -} diff --git a/patchwork-extensions-blockentity/src/main/resources/fabric.mod.json b/patchwork-extensions-blockentity/src/main/resources/fabric.mod.json index dd6c5ed2..9547905f 100644 --- a/patchwork-extensions-blockentity/src/main/resources/fabric.mod.json +++ b/patchwork-extensions-blockentity/src/main/resources/fabric.mod.json @@ -11,7 +11,8 @@ "license": "LGPL-2.1-only", "environment": "*", "depends": { - "fabricloader": ">=0.8.4" + "patchwork-api-base": "*", + "patchwork-capabilities": "*" }, "mixins": [ "patchwork-extensions-blockentity.mixins.json" diff --git a/patchwork-extensions-blockentity/src/main/resources/patchwork-extensions-blockentity.mixins.json b/patchwork-extensions-blockentity/src/main/resources/patchwork-extensions-blockentity.mixins.json index a9b886fa..ec5fd316 100644 --- a/patchwork-extensions-blockentity/src/main/resources/patchwork-extensions-blockentity.mixins.json +++ b/patchwork-extensions-blockentity/src/main/resources/patchwork-extensions-blockentity.mixins.json @@ -8,7 +8,6 @@ ], "client": [ "MixinClientPlayNetworkHandler", - "MixinBlockEntityRenderDispatcher", "MixinBlockEntityRenderer", "MixinWorldRenderer" ], diff --git a/patchwork-god-classes/build.gradle b/patchwork-god-classes/build.gradle index 9e6b8561..da0360f2 100644 --- a/patchwork-god-classes/build.gradle +++ b/patchwork-god-classes/build.gradle @@ -11,7 +11,6 @@ dependencies { implementation project(path: ':patchwork-events-rendering', configuration: 'dev') implementation project(path: ':patchwork-events-world', configuration: 'dev') implementation project(path: ':patchwork-extensions-block', configuration: 'dev') - implementation project(path: ':patchwork-extensions-blockentity', configuration: 'dev') implementation project(path: ':patchwork-extensions-item', configuration: 'dev') implementation project(path: ':patchwork-loot', configuration: 'dev') implementation project(path: ':patchwork-networking', configuration: 'dev') diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java b/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java deleted file mode 100644 index fa253e5c..00000000 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Minecraft Forge, Patchwork Project - * Copyright (c) 2016-2020, 2019-2020 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.fml.client.registry; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; -import net.minecraft.client.render.block.entity.BlockEntityRenderer; - -import net.patchworkmc.impl.extensions.blockentity.ForgeBlockEntityRenderDispatcher; - -public class ClientRegistry { - /** - * Registers a Tile Entity renderer. Call this during - * {@link net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent}. This - * method is safe to call during parallel mod loading. - */ - public static synchronized void bindTileEntityRenderer( - Class clsBlockEntity, BlockEntityRenderer specialRenderer) { - ((ForgeBlockEntityRenderDispatcher) BlockEntityRenderDispatcher.INSTANCE).setSpecialRenderer(clsBlockEntity, - specialRenderer); - specialRenderer.setRenderManager(BlockEntityRenderDispatcher.INSTANCE); - } -} diff --git a/patchwork-god-classes/src/main/resources/fabric.mod.json b/patchwork-god-classes/src/main/resources/fabric.mod.json index 30c69459..339e514d 100644 --- a/patchwork-god-classes/src/main/resources/fabric.mod.json +++ b/patchwork-god-classes/src/main/resources/fabric.mod.json @@ -25,7 +25,8 @@ "patchwork-events-world": "*", "patchwork-extensions-block": "*", "patchwork-extensions-item": "*", - "patchwork-loot": "*" + "patchwork-loot": "*", + "patchwork-networking": "*" }, "custom": { "modmenu:api": true, diff --git a/patchwork-registries/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java b/patchwork-registries/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java index 41054f51..0fda3e3c 100644 --- a/patchwork-registries/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java +++ b/patchwork-registries/src/main/java/net/minecraftforge/fml/client/registry/ClientRegistry.java @@ -24,7 +24,6 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.options.KeyBinding; -import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; import net.minecraft.client.render.block.entity.BlockEntityRenderer; import net.minecraft.entity.Entity; import net.minecraft.util.Identifier; @@ -44,7 +43,7 @@ public class ClientRegistry { */ public static synchronized void bindTileEntitySpecialRenderer(Class tileEntityClass, BlockEntityRenderer specialRenderer) { BlockEntityRendererRegistry.INSTANCE.register(tileEntityClass, specialRenderer); - specialRenderer.setRenderManager(BlockEntityRenderDispatcher.INSTANCE); + // Done by Fabric API: specialRenderer.setRenderManager(BlockEntityRenderDispatcher.INSTANCE); } /** From 1c8fd2a4ed37f00857d7be20dafe54bb65399361 Mon Sep 17 00:00:00 2001 From: bs2kbs2k Date: Sat, 26 Sep 2020 03:10:23 +0900 Subject: [PATCH 65/73] Implemented getHeight and setHeight on AbstractButtonWidget (#191) * Implement getHeight and setHeight on AbstractButtonWidget * Fixed code style on commit 0b87d35d27508056d520026b91627c3a410048b1 --- .../mixin/gui/MixinAbstractButtonWidget.java | 40 +++++++++++++++++++ .../main/resources/patchwork-gui.mixins.json | 1 + 2 files changed, 41 insertions(+) create mode 100644 patchwork-gui/src/main/java/net/patchworkmc/mixin/gui/MixinAbstractButtonWidget.java diff --git a/patchwork-gui/src/main/java/net/patchworkmc/mixin/gui/MixinAbstractButtonWidget.java b/patchwork-gui/src/main/java/net/patchworkmc/mixin/gui/MixinAbstractButtonWidget.java new file mode 100644 index 00000000..5434e17f --- /dev/null +++ b/patchwork-gui/src/main/java/net/patchworkmc/mixin/gui/MixinAbstractButtonWidget.java @@ -0,0 +1,40 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.gui; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.widget.AbstractButtonWidget; + +@Mixin(AbstractButtonWidget.class) +public abstract class MixinAbstractButtonWidget extends DrawableHelper { + @Shadow + protected int height; + + public int getHeight() { + return this.height; + } + + public void setHeight(int value) { + this.height = value; + } +} diff --git a/patchwork-gui/src/main/resources/patchwork-gui.mixins.json b/patchwork-gui/src/main/resources/patchwork-gui.mixins.json index 6bb1e5a0..4a01c95a 100644 --- a/patchwork-gui/src/main/resources/patchwork-gui.mixins.json +++ b/patchwork-gui/src/main/resources/patchwork-gui.mixins.json @@ -3,6 +3,7 @@ "package": "net.patchworkmc.mixin.gui", "compatibilityLevel": "JAVA_8", "client": [ + "MixinAbstractButtonWidget", "MixinAbstractInventoryScreen", "MixinGameRenderer", "MixinKeyboard", From 94d009259812484241acf268d5dbcce9c24c8baf Mon Sep 17 00:00:00 2001 From: YTG1234 <54103478+YTG1234@users.noreply.github.com> Date: Sat, 26 Sep 2020 20:11:58 +0300 Subject: [PATCH 66/73] Publicized MinecraftClient#textureManager (#190) * Added the `patchwork-access-modifications` module and publicized `MinecraftClient#textureManager`. * Fixed requested changes * Moved Access Widener to patchwork-fml. Didn't bump the version * Fixed --- patchwork-fml/build.gradle | 4 ++++ patchwork-fml/src/main/resources/fabric.mod.json | 3 ++- patchwork-fml/src/main/resources/patchwork-fml.accesswidener | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 patchwork-fml/src/main/resources/patchwork-fml.accesswidener diff --git a/patchwork-fml/build.gradle b/patchwork-fml/build.gradle index 4a4e6b27..a1c8ee20 100644 --- a/patchwork-fml/build.gradle +++ b/patchwork-fml/build.gradle @@ -1,6 +1,10 @@ archivesBaseName = "patchwork-fml" version = getSubprojectVersion(project, "0.4.0") +loom { + accessWidener "src/main/resources/patchwork-fml.accesswidener" +} + dependencies { implementation 'com.electronwill.night-config:toml:3.6.2' diff --git a/patchwork-fml/src/main/resources/fabric.mod.json b/patchwork-fml/src/main/resources/fabric.mod.json index 5f090b2c..8e88f088 100644 --- a/patchwork-fml/src/main/resources/fabric.mod.json +++ b/patchwork-fml/src/main/resources/fabric.mod.json @@ -24,5 +24,6 @@ "custom": { "modmenu:api": true, "modmenu:parent": "patchwork" - } + }, + "accessWidener": "patchwork-fml.accesswidener" } diff --git a/patchwork-fml/src/main/resources/patchwork-fml.accesswidener b/patchwork-fml/src/main/resources/patchwork-fml.accesswidener new file mode 100644 index 00000000..8c0669e1 --- /dev/null +++ b/patchwork-fml/src/main/resources/patchwork-fml.accesswidener @@ -0,0 +1,2 @@ +accessWidener v1 named +accessible field net/minecraft/client/MinecraftClient textureManager Lnet/minecraft/client/texture/TextureManager; From c890fabe5ee9d8f3e711e5c8c70a9dcdcef779ef Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Sat, 26 Sep 2020 14:57:40 -0500 Subject: [PATCH 67/73] Remove "jars" in favor of loader 0.10.0 remapping Also removes the duplicate ClientRegistry class in god-classes and fixes a missed patchwork-api-base dependency --- build.gradle | 22 ++----------------- .../src/main/resources/fabric.mod.json | 2 +- patchwork-items/build.gradle | 3 ++- .../src/main/resources/fabric.mod.json | 3 +-- src/main/resources/fabric.mod.json | 2 +- 5 files changed, 7 insertions(+), 25 deletions(-) diff --git a/build.gradle b/build.gradle index 2b51bcb6..d98112df 100644 --- a/build.gradle +++ b/build.gradle @@ -66,7 +66,7 @@ allprojects { dependencies { minecraft "com.mojang:minecraft:$Globals.mcVersion" mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}:v2" - modImplementation "net.fabricmc:fabric-loader:0.8.4+build.198" + modImplementation "net.fabricmc:fabric-loader:0.10.0+build.208" modImplementation "net.fabricmc.fabric-api:fabric-api:0.15.1+build.260-1.14" implementation 'net.patchworkmc:patchwork-eventbus:2.0.1:all' @@ -268,31 +268,13 @@ dependencies { minecraft "com.mojang:minecraft:$Globals.mcVersion" mappings "net.fabricmc:yarn:${Globals.mcVersion}${Globals.yarnVersion}:v2" - modImplementation "net.fabricmc:fabric-loader:0.8.4+build.198" + modImplementation "net.fabricmc:fabric-loader:0.10.0+build.208" modImplementation "net.fabricmc.fabric-api:fabric-api:0.15.1+build.260-1.14" implementation 'com.electronwill.night-config:toml:3.6.2' include 'com.electronwill.night-config:core:3.6.2' include 'com.electronwill.night-config:toml:3.6.2' include 'net.patchworkmc:patchwork-eventbus:2.0.0:all' - - fileTree(dir: 'jars', include: '*.jar').each { - String baseName = it.name.replace(".jar", "") - String version = "0.1.0" - int split = baseName.lastIndexOf('-') - - if (split != -1) { - version = baseName.substring(split + 1) - baseName = baseName.substring(0, split) - } - - String name = "testmod:${baseName}:${version}" - - System.out.println("Found test mod: " + it.name.replace(".jar", "") + " -> " + name) - - modCompileOnly name - modRuntime name - } } loom { diff --git a/patchwork-api-base/src/main/resources/fabric.mod.json b/patchwork-api-base/src/main/resources/fabric.mod.json index 4f19bf71..48e607a6 100644 --- a/patchwork-api-base/src/main/resources/fabric.mod.json +++ b/patchwork-api-base/src/main/resources/fabric.mod.json @@ -14,7 +14,7 @@ ], "depends": { // This is mirrored in the top-level project because of a Loader issue - "fabricloader": ">=0.8.4", + "fabricloader": ">=0.10.0", "fabric": ">=0.15.1" }, "description": "Common classes that don't require Mixins or involve mod loading", diff --git a/patchwork-items/build.gradle b/patchwork-items/build.gradle index b5f9e26a..a3a59f9f 100644 --- a/patchwork-items/build.gradle +++ b/patchwork-items/build.gradle @@ -2,5 +2,6 @@ archivesBaseName = "patchwork-items" version = getSubprojectVersion(project, "0.1.0") dependencies { - compile project(path: ':patchwork-capabilities', configuration: 'dev') + implementation project(path: ':patchwork-api-base', configuration: 'dev') + implementation project(path: ':patchwork-capabilities', configuration: 'dev') } diff --git a/patchwork-items/src/main/resources/fabric.mod.json b/patchwork-items/src/main/resources/fabric.mod.json index 1e0f461c..93ef2083 100644 --- a/patchwork-items/src/main/resources/fabric.mod.json +++ b/patchwork-items/src/main/resources/fabric.mod.json @@ -11,8 +11,7 @@ "icon": "assets/patchwork-items/icon.png", "environment": "*", "depends": { - "fabricloader": ">=0.8.4", - "fabric": "*" + "patchwork-api-base": "*" }, "mixins": [ "patchwork-items.mixins.json" diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0a98e243..efb4adb4 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -15,7 +15,7 @@ "depends": { // This is copied over from patchwork-api-base until Loader/201 is resolved properly. // Loader/204 exists as a bandage fix, but not a real solution. - "fabricloader": ">=0.8.4", + "fabricloader": ">=0.10.0", "fabric": ">=0.15.1" }, "description": "Implementation of Minecraft Forge for Fabric.", From 8abca85e788de32046bf0cd53117088f620367c8 Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Thu, 1 Oct 2020 22:36:50 -0500 Subject: [PATCH 68/73] Add automatic code style setting in IDEA This was meant to happen but the old gradle script for it only worked if you used the old, deprecated method. This also adds support for the checkstyle plugin. --- build.gradle | 12 +++++- idea-docs/checkstyle-idea.xml | 18 +++++++++ idea-docs/codeStyles/Project.xml | 47 ++++++++++++++++++++++++ idea-docs/codeStyles/codeStyleConfig.xml | 5 +++ 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 idea-docs/checkstyle-idea.xml create mode 100644 idea-docs/codeStyles/Project.xml create mode 100644 idea-docs/codeStyles/codeStyleConfig.xml diff --git a/build.gradle b/build.gradle index d98112df..16acf0da 100644 --- a/build.gradle +++ b/build.gradle @@ -120,7 +120,7 @@ allprojects { checkstyle { configFile = rootProject.file("checkstyle.xml") - toolVersion = '8.31' + toolVersion = '8.36.2' } } @@ -281,4 +281,12 @@ loom { shareCaches = true } -apply from: 'https://github.com/FabricMC/fabric-docs/raw/master/gradle/ideconfig.gradle' + +task copyIdeaFiles(type: Copy) { + if (file(".idea/").exists()) { + from "idea-docs/" + into ".idea/" + } +} + +copyIdeaFiles diff --git a/idea-docs/checkstyle-idea.xml b/idea-docs/checkstyle-idea.xml new file mode 100644 index 00000000..f9ee205a --- /dev/null +++ b/idea-docs/checkstyle-idea.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/idea-docs/codeStyles/Project.xml b/idea-docs/codeStyles/Project.xml new file mode 100644 index 00000000..51d1516e --- /dev/null +++ b/idea-docs/codeStyles/Project.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/idea-docs/codeStyles/codeStyleConfig.xml b/idea-docs/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/idea-docs/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file From 9ba44fa6df66c7ab6e857cdf918a30e5625e712d Mon Sep 17 00:00:00 2001 From: TheGlitch76 Date: Fri, 2 Oct 2020 14:40:38 -0500 Subject: [PATCH 69/73] Add more settings to Intellij code style --- idea-docs/codeStyles/Project.xml | 79 ++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/idea-docs/codeStyles/Project.xml b/idea-docs/codeStyles/Project.xml index 51d1516e..f8d69d4c 100644 --- a/idea-docs/codeStyles/Project.xml +++ b/idea-docs/codeStyles/Project.xml @@ -43,5 +43,84 @@ + + + + + + + + \ No newline at end of file From 542829b0714bd6c4f82808b7cd746c68766c4cb5 Mon Sep 17 00:00:00 2001 From: JFronny <33260128+JFronny@users.noreply.github.com> Date: Tue, 6 Oct 2020 20:00:03 +0200 Subject: [PATCH 70/73] Fix --- .../impl/event/world/WorldEvents.java | 33 +++++++------------ .../world/MixinThreadedAnvilChunkStorage.java | 2 -- .../net/minecraftforge/common/ForgeHooks.java | 10 +----- 3 files changed, 13 insertions(+), 32 deletions(-) diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index 483afb18..41b14830 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -19,31 +19,30 @@ package net.patchworkmc.impl.event.world; -import java.util.Collections; -import java.util.List; - -import javax.annotation.Nullable; - -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.world.ChunkEvent; -import net.minecraftforge.event.world.ChunkWatchEvent; -import net.minecraftforge.event.world.WorldEvent; - +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; import net.minecraft.entity.EntityCategory; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.Difficulty; import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.level.LevelInfo; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.DifficultyChangeEvent; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.ChunkWatchEvent; +import net.minecraftforge.event.world.WorldEvent; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.List; public class WorldEvents implements ModInitializer { public static boolean onCreateWorldSpawn(IWorld world, LevelInfo settings) { @@ -110,12 +109,4 @@ public void onInitialize() { public static void onDifficultyChange(Difficulty difficulty, Difficulty oldDifficulty) { MinecraftForge.EVENT_BUS.post(new DifficultyChangeEvent(difficulty, oldDifficulty)); } - - public static void fireChunkWatch(boolean watch, ServerPlayerEntity entity, ChunkPos chunkpos, ServerWorld world) { - if (watch) { - MinecraftForge.EVENT_BUS.post(new ChunkWatchEvent.Watch(entity, chunkpos, world)); - } else { - throw new UnsupportedOperationException("Cannot Unwatch a chunk yet"); - } - } } diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java index c340292f..bc3bc70d 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/mixin/event/world/MixinThreadedAnvilChunkStorage.java @@ -40,8 +40,6 @@ import net.patchworkmc.impl.event.world.WorldEvents; -import net.patchworkmc.impl.event.world.WorldEvents; - @Mixin(ThreadedAnvilChunkStorage.class) public class MixinThreadedAnvilChunkStorage { @Shadow diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java index 43e66779..d02c7f70 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -25,6 +25,7 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; +import net.minecraft.world.*; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.eventbus.api.Event; @@ -43,10 +44,6 @@ import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.GameMode; -import net.minecraft.world.IWorld; -import net.minecraft.world.MobSpawnerLogic; -import net.minecraft.world.World; import net.patchworkmc.impl.event.entity.EntityEvents; import net.patchworkmc.impl.extensions.block.BlockHarvestManager; @@ -54,14 +51,9 @@ import java.util.List; -import javax.annotation.Nullable; - import net.minecraft.entity.EntityCategory; -import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.Difficulty; import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; From 539bdccc79635f57ce06d5698f8b586215e58998 Mon Sep 17 00:00:00 2001 From: JFronny <33260128+JFronny@users.noreply.github.com> Date: Tue, 6 Oct 2020 20:02:27 +0200 Subject: [PATCH 71/73] Test, will be reverted later --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1d7687fe..15315206 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,8 +2,6 @@ name: Java CI on: push: - branches: - - master pull_request: jobs: From 8165cb015c1fd4e98b9268480fb4c0ec7787a9a8 Mon Sep 17 00:00:00 2001 From: JFronny <33260128+JFronny@users.noreply.github.com> Date: Tue, 6 Oct 2020 20:31:57 +0200 Subject: [PATCH 72/73] Second attempt at fixing checkstyle --- .../impl/event/world/WorldEvents.java | 25 +++++++++++-------- .../net/minecraftforge/common/ForgeHooks.java | 16 ++++++------ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java index 41b14830..36b6f931 100644 --- a/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java +++ b/patchwork-events-world/src/main/java/net/patchworkmc/impl/event/world/WorldEvents.java @@ -19,9 +19,17 @@ package net.patchworkmc.impl.event.world; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nullable; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.DifficultyChangeEvent; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.ChunkWatchEvent; +import net.minecraftforge.event.world.WorldEvent; + import net.minecraft.entity.EntityCategory; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; @@ -34,15 +42,10 @@ import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.level.LevelInfo; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.DifficultyChangeEvent; -import net.minecraftforge.event.world.ChunkEvent; -import net.minecraftforge.event.world.ChunkWatchEvent; -import net.minecraftforge.event.world.WorldEvent; -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.List; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; public class WorldEvents implements ModInitializer { public static boolean onCreateWorldSpawn(IWorld world, LevelInfo settings) { diff --git a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java index d02c7f70..aa4cd367 100644 --- a/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/patchwork-god-classes/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -20,15 +20,18 @@ package net.minecraftforge.common; import java.util.Collection; +import java.util.List; import javax.annotation.Nullable; import com.google.gson.Gson; import com.google.gson.JsonObject; -import net.minecraft.world.*; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.eventbus.api.Event; +import net.minecraft.world.MobSpawnerLogic; +import net.minecraft.world.GameMode; +import net.minecraft.world.Difficulty; import net.minecraft.world.dimension.DimensionType; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; @@ -44,13 +47,6 @@ import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; - -import net.patchworkmc.impl.event.entity.EntityEvents; -import net.patchworkmc.impl.extensions.block.BlockHarvestManager; -import net.patchworkmc.impl.loot.LootHooks; - -import java.util.List; - import net.minecraft.entity.EntityCategory; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.ChunkPos; @@ -59,6 +55,9 @@ import net.minecraft.world.biome.Biome; import net.minecraft.world.level.LevelInfo; +import net.patchworkmc.impl.extensions.block.BlockHarvestManager; +import net.patchworkmc.impl.loot.LootHooks; +import net.patchworkmc.impl.event.entity.EntityEvents; import net.patchworkmc.impl.event.world.WorldEvents; /* @@ -146,6 +145,7 @@ public static LootTable loadLootTable(Gson gson, Identifier name, JsonObject dat public static String readPoolName(JsonObject json) { return LootHooks.readPoolName(json); } + public static boolean onCreateWorldSpawn(World world, LevelInfo settings) { return WorldEvents.onCreateWorldSpawn(world, settings); } From 54a51261a9062d7b93b0ef8dfbafabbf4a22e955 Mon Sep 17 00:00:00 2001 From: JFronny <33260128+JFronny@users.noreply.github.com> Date: Tue, 6 Oct 2020 20:40:39 +0200 Subject: [PATCH 73/73] Revert Test commit (539bdccc) --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15315206..1d7687fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,8 @@ name: Java CI on: push: + branches: + - master pull_request: jobs: