From 1c071a51176a9e64990fb3b91363d17485b3cfbb Mon Sep 17 00:00:00 2001 From: Thomas <1688389+Rakambda@users.noreply.github.com> Date: Tue, 21 Mar 2023 20:25:02 +0100 Subject: [PATCH] Add option to not open GUI when placed (#199) * fabric: 1.19.4 * fabric: add option to not open GUI when placed * fix: activate forge * feat: use common code * feat: forgot some parts * feat: use mixingradle & openGuiOnPlace for forge --- .../editsign/common/EditSignCommon.java | 10 + .../editsign/common/config/Configuration.java | 3 + .../editsign/common/wrapper/IItem.java | 2 + .../editsign/common/wrapper/IItemStack.java | 4 + .../resources/assets/editsign/lang/en_us.json | 4 + .../fabric/client/cloth/ClothConfigHook.java | 7 + .../common/wrapper/ItemStackWrapper.java | 11 ++ .../fabric/common/wrapper/ItemWrapper.java | 6 + .../fabric/mixin/SignBlockEntityMixin.java | 30 ++- .../editsign/fabric/mixin/SignItemMixin.java | 29 +++ .../src/main/resources/editsign.mixins.json | 3 +- forge/build.gradle | 178 +++++++++--------- .../fr/rakambda/editsign/forge/EditSign.java | 43 +++-- .../editsign/forge/EditSignUtils.java | 79 -------- .../editsign/forge/ForgeEventSubscriber.java | 50 ----- .../forge/client/cloth/ClothConfigHook.java | 76 ++++++++ .../forge/common/EditSignCommonsImpl.java | 67 +++++++ .../common/wrapper/ComponentWrapper.java | 22 +++ .../forge/common/wrapper/HandWrapper.java | 14 ++ .../common/wrapper/ItemStackWrapper.java | 32 ++++ .../forge/common/wrapper/ItemWrapper.java | 39 ++++ .../forge/common/wrapper/PlayerWrapper.java | 29 +++ .../editsign/forge/config/CommonConfig.java | 30 --- .../editsign/forge/config/Config.java | 17 -- .../forge/config/cloth/ClothConfigHook.java | 93 --------- .../forge/event/RightClickBlockListener.java | 67 +++++++ .../editsign/forge/mixin/SignItemMixin.java | 29 +++ forge/src/main/resources/editsign.mixins.json | 14 ++ gradle/libs.versions.toml | 2 + settings.gradle.kts | 46 +++-- 30 files changed, 623 insertions(+), 413 deletions(-) create mode 100644 fabric/src/main/java/fr/rakambda/editsign/fabric/mixin/SignItemMixin.java delete mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/EditSignUtils.java delete mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/ForgeEventSubscriber.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/client/cloth/ClothConfigHook.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/common/EditSignCommonsImpl.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ComponentWrapper.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/HandWrapper.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ItemStackWrapper.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ItemWrapper.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/PlayerWrapper.java delete mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/config/CommonConfig.java delete mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/config/Config.java delete mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/config/cloth/ClothConfigHook.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/event/RightClickBlockListener.java create mode 100644 forge/src/main/java/fr/rakambda/editsign/forge/mixin/SignItemMixin.java create mode 100644 forge/src/main/resources/editsign.mixins.json diff --git a/common/src/main/java/fr/rakambda/editsign/common/EditSignCommon.java b/common/src/main/java/fr/rakambda/editsign/common/EditSignCommon.java index 77df044..a204287 100644 --- a/common/src/main/java/fr/rakambda/editsign/common/EditSignCommon.java +++ b/common/src/main/java/fr/rakambda/editsign/common/EditSignCommon.java @@ -26,6 +26,16 @@ public EditSignCommon(){ @NotNull public abstract IComponent translate(@NotNull String key, Object... objects); + public boolean playerHasSignModifier(@NotNull IPlayer player, @NotNull IHand hand){ + var playerItem = player.getHandItem(hand); + + var isDye = playerItem.getItem().isDye(); + var isGlowInkSack = playerItem.isGlowInk(); + var isInkSack = playerItem.isInkSac(); + + return isDye || isGlowInkSack || isInkSack; + } + public boolean canPlayerEdit(@NotNull IPlayer player, @NotNull IHand hand){ var requiredItem = configuration.getRequiredItem(this); if(!requiredItem.isEmpty()){ diff --git a/common/src/main/java/fr/rakambda/editsign/common/config/Configuration.java b/common/src/main/java/fr/rakambda/editsign/common/config/Configuration.java index 2aef12c..07fa050 100644 --- a/common/src/main/java/fr/rakambda/editsign/common/config/Configuration.java +++ b/common/src/main/java/fr/rakambda/editsign/common/config/Configuration.java @@ -21,6 +21,9 @@ public class Configuration{ @Expose @Getter public String requiredItemId = ""; + @Expose + @Getter + public boolean openGuiOnPlace = true; public Collection getRequiredItem(@NotNull EditSignCommon mod){ return mod.getAsItems(getRequiredItemId()); diff --git a/common/src/main/java/fr/rakambda/editsign/common/wrapper/IItem.java b/common/src/main/java/fr/rakambda/editsign/common/wrapper/IItem.java index fd2e000..a5fdbf7 100644 --- a/common/src/main/java/fr/rakambda/editsign/common/wrapper/IItem.java +++ b/common/src/main/java/fr/rakambda/editsign/common/wrapper/IItem.java @@ -2,4 +2,6 @@ public interface IItem extends IWrapper{ boolean isAir(); + + boolean isDye(); } diff --git a/common/src/main/java/fr/rakambda/editsign/common/wrapper/IItemStack.java b/common/src/main/java/fr/rakambda/editsign/common/wrapper/IItemStack.java index 8ce5048..b17194c 100644 --- a/common/src/main/java/fr/rakambda/editsign/common/wrapper/IItemStack.java +++ b/common/src/main/java/fr/rakambda/editsign/common/wrapper/IItemStack.java @@ -5,4 +5,8 @@ public interface IItemStack extends IWrapper{ @NotNull IItem getItem(); + + boolean isGlowInk(); + + boolean isInkSac(); } diff --git a/common/src/main/resources/assets/editsign/lang/en_us.json b/common/src/main/resources/assets/editsign/lang/en_us.json index c689862..772b225 100644 --- a/common/src/main/resources/assets/editsign/lang/en_us.json +++ b/common/src/main/resources/assets/editsign/lang/en_us.json @@ -7,5 +7,9 @@ "text.autoconfig.editsign.option.requiredItemId.@Tooltip[1]": "to be holding in order to edit", "text.autoconfig.editsign.option.requiredItemId.@Tooltip[2]": "a sign. If no value is set", "text.autoconfig.editsign.option.requiredItemId.@Tooltip[3]": "any item will be fine.", + "text.autoconfig.editsign.option.openGuiOnPlace": "Open GUI on place", + "text.autoconfig.editsign.option.openGuiOnPlace.@Tooltip[0]": "If set to false, sign", + "text.autoconfig.editsign.option.openGuiOnPlace.@Tooltip[1]": "GUI won't be opened", + "text.autoconfig.editsign.option.openGuiOnPlace.@Tooltip[2]": "when first placed", "editsign.action.not_editable": "This sign isn't editable" } \ No newline at end of file diff --git a/fabric/src/client/java/fr/rakambda/editsign/fabric/client/cloth/ClothConfigHook.java b/fabric/src/client/java/fr/rakambda/editsign/fabric/client/cloth/ClothConfigHook.java index dd27bf6..f3f4986 100644 --- a/fabric/src/client/java/fr/rakambda/editsign/fabric/client/cloth/ClothConfigHook.java +++ b/fabric/src/client/java/fr/rakambda/editsign/fabric/client/cloth/ClothConfigHook.java @@ -44,9 +44,16 @@ public void fillConfigScreen(@NotNull ConfigBuilder builder, @NotNull Configurat .setSaveConsumer(config::setRequiredItemId) .setErrorSupplier(map(getMinecraftItemIdCellError())) .build(); + var openGuiOnPlaceEntry = builder.entryBuilder() + .startBooleanToggle(translatable(getFieldName(null, "openGuiOnPlace")), config.isOpenGuiOnPlace()) + .setDefaultValue(true) + .setTooltip(getTooltips(null, "openGuiOnPlace", 3)) + .setSaveConsumer(config::setOpenGuiOnPlace) + .build(); var general = builder.getOrCreateCategory(translatable("text.autoconfig.editsign.category.default")); general.addEntry(requiredItemEntry); + general.addEntry(openGuiOnPlaceEntry); } @NotNull diff --git a/fabric/src/main/java/fr/rakambda/editsign/fabric/common/wrapper/ItemStackWrapper.java b/fabric/src/main/java/fr/rakambda/editsign/fabric/common/wrapper/ItemStackWrapper.java index 9aea05a..b34e1ec 100644 --- a/fabric/src/main/java/fr/rakambda/editsign/fabric/common/wrapper/ItemStackWrapper.java +++ b/fabric/src/main/java/fr/rakambda/editsign/fabric/common/wrapper/ItemStackWrapper.java @@ -5,6 +5,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import org.jetbrains.annotations.NotNull; @RequiredArgsConstructor @@ -18,4 +19,14 @@ public class ItemStackWrapper implements IItemStack{ public IItem getItem(){ return new ItemWrapper(raw.getItem()); } + + @Override + public boolean isGlowInk(){ + return raw.is(Items.GLOW_INK_SAC); + } + + @Override + public boolean isInkSac(){ + return raw.is(Items.INK_SAC); + } } diff --git a/fabric/src/main/java/fr/rakambda/editsign/fabric/common/wrapper/ItemWrapper.java b/fabric/src/main/java/fr/rakambda/editsign/fabric/common/wrapper/ItemWrapper.java index 6c339d4..cf47f8a 100644 --- a/fabric/src/main/java/fr/rakambda/editsign/fabric/common/wrapper/ItemWrapper.java +++ b/fabric/src/main/java/fr/rakambda/editsign/fabric/common/wrapper/ItemWrapper.java @@ -3,6 +3,7 @@ import fr.rakambda.editsign.common.wrapper.IItem; import lombok.Getter; import lombok.RequiredArgsConstructor; +import net.minecraft.world.item.DyeItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import org.jetbrains.annotations.NotNull; @@ -18,6 +19,11 @@ public boolean isAir(){ return Items.AIR.equals(raw); } + @Override + public boolean isDye(){ + return raw instanceof DyeItem; + } + @Override public boolean equals(Object obj){ if(!(obj instanceof IItem item)){ diff --git a/fabric/src/main/java/fr/rakambda/editsign/fabric/mixin/SignBlockEntityMixin.java b/fabric/src/main/java/fr/rakambda/editsign/fabric/mixin/SignBlockEntityMixin.java index a0bf264..965bac8 100644 --- a/fabric/src/main/java/fr/rakambda/editsign/fabric/mixin/SignBlockEntityMixin.java +++ b/fabric/src/main/java/fr/rakambda/editsign/fabric/mixin/SignBlockEntityMixin.java @@ -4,8 +4,6 @@ import fr.rakambda.editsign.fabric.common.wrapper.HandWrapper; import fr.rakambda.editsign.fabric.common.wrapper.PlayerWrapper; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.DyeItem; -import net.minecraft.world.item.Items; import net.minecraft.world.level.block.entity.SignBlockEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -14,29 +12,25 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(SignBlockEntity.class) -public final class SignBlockEntityMixin{ +public abstract class SignBlockEntityMixin{ @Shadow private boolean isEditable; - @Inject(method = "executeClickCommands", at = @At("HEAD")) + @Inject(method = "executeClickCommands", at = @At("HEAD"), cancellable = true) public void useOnBlock(ServerPlayer serverPlayer, CallbackInfoReturnable callback){ - var itemStack = serverPlayer.getItemInHand(serverPlayer.getUsedItemHand()); - var item = itemStack.getItem(); - - var isDye = item instanceof DyeItem; - var isGlowInkSack = itemStack.is(Items.GLOW_INK_SAC); - var isInkSack = itemStack.is(Items.INK_SAC); + var wrappedPlayer = new PlayerWrapper(serverPlayer); + var wrappedHand = new HandWrapper(serverPlayer.getUsedItemHand()); - if(isDye || isGlowInkSack || isInkSack){ + if(!EditSign.getMod().canPlayerEdit(wrappedPlayer, wrappedHand)){ return; } - - var wrappedPlayer = new PlayerWrapper(serverPlayer); - var wrappedHand = new HandWrapper(serverPlayer.getUsedItemHand()); - if(EditSign.getMod().canPlayerEdit(wrappedPlayer, wrappedHand)){ - isEditable = true; - SignBlockEntity sign = (SignBlockEntity) (Object) this; - serverPlayer.openTextEdit(sign); + if(EditSign.getMod().playerHasSignModifier(wrappedPlayer, wrappedHand)){ + return; } + + isEditable = true; + SignBlockEntity sign = (SignBlockEntity) (Object) this; + serverPlayer.openTextEdit(sign); + callback.setReturnValue(true); } } diff --git a/fabric/src/main/java/fr/rakambda/editsign/fabric/mixin/SignItemMixin.java b/fabric/src/main/java/fr/rakambda/editsign/fabric/mixin/SignItemMixin.java new file mode 100644 index 0000000..ba04a3c --- /dev/null +++ b/fabric/src/main/java/fr/rakambda/editsign/fabric/mixin/SignItemMixin.java @@ -0,0 +1,29 @@ +package fr.rakambda.editsign.fabric.mixin; + +import fr.rakambda.editsign.fabric.EditSign; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.SignItem; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +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; + +@Mixin(SignItem.class) +public abstract class SignItemMixin extends BlockItem{ + public SignItemMixin(Block block, Properties properties){ + super(block, properties); + } + + @Inject(method = "updateCustomBlockEntityTag", at = @At(value = "HEAD"), cancellable = true) + public void updateCustomBlockEntityTag(BlockPos blockPos, Level level, Player player, ItemStack itemStack, BlockState blockState, CallbackInfoReturnable callback){ + if(!EditSign.getMod().getConfiguration().isOpenGuiOnPlace()){ + callback.setReturnValue(super.updateCustomBlockEntityTag(blockPos, level, player, itemStack, blockState)); + } + } +} diff --git a/fabric/src/main/resources/editsign.mixins.json b/fabric/src/main/resources/editsign.mixins.json index 4617166..bd3a246 100644 --- a/fabric/src/main/resources/editsign.mixins.json +++ b/fabric/src/main/resources/editsign.mixins.json @@ -4,7 +4,8 @@ "package": "fr.rakambda.editsign.fabric.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "SignBlockEntityMixin" + "SignBlockEntityMixin", + "SignItemMixin" ], "client": [], "server": [], diff --git a/forge/build.gradle b/forge/build.gradle index 9eccf65..df62164 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -1,117 +1,125 @@ import net.minecraftforge.gradle.common.tasks.SignJar plugins { - alias(libs.plugins.forge) + alias(libs.plugins.forge) + alias(libs.plugins.mixingradle) } minecraft { - mappings channel: "official", version: "${libs.versions.forgeMappingsVersion.get()}" - runs { - client { - taskName "runESForgeClient" - workingDirectory project.file("./run/client") - property "forge.logging.markers", "REGISTRIES" - property "forge.logging.console.level", "debug" - property "forge.enabledGameTestNamespaces", "editsign" - mods { - editsign { - source sourceSets.main - } - } - } - - server { - taskName "runESForgeServer" - workingDirectory project.file("./run/server") - property "forge.logging.markers", "REGISTRIES" - property "forge.logging.console.level", "debug" - property "forge.enabledGameTestNamespaces", "editsign" - mods { - editsign { - source sourceSets.main - } - } - } - - gameTestServer { - taskName "runESForgeTestServer" - workingDirectory project.file("./run/test") - property "forge.logging.markers", "REGISTRIES" - property "forge.logging.console.level", "debug" - property "forge.enabledGameTestNamespaces", "editsign" - - mods { - editsign { - source sourceSets.main - } - } - } - - data { - taskName "runESForgeData" - workingDirectory project.file("./run/data") - property "forge.logging.markers", "REGISTRIES" - property "forge.logging.console.level", "debug" - args '--mod', 'editsign', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - - mods { - editsign { - source sourceSets.main - } - } - } - } + mappings channel: "official", version: "${libs.versions.forgeMappingsVersion.get()}" + runs { + client { + taskName "runESForgeClient" + workingDirectory project.file("./run/client") + property "forge.logging.markers", "REGISTRIES" + property "forge.logging.console.level", "debug" + property "forge.enabledGameTestNamespaces", "editsign" + mods { + editsign { + source sourceSets.main + } + } + } + + server { + taskName "runESForgeServer" + workingDirectory project.file("./run/server") + property "forge.logging.markers", "REGISTRIES" + property "forge.logging.console.level", "debug" + property "forge.enabledGameTestNamespaces", "editsign" + mods { + editsign { + source sourceSets.main + } + } + } + + gameTestServer { + taskName "runESForgeTestServer" + workingDirectory project.file("./run/test") + property "forge.logging.markers", "REGISTRIES" + property "forge.logging.console.level", "debug" + property "forge.enabledGameTestNamespaces", "editsign" + + mods { + editsign { + source sourceSets.main + } + } + } + + data { + taskName "runESForgeData" + workingDirectory project.file("./run/data") + property "forge.logging.markers", "REGISTRIES" + property "forge.logging.console.level", "debug" + args '--mod', 'editsign', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + + mods { + editsign { + source sourceSets.main + } + } + } + } +} + +tasks { + mixin { + add(sourceSets.main, "forge.${modId}.refmap.json") + config("editsign.mixins.json") + } } configurations { - library - implementation.extendsFrom library + library + implementation.extendsFrom library } minecraft.runs.all { - lazyToken('minecraft_classpath') { - configurations.library.copyRecursive().resolve().collect { it.absolutePath }.join(File.pathSeparator) - } + lazyToken('minecraft_classpath') { + configurations.library.copyRecursive().resolve().collect { it.absolutePath }.join(File.pathSeparator) + } } sourceSets.main.resources { srcDir 'src/generated/resources' } dependencies { - minecraft(libs.forge) - library(project(":common")) + minecraft(libs.forge) + library(project(":common")) - implementation(fg.deobf("me.shedaniel.cloth:cloth-config-forge:${libs.versions.clothConfigVersion.get()}")) + implementation(fg.deobf("me.shedaniel.cloth:cloth-config-forge:${libs.versions.clothConfigVersion.get()}")) } processResources { - duplicatesStrategy = DuplicatesStrategy.INCLUDE + duplicatesStrategy = DuplicatesStrategy.INCLUDE - from "src/main/resources", "../common/src/main/resources" + from "src/main/resources", "../common/src/main/resources" - filesMatching("META-INF/mods.toml") { - expand project.properties - } + filesMatching("META-INF/mods.toml") { + expand project.properties + } } ext { - minecraftVersion = libs.versions.minecraftVersion.get() + minecraftVersion = libs.versions.minecraftVersion.get() } jar.finalizedBy("reobfJar") task signJar(type: SignJar, dependsOn: rootProject.buildJar, group: "modding") { - onlyIf { - project.hasProperty("forgeKeyStore") - && project.hasProperty("forgeKeyStoreAlias") - && project.hasProperty("forgeKeyStorePass") - && project.hasProperty("forgeKeyStoreKeyPass") - && rootProject.file(project.findProperty("forgeKeyStore")).exists() - } - - keyStore = project.findProperty("forgeKeyStore") == null ? null : rootProject.file(project.findProperty("forgeKeyStore")).absolutePath - alias = project.findProperty("forgeKeyStoreAlias") - storePass = project.findProperty("forgeKeyStorePass") - keyPass = project.findProperty("forgeKeyStoreKeyPass") - inputFile = rootProject.jar.getArchiveFile() - outputFile = rootProject.jar.getArchiveFile() + onlyIf { + project.hasProperty("forgeKeyStore") + && project.hasProperty("forgeKeyStoreAlias") + && project.hasProperty("forgeKeyStorePass") + && project.hasProperty("forgeKeyStoreKeyPass") + && rootProject.file(project.findProperty("forgeKeyStore")).exists() + } + + keyStore = project.findProperty("forgeKeyStore") == null ? null : rootProject.file(project.findProperty("forgeKeyStore")).absolutePath + alias = project.findProperty("forgeKeyStoreAlias") + storePass = project.findProperty("forgeKeyStorePass") + keyPass = project.findProperty("forgeKeyStoreKeyPass") + inputFile = rootProject.jar.getArchiveFile() + outputFile = rootProject.jar.getArchiveFile() } diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/EditSign.java b/forge/src/main/java/fr/rakambda/editsign/forge/EditSign.java index 8affc1e..f1488dd 100644 --- a/forge/src/main/java/fr/rakambda/editsign/forge/EditSign.java +++ b/forge/src/main/java/fr/rakambda/editsign/forge/EditSign.java @@ -1,33 +1,36 @@ package fr.rakambda.editsign.forge; -import fr.rakambda.editsign.forge.config.Config; -import fr.rakambda.editsign.forge.config.cloth.ClothConfigHook; -import net.minecraftforge.fml.IExtensionPoint.DisplayTest; +import fr.rakambda.editsign.common.EditSignCommon; +import fr.rakambda.editsign.forge.common.EditSignCommonsImpl; +import fr.rakambda.editsign.forge.client.cloth.ClothConfigHook; +import lombok.Getter; +import lombok.extern.log4j.Log4j2; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.config.ModConfig; -import net.minecraftforge.network.NetworkConstants; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import java.lang.reflect.InvocationTargetException; +@Log4j2 @Mod(EditSign.MOD_ID) public class EditSign{ public static final String MOD_ID = "editsign"; - public static final Logger LOGGER = LogManager.getLogger(MOD_ID); + @Getter + private static final EditSignCommonsImpl mod = new EditSignCommonsImpl(); - public EditSign() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException{ - ModLoadingContext.get().registerExtensionPoint(DisplayTest.class, () -> new DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (a, b) -> true)); - ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.COMMON_SPEC); - - if(ModList.get().isLoaded("cloth_config")) - { - Class.forName("fr.rakambda.editsign.forge.config.cloth.ClothConfigHook") - .asSubclass(ClothConfigHook.class) - .getConstructor() - .newInstance() - .load(); + public EditSign(){ + if(ModList.get().isLoaded("cloth_config")){ + try{ + Class.forName("fr.rakambda.editsign.forge.client.cloth.ClothConfigHook") + .asSubclass(ClothConfigHook.class) + .getConstructor(EditSignCommon.class) + .newInstance(mod) + .load(); + } + catch(ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e){ + log.error("Failed to hook into ClothConfig", e); + } } + + mod.registerForge(MinecraftForge.EVENT_BUS); } } diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/EditSignUtils.java b/forge/src/main/java/fr/rakambda/editsign/forge/EditSignUtils.java deleted file mode 100644 index 5050e65..0000000 --- a/forge/src/main/java/fr/rakambda/editsign/forge/EditSignUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -package fr.rakambda.editsign.forge; - -import fr.rakambda.editsign.forge.config.Config; -import net.minecraft.core.Holder; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.DyeItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.IForgeRegistry; -import org.jetbrains.annotations.NotNull; -import javax.annotation.Nonnull; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Stream; -import static java.util.stream.Collectors.toSet; -import static java.util.stream.Stream.empty; - -public class EditSignUtils{ - public static boolean canPlayerEdit(Player player, ItemStack itemStack){ - return player.mayBuild() && !player.isCrouching() && !isHoldingDye(itemStack) && hasRightItem(itemStack); - } - - private static boolean isHoldingDye(ItemStack itemStack){ - return itemStack.getItem() instanceof DyeItem; - } - - private static boolean hasRightItem(ItemStack itemStack){ - var requiredItem = Config.COMMON.getRequiredItem(); - if(requiredItem.isEmpty()){ - return true; - } - - var playerItem = itemStack.getItem(); - return requiredItem.stream().anyMatch(item -> item.equals(playerItem)); - } - - public static Set getAsItems(String name){ - return Stream.of(name) - .filter(Objects::nonNull) - .filter(val -> !val.isEmpty()) - .flatMap(EditSignUtils::getItem) - .filter(Objects::nonNull) - .collect(toSet()); - } - - @Nonnull - public static Stream getItem(String name){ - try{ - var isTag = name.startsWith("#"); - if(isTag){ - name = name.substring(1); - } - var resourceLocation = new ResourceLocation(name); - if(isTag){ - var tag = TagKey.create(Registries.ITEM, resourceLocation); - return getRegistryTagContent(ForgeRegistries.ITEMS, tag); - } - return getRegistryElement(ForgeRegistries.ITEMS, resourceLocation).stream(); - } - catch(Exception e){ - return empty(); - } - } - - @NotNull - private static Optional getRegistryElement(IForgeRegistry registryKey, ResourceLocation identifier){ - return registryKey.getHolder(identifier).map(Holder::value); - } - - @NotNull - private static Stream getRegistryTagContent(@NotNull IForgeRegistry registry, @NotNull TagKey tag){ - return registry.tags().getTag(tag).stream(); - } -} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/ForgeEventSubscriber.java b/forge/src/main/java/fr/rakambda/editsign/forge/ForgeEventSubscriber.java deleted file mode 100644 index 505058d..0000000 --- a/forge/src/main/java/fr/rakambda/editsign/forge/ForgeEventSubscriber.java +++ /dev/null @@ -1,50 +0,0 @@ -package fr.rakambda.editsign.forge; - -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.block.entity.SignBlockEntity; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.util.ObfuscationReflectionHelper; - -@Mod.EventBusSubscriber(modid = EditSign.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE) -public final class ForgeEventSubscriber{ - private static final String[] IS_EDITABLE_FIELDS = { - "f_59721_", - "isEditable", - }; - - @SubscribeEvent(priority = EventPriority.LOWEST) - public static void onRightClickBlock(PlayerInteractEvent.RightClickBlock event){ - var player = event.getEntity(); - if(EditSignUtils.canPlayerEdit(player, event.getItemStack())){ - var blockEntity = event.getLevel().getBlockEntity(event.getPos()); - if(blockEntity instanceof SignBlockEntity sign){ - setSignEditable(sign); - if(sign.isEditable()){ - player.openTextEdit(sign); - } - else{ - if(player instanceof ServerPlayer serverPlayer){ - serverPlayer.sendSystemMessage(Component.translatable(EditSign.MOD_ID + ".action.not_editable"), false); - } - } - } - } - } - - private static void setSignEditable(SignBlockEntity sign){ - for(var field : IS_EDITABLE_FIELDS){ - try{ - ObfuscationReflectionHelper.setPrivateValue(SignBlockEntity.class, sign, true, field); - return; - } - catch(ObfuscationReflectionHelper.UnableToFindFieldException e){ - EditSign.LOGGER.debug("Failed to get field {}", field); - } - } - EditSign.LOGGER.debug("Couldn't set sign editable"); - } -} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/client/cloth/ClothConfigHook.java b/forge/src/main/java/fr/rakambda/editsign/forge/client/cloth/ClothConfigHook.java new file mode 100644 index 0000000..f10434b --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/client/cloth/ClothConfigHook.java @@ -0,0 +1,76 @@ +package fr.rakambda.editsign.forge.client.cloth; + +import fr.rakambda.editsign.common.EditSignCommon; +import fr.rakambda.editsign.common.config.Configuration; +import fr.rakambda.editsign.common.config.cloth.ClothHookBase; +import fr.rakambda.editsign.common.wrapper.IComponent; +import me.shedaniel.clothconfig2.api.ConfigBuilder; +import net.minecraft.network.chat.Component; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.ConfigScreenHandler; +import net.minecraftforge.fml.ModLoadingContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.Optional; +import java.util.function.Function; + +public class ClothConfigHook extends ClothHookBase{ + public ClothConfigHook(@NotNull EditSignCommon mod){ + super(mod); + } + + public void load(){ + ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory((minecraft, screen) -> { + var builder = ConfigBuilder.create() + .setParentScreen(screen) + .setTitle(Component.literal("EditSign")); + + var configuration = getMod().getConfiguration(); + builder.setSavingRunnable(configuration::onUpdate); + + fillConfigScreen(builder, configuration); + + return builder.build(); + })); + } + + @OnlyIn(Dist.CLIENT) + public void fillConfigScreen(@NotNull ConfigBuilder builder, @NotNull Configuration config){ + var requiredItemEntry = builder.entryBuilder() + .startStrField(translatable(getFieldName(null, "requiredItemId")), config.getRequiredItemId()) + .setDefaultValue("") + .setTooltip(getTooltips(null, "requiredItemId", 4)) + .setSaveConsumer(config::setRequiredItemId) + .setErrorSupplier(map(getMinecraftItemIdCellError())) + .build(); + var openGuiOnPlaceEntry = builder.entryBuilder() + .startBooleanToggle(translatable(getFieldName(null, "openGuiOnPlace")), config.isOpenGuiOnPlace()) + .setDefaultValue(true) + .setTooltip(getTooltips(null, "openGuiOnPlace", 3)) + .setSaveConsumer(config::setOpenGuiOnPlace) + .build(); + + var general = builder.getOrCreateCategory(translatable("text.autoconfig.editsign.category.default")); + general.addEntry(requiredItemEntry); + general.addEntry(openGuiOnPlaceEntry); + } + + @NotNull + private Function> map(@NotNull Function> fct){ + return str -> fct.apply(str).map(IComponent::getRaw).map(Component.class::cast); + } + + @NotNull + protected Component[] getTooltips(@Nullable String category, @NotNull String fieldName, int count){ + return getTooltipsInternal(category, fieldName, count) + .map(IComponent::getRaw) + .map(Component.class::cast) + .toArray(Component[]::new); + } + + @NotNull + private Component translatable(@NotNull String key){ + return (Component) getMod().translate(key).getRaw(); + } +} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/common/EditSignCommonsImpl.java b/forge/src/main/java/fr/rakambda/editsign/forge/common/EditSignCommonsImpl.java new file mode 100644 index 0000000..66a9e9b --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/common/EditSignCommonsImpl.java @@ -0,0 +1,67 @@ +package fr.rakambda.editsign.forge.common; + +import fr.rakambda.editsign.common.EditSignCommon; +import fr.rakambda.editsign.common.wrapper.IComponent; +import fr.rakambda.editsign.common.wrapper.IItem; +import fr.rakambda.editsign.forge.common.wrapper.ComponentWrapper; +import fr.rakambda.editsign.forge.common.wrapper.ItemWrapper; +import fr.rakambda.editsign.forge.event.RightClickBlockListener; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.IExtensionPoint; +import net.minecraftforge.fml.ModLoadingContext; +import net.minecraftforge.network.NetworkConstants; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.IForgeRegistry; +import org.jetbrains.annotations.NotNull; +import javax.annotation.Nonnull; +import java.util.Optional; +import java.util.stream.Stream; +import static java.util.stream.Stream.empty; + +public class EditSignCommonsImpl extends EditSignCommon{ + @Override + @NotNull + public IComponent translate(@NotNull String key, Object... objects){ + return new ComponentWrapper(Component.translatable(key, objects)); + } + + @Nonnull + public Stream getItem(@NotNull String name){ + try{ + var isTag = name.startsWith("#"); + if(isTag){ + name = name.substring(1); + } + var resourceLocation = new ResourceLocation(name); + if(isTag){ + var tag = TagKey.create(Registries.ITEM, resourceLocation); + return getRegistryTagContent(ForgeRegistries.ITEMS, tag).map(ItemWrapper::new); + } + return getRegistryElement(ForgeRegistries.ITEMS, resourceLocation).stream().map(ItemWrapper::new); + } + catch(Exception e){ + return empty(); + } + } + + @NotNull + private static Optional getRegistryElement(@NotNull IForgeRegistry registryKey, @NotNull ResourceLocation identifier){ + return registryKey.getHolder(identifier).map(Holder::value); + } + + @NotNull + private static Stream getRegistryTagContent(@NotNull IForgeRegistry registry, @NotNull TagKey tag){ + return registry.tags().getTag(tag).stream(); + } + + public void registerForge(@NotNull IEventBus eventBus){ + ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (a, b) -> true)); + + eventBus.register(new RightClickBlockListener(this)); + } +} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ComponentWrapper.java b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ComponentWrapper.java new file mode 100644 index 0000000..0069a26 --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ComponentWrapper.java @@ -0,0 +1,22 @@ +package fr.rakambda.editsign.forge.common.wrapper; + +import fr.rakambda.editsign.common.wrapper.IComponent; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import org.jetbrains.annotations.NotNull; + +@RequiredArgsConstructor +public class ComponentWrapper implements IComponent{ + @NotNull + @Getter + private final MutableComponent raw; + + @Override + @NotNull + public IComponent append(@NotNull IComponent component){ + raw.append((Component) component.getRaw()); + return this; + } +} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/HandWrapper.java b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/HandWrapper.java new file mode 100644 index 0000000..2c792f3 --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/HandWrapper.java @@ -0,0 +1,14 @@ +package fr.rakambda.editsign.forge.common.wrapper; + +import fr.rakambda.editsign.common.wrapper.IHand; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.world.InteractionHand; +import org.jetbrains.annotations.NotNull; + +@RequiredArgsConstructor +public class HandWrapper implements IHand{ + @NotNull + @Getter + private final InteractionHand raw; +} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ItemStackWrapper.java b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ItemStackWrapper.java new file mode 100644 index 0000000..063325d --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ItemStackWrapper.java @@ -0,0 +1,32 @@ +package fr.rakambda.editsign.forge.common.wrapper; + +import fr.rakambda.editsign.common.wrapper.IItem; +import fr.rakambda.editsign.common.wrapper.IItemStack; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import org.jetbrains.annotations.NotNull; + +@RequiredArgsConstructor +public class ItemStackWrapper implements IItemStack{ + @NotNull + @Getter + private final ItemStack raw; + + @Override + @NotNull + public IItem getItem(){ + return new ItemWrapper(raw.getItem()); + } + + @Override + public boolean isGlowInk(){ + return raw.is(Items.GLOW_INK_SAC); + } + + @Override + public boolean isInkSac(){ + return raw.is(Items.INK_SAC); + } +} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ItemWrapper.java b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ItemWrapper.java new file mode 100644 index 0000000..fa1b1ac --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/ItemWrapper.java @@ -0,0 +1,39 @@ +package fr.rakambda.editsign.forge.common.wrapper; + +import fr.rakambda.editsign.common.wrapper.IItem; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.world.item.DyeItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import org.jetbrains.annotations.NotNull; + +@RequiredArgsConstructor +public class ItemWrapper implements IItem{ + @NotNull + @Getter + private final Item raw; + + @Override + public boolean isAir(){ + return Items.AIR.equals(raw); + } + + @Override + public boolean isDye(){ + return raw instanceof DyeItem; + } + + @Override + public boolean equals(Object obj){ + if(!(obj instanceof IItem item)){ + return false; + } + return raw.equals(item.getRaw()); + } + + @Override + public int hashCode(){ + return raw.hashCode(); + } +} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/PlayerWrapper.java b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/PlayerWrapper.java new file mode 100644 index 0000000..02b5784 --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/common/wrapper/PlayerWrapper.java @@ -0,0 +1,29 @@ +package fr.rakambda.editsign.forge.common.wrapper; + +import fr.rakambda.editsign.common.wrapper.IHand; +import fr.rakambda.editsign.common.wrapper.IItemStack; +import fr.rakambda.editsign.common.wrapper.IPlayer; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.NotNull; + +@RequiredArgsConstructor +public class PlayerWrapper implements IPlayer{ + @NotNull + @Getter + private final Player raw; + + @Override + public boolean mayBuild(){ + return raw.mayBuild(); + } + + @Override + @NotNull + public IItemStack getHandItem(@NotNull IHand hand){ + var item = raw.getItemInHand((InteractionHand) hand.getRaw()); + return new ItemStackWrapper(item); + } +} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/config/CommonConfig.java b/forge/src/main/java/fr/rakambda/editsign/forge/config/CommonConfig.java deleted file mode 100644 index 1f0772d..0000000 --- a/forge/src/main/java/fr/rakambda/editsign/forge/config/CommonConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package fr.rakambda.editsign.forge.config; - -import net.minecraft.world.item.Item; -import net.minecraftforge.common.ForgeConfigSpec; -import java.util.Collection; -import static fr.rakambda.editsign.forge.EditSignUtils.getAsItems; - -public class CommonConfig{ - private static final String[] DESC_REQUIRED_ITEM_ID = { - "Required item to edit signs" - }; - private final ForgeConfigSpec.ConfigValue requiredItemId; - - public CommonConfig(ForgeConfigSpec.Builder builder){ - builder.comment("Edit Sign configuration"); - requiredItemId = builder.comment(DESC_REQUIRED_ITEM_ID).define("required_item_id", ""); - } - - public void setRequiredItemId(String s){ - requiredItemId.set(s); - } - - public String getRequiredItemStr(){ - return requiredItemId.get(); - } - - public Collection getRequiredItem(){ - return getAsItems(requiredItemId.get()); - } -} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/config/Config.java b/forge/src/main/java/fr/rakambda/editsign/forge/config/Config.java deleted file mode 100644 index 1544ab6..0000000 --- a/forge/src/main/java/fr/rakambda/editsign/forge/config/Config.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.rakambda.editsign.forge.config; - -import fr.rakambda.editsign.forge.EditSign; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.fml.common.Mod; - -@Mod.EventBusSubscriber(modid = EditSign.MOD_ID) -public class Config{ - public static final CommonConfig COMMON; - public static final ForgeConfigSpec COMMON_SPEC; - - static{ - var commonPair = new ForgeConfigSpec.Builder().configure(CommonConfig::new); - COMMON = commonPair.getLeft(); - COMMON_SPEC = commonPair.getRight(); - } -} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/config/cloth/ClothConfigHook.java b/forge/src/main/java/fr/rakambda/editsign/forge/config/cloth/ClothConfigHook.java deleted file mode 100644 index 0f2c1a7..0000000 --- a/forge/src/main/java/fr/rakambda/editsign/forge/config/cloth/ClothConfigHook.java +++ /dev/null @@ -1,93 +0,0 @@ -package fr.rakambda.editsign.forge.config.cloth; - -import fr.rakambda.editsign.forge.config.CommonConfig; -import fr.rakambda.editsign.forge.config.Config; -import lombok.NoArgsConstructor; -import me.shedaniel.clothconfig2.api.ConfigBuilder; -import me.shedaniel.clothconfig2.api.ConfigCategory; -import me.shedaniel.clothconfig2.gui.entries.StringListEntry; -import net.minecraft.network.chat.Component; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.ConfigScreenHandler; -import net.minecraftforge.fml.ModLoadingContext; -import org.jetbrains.annotations.NotNull; -import java.util.LinkedList; -import java.util.Optional; -import java.util.function.Function; -import java.util.regex.Pattern; - -@NoArgsConstructor -public class ClothConfigHook{ - private static final Pattern MINECRAFT_ID_PATTERN = Pattern.compile("#?[a-z0-9_.-]+:[a-z0-9/._-]+"); - - public static Function> getMinecraftItemIdCellError(){ - return value -> { - boolean valid; - if(value == null || value.isEmpty()){ - valid = true; - } - else{ - valid = MINECRAFT_ID_PATTERN.matcher(value).matches(); - } - - if(!valid){ - return Optional.of(translatable("text.autoconfig.editsign.error.invalidItemResourceLocation")); - } - return Optional.empty(); - }; - } - - public void load(){ - ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory((minecraft, screen) -> { - ConfigBuilder builder = ConfigBuilder.create() - .setParentScreen(screen) - .setTitle(Component.literal("EditSign")); - - fillConfigScreen(builder); - - return builder.build(); - })); - } - - @OnlyIn(Dist.CLIENT) - public void fillConfigScreen(ConfigBuilder builder){ - CommonConfig config = Config.COMMON; - - StringListEntry reverseSneakingEntry = builder.entryBuilder() - .startStrField(translatable(getFieldName("requiredItemId")), config.getRequiredItemStr()) - .setDefaultValue("") - .setTooltip(getTooltips("requiredItemId", 4)) - .setSaveConsumer(config::setRequiredItemId) - .setErrorSupplier(getMinecraftItemIdCellError()) - .build(); - - ConfigCategory general = builder.getOrCreateCategory(translatable("text.autoconfig.editsign.category.default")); - general.addEntry(reverseSneakingEntry); - } - - @NotNull - private static Component translatable(@NotNull String key){ - return Component.translatable(key); - } - - private String getFieldName(String fieldName){ - return "text.autoconfig.editsign.option." + fieldName; - } - - private Component[] getTooltips(String fieldName, int count){ - var tooltipKey = getFieldName(fieldName) + ".@Tooltip"; - var keys = new LinkedList(); - if(count <= 1){ - keys.add(tooltipKey); - } - else{ - for(int i = 0; i < count; i++){ - keys.add(tooltipKey + "[" + i + "]"); - } - } - return keys.stream() - .map(ClothConfigHook::translatable) - .toArray(Component[]::new); - } -} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/event/RightClickBlockListener.java b/forge/src/main/java/fr/rakambda/editsign/forge/event/RightClickBlockListener.java new file mode 100644 index 0000000..5fbbce3 --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/event/RightClickBlockListener.java @@ -0,0 +1,67 @@ +package fr.rakambda.editsign.forge.event; + +import fr.rakambda.editsign.common.EditSignCommon; +import fr.rakambda.editsign.forge.EditSign; +import fr.rakambda.editsign.forge.common.wrapper.HandWrapper; +import fr.rakambda.editsign.forge.common.wrapper.PlayerWrapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.block.entity.SignBlockEntity; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.util.ObfuscationReflectionHelper; +import org.jetbrains.annotations.NotNull; + +@Log4j2 +@RequiredArgsConstructor +public final class RightClickBlockListener{ + private static final String[] IS_EDITABLE_FIELDS = { + "f_59721_", + "isEditable", + }; + + @NotNull + private final EditSignCommon mod; + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void onRightClickBlock(PlayerInteractEvent.RightClickBlock event){ + var player = event.getEntity(); + + var playerWrapper = new PlayerWrapper(event.getEntity()); + var handWrapper = new HandWrapper(event.getHand()); + + if(!mod.canPlayerEdit(playerWrapper, handWrapper)){ + return; + } + if(mod.playerHasSignModifier(playerWrapper, handWrapper)){ + return; + } + + var blockEntity = event.getLevel().getBlockEntity(event.getPos()); + if(blockEntity instanceof SignBlockEntity sign){ + setSignEditable(sign); + if(sign.isEditable()){ + player.openTextEdit(sign); + } + else if(player instanceof ServerPlayer serverPlayer){ + serverPlayer.sendSystemMessage((Component) mod.translate(EditSign.MOD_ID + ".action.not_editable").getRaw(), false); + } + } + } + + private static void setSignEditable(SignBlockEntity sign){ + for(var field : IS_EDITABLE_FIELDS){ + try{ + ObfuscationReflectionHelper.setPrivateValue(SignBlockEntity.class, sign, true, field); + return; + } + catch(ObfuscationReflectionHelper.UnableToFindFieldException e){ + log.debug("Failed to get field {}", field); + } + } + log.debug("Couldn't set sign editable"); + } +} diff --git a/forge/src/main/java/fr/rakambda/editsign/forge/mixin/SignItemMixin.java b/forge/src/main/java/fr/rakambda/editsign/forge/mixin/SignItemMixin.java new file mode 100644 index 0000000..cc07824 --- /dev/null +++ b/forge/src/main/java/fr/rakambda/editsign/forge/mixin/SignItemMixin.java @@ -0,0 +1,29 @@ +package fr.rakambda.editsign.forge.mixin; + +import fr.rakambda.editsign.forge.EditSign; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.SignItem; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +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; + +@Mixin(SignItem.class) +public abstract class SignItemMixin extends BlockItem{ + public SignItemMixin(Block block, Properties properties){ + super(block, properties); + } + + @Inject(method = "updateCustomBlockEntityTag", at = @At(value = "HEAD"), cancellable = true) + public void updateCustomBlockEntityTag(BlockPos blockPos, Level level, Player player, ItemStack itemStack, BlockState blockState, CallbackInfoReturnable callback){ + if(!EditSign.getMod().getConfiguration().isOpenGuiOnPlace()){ + callback.setReturnValue(super.updateCustomBlockEntityTag(blockPos, level, player, itemStack, blockState)); + } + } +} diff --git a/forge/src/main/resources/editsign.mixins.json b/forge/src/main/resources/editsign.mixins.json new file mode 100644 index 0000000..6a88ae4 --- /dev/null +++ b/forge/src/main/resources/editsign.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "fr.rakambda.editsign.forge.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "SignItemMixin" + ], + "client": [], + "server": [], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ee07cf7..7077451 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,6 +21,7 @@ forge-plugin-version = "5.1.70" curse-version = "1.4.0" modrinth-version = "2.7.5" names-version = "0.46.0" +mixingradle-plugin-version = "0.7-SNAPSHOT" [libraries] lombok = { group = "org.projectlombok", name = "lombok", version.ref = "lombok-version" } @@ -44,3 +45,4 @@ modrinth = { id = "com.modrinth.minotaur", version.ref = "modrinth-version"} names = { id = "com.github.ben-manes.versions", version.ref = "names-version" } loom = { id = "fabric-loom", version.ref = "fabric-loom-version" } forge = { id = "net.minecraftforge.gradle", version.ref = "forge-plugin-version" } +mixingradle = { id = "org.spongepowered.mixin", version.ref = "mixingradle-plugin-version" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 844c830..b1b3e38 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,24 +1,30 @@ rootProject.name = "EditSign" pluginManagement { - repositories { - maven { - name = "Fabric" - url = uri("https://maven.fabricmc.net/") - } - maven { - name = "MinecraftForge" - url = uri("https://maven.minecraftforge.net") - } - gradlePluginPortal() - } - resolutionStrategy { - eachPlugin { - if (requested.id.id == "net.minecraftforge.gradle") { - useModule("${requested.id}:ForgeGradle:${requested.version}") - } - } - } + repositories { + maven { + name = "Fabric" + url = uri("https://maven.fabricmc.net/") + } + maven { + name = "MinecraftForge" + url = uri("https://maven.minecraftforge.net") + } + maven{ + name = "SpongePowered" + url = uri("https://repo.spongepowered.org/repository/maven-public/") + } + gradlePluginPortal() + } + resolutionStrategy { + eachPlugin { + if (requested.id.id == "net.minecraftforge.gradle") { + useModule("${requested.id}:ForgeGradle:${requested.version}") + } else if (requested.id.id == "org.spongepowered.mixin") { + useModule("org.spongepowered:mixingradle:${requested.version}") + } + } + } } val includeFabric: String by settings @@ -26,8 +32,8 @@ val includeForge: String by settings include("common") if (includeFabric.toBoolean()) { - include("fabric") + include("fabric") } if (includeForge.toBoolean()) { - include("forge") + include("forge") }