diff --git a/build.gradle b/build.gradle index bf70922..337ac6b 100644 --- a/build.gradle +++ b/build.gradle @@ -93,6 +93,11 @@ neoForge { sourceSet(sourceSets.main) } } + + unitTest { + enable() + testedMod = mods.voteme + } } configurations { @@ -117,27 +122,6 @@ shadowJar { } tasks.build.dependsOn shadowJar -tasks.withType(ProcessResources).configureEach { - var replaceProperties = [ - minecraft_version : minecraft_version, - minecraft_version_range: minecraft_version_range, - neo_version : neo_version, - neo_version_range : neo_version_range, - loader_version_range : loader_version_range, - mod_id : mod_id, - mod_name : mod_name, - mod_license : mod_license, - mod_version : mod_version, - mod_authors : mod_authors, - mod_description : mod_description - ] - inputs.properties replaceProperties - - filesMatching(['META-INF/neoforge.mods.toml']) { - expand replaceProperties - } -} - publishing { publications { release(MavenPublication) { diff --git a/src/main/java/org/teacon/voteme/VoteMe.java b/src/main/java/org/teacon/voteme/VoteMe.java index 4c0b983..659ffcb 100644 --- a/src/main/java/org/teacon/voteme/VoteMe.java +++ b/src/main/java/org/teacon/voteme/VoteMe.java @@ -1,10 +1,10 @@ package org.teacon.voteme; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.config.ModConfig; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.config.ModConfig; +import net.neoforged.neoforge.common.ModConfigSpec; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -17,11 +17,11 @@ public final class VoteMe { public static final Logger LOGGER = LogManager.getLogger(VoteMe.class); - public static final VoteMeConfig CONFIG; + public static VoteMeConfig CONFIG; - static { - Pair pair = new ForgeConfigSpec.Builder().configure(VoteMeConfig::new); - ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, pair.getRight()); + public VoteMe(ModContainer modContainer) { + Pair pair = new ModConfigSpec.Builder().configure(VoteMeConfig::new); + modContainer.registerConfig(ModConfig.Type.SERVER, pair.getRight()); CONFIG = pair.getLeft(); } } diff --git a/src/main/java/org/teacon/voteme/VoteMeConfig.java b/src/main/java/org/teacon/voteme/VoteMeConfig.java index b804613..66245c5 100644 --- a/src/main/java/org/teacon/voteme/VoteMeConfig.java +++ b/src/main/java/org/teacon/voteme/VoteMeConfig.java @@ -1,16 +1,16 @@ package org.teacon.voteme; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraftforge.common.ForgeConfigSpec; +import net.neoforged.neoforge.common.ModConfigSpec; import javax.annotation.ParametersAreNonnullByDefault; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public final class VoteMeConfig { - public final ForgeConfigSpec.ConfigValue REDIS_ATTACH_URI; + public final ModConfigSpec.ConfigValue REDIS_ATTACH_URI; - public VoteMeConfig(ForgeConfigSpec.Builder builder) { + public VoteMeConfig(ModConfigSpec.Builder builder) { REDIS_ATTACH_URI = builder .comment( "Redis attach uri (example: redis://password@localhost:6379/0), env substitution supported", diff --git a/src/main/java/org/teacon/voteme/category/VoteCategory.java b/src/main/java/org/teacon/voteme/category/VoteCategory.java index c9559d0..35e9c00 100644 --- a/src/main/java/org/teacon/voteme/category/VoteCategory.java +++ b/src/main/java/org/teacon/voteme/category/VoteCategory.java @@ -4,7 +4,13 @@ import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.HolderLookup; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.util.GsonHelper; import javax.annotation.ParametersAreNonnullByDefault; @@ -12,6 +18,15 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public final class VoteCategory { + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ComponentSerialization.STREAM_CODEC, c -> c.name, + ComponentSerialization.STREAM_CODEC, c -> c.description, + ByteBufCodecs.BOOL, c -> c.enabledDefault, + ByteBufCodecs.BOOL, c -> c.enabledModifiable, + VoteCategory::new + ); + public final Component name; public final Component description; public final boolean enabledDefault, enabledModifiable; @@ -23,13 +38,13 @@ public VoteCategory(Component name, Component description, boolean enabledDefaul this.enabledModifiable = enabledModifiable; } - public static VoteCategory fromJson(JsonElement json) { + public static VoteCategory fromJson(JsonElement json, HolderLookup.Provider registries) { JsonObject root = json.getAsJsonObject(); JsonObject enabled = GsonHelper.getAsJsonObject(root, "enabled"); boolean enabledDefault = GsonHelper.getAsBoolean(enabled, "default"); boolean enabledModifiable = GsonHelper.getAsBoolean(enabled, "modifiable"); - Component name = Component.Serializer.fromJson(root.get("name")); - Component desc = Component.Serializer.fromJson(root.get("description")); + Component name = Component.Serializer.fromJson(root.get("name"), registries); + Component desc = Component.Serializer.fromJson(root.get("description"), registries); if (name == null || desc == null) { throw new JsonSyntaxException("Both name and description are expected"); } diff --git a/src/main/java/org/teacon/voteme/category/VoteCategoryHandler.java b/src/main/java/org/teacon/voteme/category/VoteCategoryHandler.java index f34ec6a..0f96f1e 100644 --- a/src/main/java/org/teacon/voteme/category/VoteCategoryHandler.java +++ b/src/main/java/org/teacon/voteme/category/VoteCategoryHandler.java @@ -7,6 +7,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.HolderLookup; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.MutableComponent; @@ -17,12 +18,12 @@ import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.entity.player.Player; -import net.minecraftforge.event.AddReloadListenerEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.network.PacketDistributor; -import net.minecraftforge.server.ServerLifecycleHooks; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.AddReloadListenerEvent; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.network.PacketDistributor; +import net.neoforged.neoforge.server.ServerLifecycleHooks; import org.teacon.voteme.network.SyncCategoryPacket; import org.teacon.voteme.network.VoteMePacketManager; @@ -33,14 +34,16 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.GAME) public final class VoteCategoryHandler extends SimpleJsonResourceReloadListener { private static final Gson GSON = new GsonBuilder().create(); private static ImmutableMap categoryMap = ImmutableMap.of(); + private final HolderLookup.Provider registries; - public VoteCategoryHandler() { + public VoteCategoryHandler(HolderLookup.Provider registries) { super(GSON, "vote_categories"); + this.registries = registries; } public static Optional getCategory(ResourceLocation id) { @@ -53,11 +56,11 @@ public static Collection getIds() { @Override protected void apply(Map objects, ResourceManager manager, ProfilerFiller profiler) { - categoryMap = ImmutableSortedMap.copyOf(Maps.transformValues(objects, VoteCategory::fromJson)); + categoryMap = ImmutableSortedMap.copyOf(Maps.transformValues(objects, v -> VoteCategory.fromJson(v, this.registries))); MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); if (server != null) { SyncCategoryPacket packet = SyncCategoryPacket.create(categoryMap); - VoteMePacketManager.CHANNEL.send(PacketDistributor.ALL.noArg(), packet); + PacketDistributor.sendToAllPlayers(packet); } } @@ -67,7 +70,7 @@ public static void setCategoriesFromServer(ImmutableMap serverPlayer), packet); + PacketDistributor.sendToPlayer(serverPlayer, packet); } } diff --git a/src/main/java/org/teacon/voteme/command/AliasArgumentType.java b/src/main/java/org/teacon/voteme/command/AliasArgumentType.java index afc6ad5..cc57b86 100644 --- a/src/main/java/org/teacon/voteme/command/AliasArgumentType.java +++ b/src/main/java/org/teacon/voteme/command/AliasArgumentType.java @@ -8,11 +8,11 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.synchronization.ArgumentTypeInfos; import net.minecraft.commands.synchronization.SingletonArgumentInfo; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegisterEvent; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.RegisterEvent; import org.teacon.voteme.vote.VoteArtifactNames; import javax.annotation.ParametersAreNonnullByDefault; @@ -21,7 +21,7 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) public final class AliasArgumentType implements ArgumentType { public static AliasArgumentType alias() { @@ -51,7 +51,7 @@ public Collection getExamples() { @SubscribeEvent public static void register(RegisterEvent event) { - event.register(ForgeRegistries.COMMAND_ARGUMENT_TYPES.getRegistryKey(), new ResourceLocation("voteme:alias"), () -> + event.register(Registries.COMMAND_ARGUMENT_TYPE, ResourceLocation.parse("voteme:alias"), () -> ArgumentTypeInfos.registerByClass(AliasArgumentType.class, SingletonArgumentInfo.contextFree(AliasArgumentType::alias))); } } diff --git a/src/main/java/org/teacon/voteme/command/ArtifactArgumentType.java b/src/main/java/org/teacon/voteme/command/ArtifactArgumentType.java index 93e099a..5e7d5a5 100644 --- a/src/main/java/org/teacon/voteme/command/ArtifactArgumentType.java +++ b/src/main/java/org/teacon/voteme/command/ArtifactArgumentType.java @@ -11,11 +11,12 @@ import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.synchronization.ArgumentTypeInfos; import net.minecraft.commands.synchronization.SingletonArgumentInfo; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegisterEvent; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.NeoForgeRegistries; +import net.neoforged.neoforge.registries.RegisterEvent; import org.teacon.voteme.vote.VoteArtifactNames; import javax.annotation.ParametersAreNonnullByDefault; @@ -30,7 +31,7 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) public final class ArtifactArgumentType implements ArgumentType { private static final Pattern UUID_PATTERN = Pattern.compile("^([-0-9a-fA-F]+)"); @@ -87,7 +88,10 @@ public Collection getExamples() { @SubscribeEvent public static void register(RegisterEvent event) { - event.register(ForgeRegistries.COMMAND_ARGUMENT_TYPES.getRegistryKey(), new ResourceLocation("voteme:artifact"), () -> + if (event.getRegistryKey() != Registries.COMMAND_ARGUMENT_TYPE) { + return; + } + event.register(Registries.COMMAND_ARGUMENT_TYPE, ResourceLocation.parse("voteme:artifact"), () -> ArgumentTypeInfos.registerByClass(ArtifactArgumentType.class, SingletonArgumentInfo.contextFree(ArtifactArgumentType::artifact))); } } diff --git a/src/main/java/org/teacon/voteme/command/VoteMeCommand.java b/src/main/java/org/teacon/voteme/command/VoteMeCommand.java index 07df814..a3966c1 100644 --- a/src/main/java/org/teacon/voteme/command/VoteMeCommand.java +++ b/src/main/java/org/teacon/voteme/command/VoteMeCommand.java @@ -25,16 +25,18 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.permission.PermissionAPI; -import net.minecraftforge.server.permission.nodes.PermissionNode; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.RegisterCommandsEvent; +import net.neoforged.neoforge.server.permission.PermissionAPI; +import net.neoforged.neoforge.server.permission.nodes.PermissionNode; import org.apache.commons.lang3.tuple.Pair; import org.teacon.voteme.category.VoteCategory; import org.teacon.voteme.category.VoteCategoryHandler; import org.teacon.voteme.item.CounterItem; import org.teacon.voteme.item.VoterItem; +import org.teacon.voteme.item.component.ArtifactID; +import org.teacon.voteme.item.component.CategoryID; import org.teacon.voteme.roles.VoteRoleHandler; import org.teacon.voteme.vote.VoteArtifactNames; import org.teacon.voteme.vote.VoteDataStorage; @@ -66,7 +68,7 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.GAME) public final class VoteMeCommand { public static final SimpleCommandExceptionType ALIAS_INVALID = new SimpleCommandExceptionType(Component.translatable("argument.voteme.alias.invalid")); public static final SimpleCommandExceptionType ARTIFACT_INVALID = new SimpleCommandExceptionType(Component.translatable("argument.voteme.artifact.invalid")); @@ -240,8 +242,8 @@ private static int giveCounter(CommandContext context) throw Pair category = Pair.of(location, result.orElseThrow(() -> CATEGORY_NOT_FOUND.create(location))); for (ServerPlayer player : targets) { ItemStack item = CounterItem.INSTANCE.get().getDefaultInstance(); - item.getOrCreateTag().putString("CurrentCategory", category.getKey().toString()); - item.getOrCreateTag().putUUID("CurrentArtifact", artifactID); + item.set(CategoryID.INSTANCE, category.getKey()); + item.set(ArtifactID.INSTANCE, artifactID); processGiveItemToPlayer(player, item); } return targets.size(); @@ -252,7 +254,7 @@ private static int giveVoter(CommandContext context) throws Collection targets = getPlayers(context, "targets"); for (ServerPlayer player : targets) { ItemStack item = VoterItem.INSTANCE.get().getDefaultInstance(); - item.getOrCreateTag().putUUID("CurrentArtifact", artifactID); + item.set(ArtifactID.INSTANCE, artifactID); processGiveItemToPlayer(player, item); } return targets.size(); @@ -262,9 +264,9 @@ private static int openVoter(CommandContext context) throws UUID artifactID = getArtifact(context, "artifact"); Collection targets = getPlayers(context, "targets"); for (ServerPlayer player : targets) { - CompoundTag tag = new CompoundTag(); - tag.putUUID("CurrentArtifact", artifactID); - VoterItem.INSTANCE.get().open(player, tag); + ItemStack fakeVoter = new ItemStack(VoterItem.INSTANCE); + fakeVoter.set(ArtifactID.INSTANCE, artifactID); + VoterItem.INSTANCE.get().open(player, fakeVoter); } return targets.size(); } diff --git a/src/main/java/org/teacon/voteme/command/VoteMePermissions.java b/src/main/java/org/teacon/voteme/command/VoteMePermissions.java index dd46ede..1d29a43 100644 --- a/src/main/java/org/teacon/voteme/command/VoteMePermissions.java +++ b/src/main/java/org/teacon/voteme/command/VoteMePermissions.java @@ -6,13 +6,13 @@ import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; -import net.minecraftforge.server.permission.events.PermissionGatherEvent; -import net.minecraftforge.server.permission.nodes.PermissionDynamicContext; -import net.minecraftforge.server.permission.nodes.PermissionNode; -import net.minecraftforge.server.permission.nodes.PermissionTypes; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.server.ServerLifecycleHooks; +import net.neoforged.neoforge.server.permission.events.PermissionGatherEvent; +import net.neoforged.neoforge.server.permission.nodes.PermissionDynamicContext; +import net.neoforged.neoforge.server.permission.nodes.PermissionNode; +import net.neoforged.neoforge.server.permission.nodes.PermissionTypes; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -20,7 +20,7 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.GAME) public final class VoteMePermissions { public static final PermissionNode ADMIN = Util.make(new PermissionNode<>("voteme", "admin", PermissionTypes.BOOLEAN, VoteMePermissions::moderator), node -> node.setInformation(Component.translatable("permission.voteme.admin.name"), Component.translatable("permission.voteme.admin.description"))); diff --git a/src/main/java/org/teacon/voteme/crafting/VoterFromCounterRecipe.java b/src/main/java/org/teacon/voteme/crafting/VoterFromCounterRecipe.java index d6ac35b..05cb798 100644 --- a/src/main/java/org/teacon/voteme/crafting/VoterFromCounterRecipe.java +++ b/src/main/java/org/teacon/voteme/crafting/VoterFromCounterRecipe.java @@ -1,21 +1,23 @@ package org.teacon.voteme.crafting; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; import net.minecraft.world.level.Level; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegisterEvent; -import net.minecraftforge.registries.RegistryObject; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.RegisterEvent; import org.teacon.voteme.item.CounterItem; import org.teacon.voteme.item.VoterItem; @@ -23,27 +25,27 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) public final class VoterFromCounterRecipe extends CustomRecipe { - public static final ResourceLocation ID = new ResourceLocation("voteme:crafting_special_counter_from_voter"); + public static final ResourceLocation ID = ResourceLocation.parse("voteme:crafting_special_counter_from_voter"); - public static final RegistryObject> SERIALIZER = RegistryObject.create(ID, ForgeRegistries.RECIPE_SERIALIZERS); + public static final DeferredHolder, SimpleCraftingRecipeSerializer> SERIALIZER + = DeferredHolder.create(Registries.RECIPE_SERIALIZER, ID); @SubscribeEvent public static void register(RegisterEvent event) { - event.register(ForgeRegistries.RECIPE_SERIALIZERS.getRegistryKey(), ID, - () -> new SimpleCraftingRecipeSerializer<>(VoterFromCounterRecipe::new)); + event.register(Registries.RECIPE_SERIALIZER, ID, () -> new SimpleCraftingRecipeSerializer<>(VoterFromCounterRecipe::new)); } - private VoterFromCounterRecipe(ResourceLocation location, CraftingBookCategory category) { - super(location, category); + private VoterFromCounterRecipe(CraftingBookCategory category) { + super(category); } @Override - public boolean matches(CraftingContainer inv, Level worldIn) { + public boolean matches(CraftingInput inv, Level worldIn) { int voterSize = 0; ItemStack counter = ItemStack.EMPTY; - for (int i = 0, size = inv.getContainerSize(); i < size; ++i) { + for (int i = 0, size = inv.size(); i < size; ++i) { ItemStack stack = inv.getItem(i); if (stack.isEmpty()) { continue; @@ -62,10 +64,10 @@ public boolean matches(CraftingContainer inv, Level worldIn) { } @Override - public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) { + public ItemStack assemble(CraftingInput inv, HolderLookup.Provider registries) { int voterSize = 0; ItemStack counter = ItemStack.EMPTY; - for (int i = 0, size = inv.getContainerSize(); i < size; ++i) { + for (int i = 0, size = inv.size(); i < size; ++i) { ItemStack stack = inv.getItem(i); if (counter.isEmpty() && stack.is(CounterItem.INSTANCE.get())) { counter = stack; @@ -87,8 +89,8 @@ public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) } @Override - public NonNullList getRemainingItems(CraftingContainer inv) { - NonNullList list = NonNullList.withSize(inv.getContainerSize(), ItemStack.EMPTY); + public NonNullList getRemainingItems(CraftingInput inv) { + NonNullList list = NonNullList.withSize(inv.size(), ItemStack.EMPTY); for (int i = 0, size = list.size(); i < size; ++i) { ItemStack stack = inv.getItem(i); if (stack.hasCraftingRemainingItem()) { diff --git a/src/main/java/org/teacon/voteme/item/CounterItem.java b/src/main/java/org/teacon/voteme/item/CounterItem.java index 91d4c4f..115b365 100644 --- a/src/main/java/org/teacon/voteme/item/CounterItem.java +++ b/src/main/java/org/teacon/voteme/item/CounterItem.java @@ -3,7 +3,7 @@ import com.google.common.collect.ImmutableList; import net.minecraft.ChatFormatting; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; @@ -17,23 +17,22 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; -import net.minecraftforge.common.CreativeModeTabRegistry; -import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.network.PacketDistributor; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegisterEvent; -import net.minecraftforge.registries.RegistryObject; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.common.CreativeModeTabRegistry; +import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; +import net.neoforged.neoforge.network.PacketDistributor; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.RegisterEvent; import org.teacon.voteme.VoteMe; import org.teacon.voteme.category.VoteCategory; import org.teacon.voteme.category.VoteCategoryHandler; +import org.teacon.voteme.item.component.ArtifactID; +import org.teacon.voteme.item.component.CategoryID; import org.teacon.voteme.network.ShowCounterPacket; -import org.teacon.voteme.network.VoteMePacketManager; import org.teacon.voteme.vote.VoteArtifactNames; import org.teacon.voteme.vote.VoteDataStorage; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import java.util.List; import java.util.Objects; @@ -42,22 +41,25 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) public final class CounterItem extends Item { - public static final ResourceLocation ID = new ResourceLocation("voteme:counter"); + public static final ResourceLocation ID = ResourceLocation.parse("voteme:counter"); - public static final RegistryObject INSTANCE = RegistryObject.create(ID, ForgeRegistries.ITEMS); + public static final DeferredHolder INSTANCE = DeferredHolder.create(Registries.ITEM, ID); @SubscribeEvent public static void register(RegisterEvent event) { - event.register(ForgeRegistries.ITEMS.getRegistryKey(), ID, () -> new CounterItem(new Properties().stacksTo(1))); + if (event.getRegistryKey() != Registries.ITEM) { + return; + } + event.register(Registries.ITEM, ID, () -> new CounterItem(new Properties().stacksTo(1))); } @SubscribeEvent public static void register(BuildCreativeModeTabContentsEvent event) { if (VoteMeItemGroup.ID.equals(CreativeModeTabRegistry.getName(event.getTab()))) { - event.accept(INSTANCE, CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS); + event.accept(INSTANCE.get(), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS); } } @@ -66,16 +68,13 @@ private CounterItem(Properties properties) { } @Override - public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { - CompoundTag tag = stack.getTag(); - tooltip.add(Component.empty()); - if (tag != null && tag.hasUUID("CurrentArtifact")) { - UUID artifactID = tag.getUUID("CurrentArtifact"); + public void appendHoverText(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipFlag tooltipFlag) { + UUID artifactID = stack.get(ArtifactID.INSTANCE); Optional artifactNames = VoteArtifactNames.effective(); - if (artifactNames.isPresent() && !artifactNames.get().getName(artifactID).isEmpty()) { + if (artifactNames.isPresent() && artifactID != null && !artifactNames.get().getName(artifactID).isEmpty()) { MutableComponent artifactText = artifactNames.get().toText(artifactID).withStyle(ChatFormatting.GREEN); tooltip.add(Component.translatable("gui.voteme.counter.current_artifact_hint", artifactText).withStyle(ChatFormatting.GRAY)); - ResourceLocation currentCategoryID = new ResourceLocation(tag.getString("CurrentCategory")); + ResourceLocation currentCategoryID = stack.get(CategoryID.INSTANCE); if (!VoteCategoryHandler.getIds().isEmpty()) { tooltip.add(Component.empty()); } @@ -91,29 +90,25 @@ public void appendHoverText(ItemStack stack, @Nullable Level world, List use(Level world, Player player, InteractionHand hand) { ItemStack itemStack = player.getItemInHand(hand); - CompoundTag tag = itemStack.getOrCreateTag(); if (player instanceof ServerPlayer) { Optional packet = Optional.empty(); MinecraftServer server = Objects.requireNonNull(player.getServer()); int inventoryId = hand == InteractionHand.MAIN_HAND ? player.getInventory().selected : 40; - if (tag.hasUUID("CurrentArtifact")) { - ResourceLocation category = new ResourceLocation(tag.getString("CurrentCategory")); - packet = ShowCounterPacket.create(inventoryId, tag.getUUID("CurrentArtifact"), category, server); + UUID artifactID = itemStack.get(ArtifactID.INSTANCE); + ResourceLocation category = itemStack.get(CategoryID.INSTANCE); + if (artifactID != null && category != null) { + packet = ShowCounterPacket.create(inventoryId, artifactID, category, server); } if (packet.isEmpty()) { - packet = ShowCounterPacket.create(inventoryId, uuid -> tag.putUUID("CurrentArtifact", uuid)); + packet = ShowCounterPacket.create(inventoryId, uuid -> itemStack.set(ArtifactID.INSTANCE, uuid)); } if (packet.isPresent()) { - PacketDistributor.PacketTarget target = PacketDistributor.PLAYER.with(() -> (ServerPlayer) player); - VoteMePacketManager.CHANNEL.send(target, packet.get()); + PacketDistributor.sendToPlayer((ServerPlayer) player, packet.get()); return InteractionResultHolder.consume(itemStack); } } else { @@ -124,9 +119,8 @@ public InteractionResultHolder use(Level world, Player player, Intera @Override public Component getName(ItemStack stack) { - CompoundTag tag = stack.getTag(); - if (tag != null && tag.hasUUID("CurrentArtifact")) { - UUID artifactID = tag.getUUID("CurrentArtifact"); + UUID artifactID = stack.get(ArtifactID.INSTANCE); + if (artifactID != null) { Optional artifactNames = VoteArtifactNames.effective(); if (artifactNames.isPresent()) { String artifactName = artifactNames.get().getName(artifactID); @@ -151,8 +145,8 @@ public void applyChanges(ServerPlayer sender, ItemStack stack, UUID artifactID, ImmutableList enabledCategories, ImmutableList disabledCategories) { VoteDataStorage handler = VoteDataStorage.get(Objects.requireNonNull(sender.getServer())); if (this.checkMatchedArtifact(stack, artifactID)) { - stack.getOrCreateTag().putString("CurrentCategory", currentCategory.toString()); - stack.getOrCreateTag().putUUID("CurrentArtifact", artifactID); + stack.set(CategoryID.INSTANCE, currentCategory); + stack.set(ArtifactID.INSTANCE, artifactID); for (ResourceLocation category : enabledCategories) { if (VoteCategoryHandler.getCategory(category).filter(c -> c.enabledModifiable).isPresent()) { int entryID = handler.getIdOrCreate(artifactID, category); @@ -175,9 +169,9 @@ public void applyChanges(ServerPlayer sender, ItemStack stack, UUID artifactID, } private boolean checkMatchedArtifact(ItemStack stack, UUID artifactID) { - CompoundTag tag = stack.getTag(); - if (tag != null && tag.hasUUID("CurrentArtifact")) { - return tag.getUUID("CurrentArtifact").equals(artifactID); + UUID inStack = stack.get(ArtifactID.INSTANCE); + if (inStack != null) { + return inStack.equals(artifactID); } return false; } diff --git a/src/main/java/org/teacon/voteme/item/VoteMeItemGroup.java b/src/main/java/org/teacon/voteme/item/VoteMeItemGroup.java index b88fa96..bae6690 100644 --- a/src/main/java/org/teacon/voteme/item/VoteMeItemGroup.java +++ b/src/main/java/org/teacon/voteme/item/VoteMeItemGroup.java @@ -1,28 +1,29 @@ package org.teacon.voteme.item; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.registries.RegisterEvent; -import net.minecraftforge.registries.RegistryObject; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.RegisterEvent; import javax.annotation.ParametersAreNonnullByDefault; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) public final class VoteMeItemGroup { - public static final ResourceLocation ID = new ResourceLocation("voteme:voteme"); + public static final ResourceLocation ID = ResourceLocation.parse("voteme:voteme"); @SubscribeEvent public static void register(RegisterEvent event) { - event.register(BuiltInRegistries.CREATIVE_MODE_TAB.key(), ID, () -> CreativeModeTab.builder() + if (event.getRegistryKey() != Registries.CREATIVE_MODE_TAB) { + return; + } + event.register(Registries.CREATIVE_MODE_TAB, ID, () -> CreativeModeTab.builder() .title(Component.translatable("itemGroup.voteme")).icon(VoteMeItemGroup::makeIcon).build()); } diff --git a/src/main/java/org/teacon/voteme/item/VoterItem.java b/src/main/java/org/teacon/voteme/item/VoterItem.java index 5b6df1a..7b13737 100644 --- a/src/main/java/org/teacon/voteme/item/VoterItem.java +++ b/src/main/java/org/teacon/voteme/item/VoterItem.java @@ -2,7 +2,7 @@ import net.minecraft.ChatFormatting; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; @@ -15,25 +15,24 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; -import net.minecraftforge.common.CreativeModeTabRegistry; -import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.network.PacketDistributor; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegisterEvent; -import net.minecraftforge.registries.RegistryObject; -import net.minecraftforge.server.permission.PermissionAPI; -import net.minecraftforge.server.permission.nodes.PermissionNode; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.common.CreativeModeTabRegistry; +import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; +import net.neoforged.neoforge.network.PacketDistributor; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.RegisterEvent; +import net.neoforged.neoforge.server.permission.PermissionAPI; +import net.neoforged.neoforge.server.permission.nodes.PermissionNode; import org.teacon.voteme.category.VoteCategory; import org.teacon.voteme.category.VoteCategoryHandler; +import org.teacon.voteme.item.component.ArtifactID; import org.teacon.voteme.network.ShowVoterPacket; -import org.teacon.voteme.network.VoteMePacketManager; import org.teacon.voteme.vote.VoteArtifactNames; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.UUID; import java.util.stream.Stream; @@ -43,22 +42,25 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) public final class VoterItem extends Item { - public static final ResourceLocation ID = new ResourceLocation("voteme:voter"); + public static final ResourceLocation ID = ResourceLocation.parse("voteme:voter"); - public static final RegistryObject INSTANCE = RegistryObject.create(ID, ForgeRegistries.ITEMS); + public static final DeferredHolder INSTANCE = DeferredHolder.create(Registries.ITEM, ID); @SubscribeEvent public static void register(RegisterEvent event) { - event.register(ForgeRegistries.ITEMS.getRegistryKey(), ID, () -> new VoterItem(new Properties())); + if (event.getRegistryKey() != Registries.ITEM) { + return; + } + event.register(Registries.ITEM, ID, () -> new VoterItem(new Properties())); } @SubscribeEvent public static void register(BuildCreativeModeTabContentsEvent event) { if (VoteMeItemGroup.ID.equals(CreativeModeTabRegistry.getName(event.getTab()))) { - event.accept(INSTANCE, CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS); + event.accept(INSTANCE.get(), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS); } } @@ -67,13 +69,10 @@ private VoterItem(Properties properties) { } @Override - public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { - CompoundTag tag = stack.getTag(); - tooltip.add(Component.empty()); - if (tag != null && tag.hasUUID("CurrentArtifact")) { - UUID artifactID = tag.getUUID("CurrentArtifact"); + public void appendHoverText(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipFlag tooltipFlag) { + UUID artifactID = stack.get(ArtifactID.INSTANCE); Optional artifactNames = VoteArtifactNames.effective(); - if (artifactNames.isPresent() && !artifactNames.get().getName(artifactID).isEmpty()) { + if (artifactNames.isPresent() && artifactID != null && !artifactNames.get().getName(artifactID).isEmpty()) { MutableComponent artifactText = artifactNames.get().toText(artifactID).withStyle(ChatFormatting.GREEN); tooltip.add(Component.translatable("gui.voteme.voter.current_artifact_hint", artifactText).withStyle(ChatFormatting.GRAY)); if (!VoteCategoryHandler.getIds().isEmpty()) { @@ -90,35 +89,30 @@ public void appendHoverText(ItemStack stack, @Nullable Level world, List use(Level world, Player player, InteractionHand hand) { ItemStack itemStack = player.getItemInHand(hand); - CompoundTag tag = itemStack.getTag(); if (player instanceof ServerPlayer serverPlayer) { - if (this.open(serverPlayer, tag)) { + if (this.open(serverPlayer, itemStack)) { return InteractionResultHolder.consume(itemStack); } - } else if (tag != null && tag.hasUUID("CurrentArtifact")) { + } else if (itemStack.has(ArtifactID.INSTANCE)) { return InteractionResultHolder.success(itemStack); } return InteractionResultHolder.fail(itemStack); } - public boolean open(ServerPlayer player, @Nullable CompoundTag tag) { + public boolean open(ServerPlayer player, ItemStack itemStack) { Stream> permissions = Stream.of(OPEN_VOTER, OPEN); if (permissions.anyMatch(p -> PermissionAPI.getPermission(player, p))) { Optional packet = Optional.empty(); - if (tag != null && tag.hasUUID("CurrentArtifact")) { - packet = ShowVoterPacket.create(tag.getUUID("CurrentArtifact"), player); + if (itemStack.has(ArtifactID.INSTANCE)) { + packet = ShowVoterPacket.create(Objects.requireNonNull(itemStack.get(ArtifactID.INSTANCE), "Artifact ID must not be null here"), player); } if (packet.isPresent()) { - PacketDistributor.PacketTarget target = PacketDistributor.PLAYER.with(() -> player); - VoteMePacketManager.CHANNEL.send(target, packet.get()); + PacketDistributor.sendToPlayer(player, packet.get()); return true; } } @@ -127,9 +121,8 @@ public boolean open(ServerPlayer player, @Nullable CompoundTag tag) { @Override public Component getName(ItemStack stack) { - CompoundTag tag = stack.getTag(); - if (tag != null && tag.hasUUID("CurrentArtifact")) { - UUID artifactID = tag.getUUID("CurrentArtifact"); + UUID artifactID = stack.get(ArtifactID.INSTANCE); + if (artifactID != null) { Optional artifactNames = VoteArtifactNames.effective(); if (artifactNames.isPresent()) { String artifactName = artifactNames.get().getName(artifactID); @@ -142,12 +135,8 @@ public Component getName(ItemStack stack) { } public ItemStack copyFrom(int voterSize, ItemStack stack) { - CompoundTag tag = stack.getTag(), newTag = new CompoundTag(); - if (tag != null && tag.hasUUID("CurrentArtifact")) { - newTag.putUUID("CurrentArtifact", tag.getUUID("CurrentArtifact")); - } ItemStack result = new ItemStack(this, voterSize); - result.setTag(newTag); + result.copyFrom(stack, ArtifactID.INSTANCE); return result; } } diff --git a/src/main/java/org/teacon/voteme/item/component/ArtifactID.java b/src/main/java/org/teacon/voteme/item/component/ArtifactID.java new file mode 100644 index 0000000..4729a2d --- /dev/null +++ b/src/main/java/org/teacon/voteme/item/component/ArtifactID.java @@ -0,0 +1,30 @@ +package org.teacon.voteme.item.component; + +import net.minecraft.core.UUIDUtil; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.RegisterEvent; + +import java.util.UUID; + +@EventBusSubscriber(modid = "voteme", bus = EventBusSubscriber.Bus.MOD) +public class ArtifactID { + + public static final ResourceLocation ID = ResourceLocation.parse("voteme:artifact_id"); + + public static final DeferredHolder, DataComponentType> INSTANCE = DeferredHolder.create(Registries.DATA_COMPONENT_TYPE, ID); + + @SubscribeEvent + public static void on(RegisterEvent event) { + if (event.getRegistryKey() == Registries.DATA_COMPONENT_TYPE) { + event.register(Registries.DATA_COMPONENT_TYPE, ID, () -> DataComponentType.builder() + .persistent(UUIDUtil.CODEC) + .networkSynchronized(UUIDUtil.STREAM_CODEC) + .build()); + } + } +} diff --git a/src/main/java/org/teacon/voteme/item/component/CategoryID.java b/src/main/java/org/teacon/voteme/item/component/CategoryID.java new file mode 100644 index 0000000..3a6722d --- /dev/null +++ b/src/main/java/org/teacon/voteme/item/component/CategoryID.java @@ -0,0 +1,32 @@ +package org.teacon.voteme.item.component; + +import net.minecraft.core.UUIDUtil; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.RegisterEvent; + +import java.util.UUID; + +@EventBusSubscriber(modid = "voteme", bus = EventBusSubscriber.Bus.MOD) +public class CategoryID { + + public static final ResourceLocation ID = ResourceLocation.parse("voteme:category_id"); + + public static final DeferredHolder, DataComponentType> INSTANCE + = DeferredHolder.create(Registries.DATA_COMPONENT_TYPE, ID); + + @SubscribeEvent + public static void on(RegisterEvent event) { + if (event.getRegistryKey() == Registries.DATA_COMPONENT_TYPE) { + event.register(Registries.DATA_COMPONENT_TYPE, ID, () -> DataComponentType.builder() + .persistent(ResourceLocation.CODEC) + .networkSynchronized(ResourceLocation.STREAM_CODEC) + .build()); + } + } +} + diff --git a/src/main/java/org/teacon/voteme/network/ChangeNameByCounterPacket.java b/src/main/java/org/teacon/voteme/network/ChangeNameByCounterPacket.java index 8bdf2c9..41cc1cd 100644 --- a/src/main/java/org/teacon/voteme/network/ChangeNameByCounterPacket.java +++ b/src/main/java/org/teacon/voteme/network/ChangeNameByCounterPacket.java @@ -1,27 +1,40 @@ package org.teacon.voteme.network; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.UUIDUtil; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent; -import net.minecraftforge.server.permission.PermissionAPI; -import net.minecraftforge.server.permission.nodes.PermissionNode; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import net.neoforged.neoforge.server.permission.PermissionAPI; +import net.neoforged.neoforge.server.permission.nodes.PermissionNode; import org.teacon.voteme.item.CounterItem; import org.teacon.voteme.vote.VoteArtifactNames; import org.teacon.voteme.vote.VoteDataStorage; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Objects; import java.util.UUID; -import java.util.function.Supplier; import java.util.stream.Stream; import static org.teacon.voteme.command.VoteMePermissions.*; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public final class ChangeNameByCounterPacket { +public final class ChangeNameByCounterPacket implements CustomPacketPayload { + + public static final Type TYPE = new Type<>(ResourceLocation.parse("voteme:change_name_by_counter")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.VAR_INT, p -> p.inventoryIndex, + UUIDUtil.STREAM_CODEC, p -> p.artifactUUID, + ByteBufCodecs.STRING_UTF8, p -> p.newArtifactName, + ChangeNameByCounterPacket::new + ); + public final int inventoryIndex; public final UUID artifactUUID; public final String newArtifactName; @@ -32,34 +45,23 @@ private ChangeNameByCounterPacket(int inventoryIndex, UUID artifactUUID, String this.newArtifactName = newArtifactName; } - public void handle(Supplier supplier) { - supplier.get().enqueueWork(() -> { - ServerPlayer sender = Objects.requireNonNull(supplier.get().getSender()); - VoteArtifactNames artifactNames = VoteDataStorage.get(sender.server).getArtifactNames(); - boolean isCreating = artifactNames.getName(this.artifactUUID).isEmpty(); - Stream> permissions = isCreating - ? Stream.of(CREATE_COUNTER, CREATE, ADMIN_CREATE, ADMIN) : Stream.of(MODIFY_COUNTER, MODIFY); - if (permissions.anyMatch(p -> PermissionAPI.getPermission(sender, p))) { - ItemStack stack = sender.getInventory().getItem(this.inventoryIndex); - if (CounterItem.INSTANCE.get().equals(stack.getItem())) { - CounterItem.INSTANCE.get().rename(sender, stack, this.artifactUUID, this.newArtifactName); - } - } - }); - supplier.get().setPacketHandled(true); + @Override + public Type type() { + return TYPE; } - public void write(FriendlyByteBuf buffer) { - buffer.writeVarInt(this.inventoryIndex); - buffer.writeUUID(this.artifactUUID); - buffer.writeUtf(this.newArtifactName); - } - - public static ChangeNameByCounterPacket read(FriendlyByteBuf buffer) { - int inventoryIndex = buffer.readVarInt(); - UUID artifactUUID = buffer.readUUID(); - String artifactName = buffer.readUtf(Short.MAX_VALUE); - return new ChangeNameByCounterPacket(inventoryIndex, artifactUUID, artifactName); + public void handle(IPayloadContext context) { + ServerPlayer sender = (ServerPlayer) context.player(); + VoteArtifactNames artifactNames = VoteDataStorage.get(sender.server).getArtifactNames(); + boolean isCreating = artifactNames.getName(this.artifactUUID).isEmpty(); + Stream> permissions = isCreating + ? Stream.of(CREATE_COUNTER, CREATE, ADMIN_CREATE, ADMIN) : Stream.of(MODIFY_COUNTER, MODIFY); + if (permissions.anyMatch(p -> PermissionAPI.getPermission(sender, p))) { + ItemStack stack = sender.getInventory().getItem(this.inventoryIndex); + if (CounterItem.INSTANCE.get().equals(stack.getItem())) { + CounterItem.INSTANCE.get().rename(sender, stack, this.artifactUUID, this.newArtifactName); + } + } } public static ChangeNameByCounterPacket create(int inventoryIndex, UUID artifactUUID, String newArtifactName) { diff --git a/src/main/java/org/teacon/voteme/network/ChangePropsByCounterPacket.java b/src/main/java/org/teacon/voteme/network/ChangePropsByCounterPacket.java index 454e61f..c3c8af2 100644 --- a/src/main/java/org/teacon/voteme/network/ChangePropsByCounterPacket.java +++ b/src/main/java/org/teacon/voteme/network/ChangePropsByCounterPacket.java @@ -2,27 +2,47 @@ import com.google.common.collect.ImmutableList; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.UUIDUtil; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent; -import net.minecraftforge.server.permission.PermissionAPI; -import net.minecraftforge.server.permission.nodes.PermissionNode; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import net.neoforged.neoforge.server.permission.PermissionAPI; +import net.neoforged.neoforge.server.permission.nodes.PermissionNode; import org.teacon.voteme.VoteMe; import org.teacon.voteme.item.CounterItem; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Objects; +import java.util.List; import java.util.UUID; -import java.util.function.Supplier; import java.util.stream.Stream; import static org.teacon.voteme.command.VoteMePermissions.*; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public final class ChangePropsByCounterPacket { +public final class ChangePropsByCounterPacket implements CustomPacketPayload { + + public static final Type TYPE = new Type<>(ResourceLocation.parse("voteme:change_props_by_counter")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.VAR_INT, p -> p.inventoryIndex, + UUIDUtil.STREAM_CODEC, p -> p.artifactUUID, + ResourceLocation.STREAM_CODEC, p -> p.categoryID, + ResourceLocation.STREAM_CODEC.apply(ByteBufCodecs.list()), p -> p.enabled, + ResourceLocation.STREAM_CODEC.apply(ByteBufCodecs.list()), p -> p.disabled, + ChangePropsByCounterPacket::new + ); + + @Override + public Type type() { + return TYPE; + } + public final int inventoryIndex; public final UUID artifactUUID; public final ResourceLocation categoryID; @@ -30,53 +50,24 @@ public final class ChangePropsByCounterPacket { public final ImmutableList disabled; private ChangePropsByCounterPacket(int inventoryIndex, UUID artifactUUID, ResourceLocation category, - ImmutableList enabled, ImmutableList disabled) { + List enabled, List disabled) { this.inventoryIndex = inventoryIndex; this.artifactUUID = artifactUUID; this.categoryID = category; - this.disabled = disabled; - this.enabled = enabled; + this.disabled = ImmutableList.copyOf(disabled); + this.enabled = ImmutableList.copyOf(enabled); } - public void handle(Supplier supplier) { - supplier.get().enqueueWork(() -> { - ServerPlayer sender = Objects.requireNonNull(supplier.get().getSender()); - Stream> permissions = Stream.of(SWITCH_COUNTER, SWITCH, ADMIN_SWITCH, ADMIN); - if (permissions.anyMatch(p -> PermissionAPI.getPermission(sender, p))) { - ItemStack stack = sender.getInventory().getItem(this.inventoryIndex); - if (CounterItem.INSTANCE.get().equals(stack.getItem())) { - CounterItem.INSTANCE.get().applyChanges(sender, stack, - this.artifactUUID, this.categoryID, this.enabled, this.disabled); - } + public void handle(IPayloadContext context) { + ServerPlayer sender = (ServerPlayer) context.player(); + Stream> permissions = Stream.of(SWITCH_COUNTER, SWITCH, ADMIN_SWITCH, ADMIN); + if (permissions.anyMatch(p -> PermissionAPI.getPermission(sender, p))) { + ItemStack stack = sender.getInventory().getItem(this.inventoryIndex); + if (CounterItem.INSTANCE.get().equals(stack.getItem())) { + CounterItem.INSTANCE.get().applyChanges(sender, stack, + this.artifactUUID, this.categoryID, this.enabled, this.disabled); } - }); - supplier.get().setPacketHandled(true); - } - - public void write(FriendlyByteBuf buffer) { - buffer.writeVarInt(this.inventoryIndex); - buffer.writeUUID(this.artifactUUID); - buffer.writeResourceLocation(this.categoryID); - buffer.writeInt(this.enabled.size()); - buffer.writeInt(this.disabled.size()); - this.enabled.forEach(buffer::writeResourceLocation); - this.disabled.forEach(buffer::writeResourceLocation); - } - - public static ChangePropsByCounterPacket read(FriendlyByteBuf buffer) { - int inventoryIndex = buffer.readVarInt(); - UUID artifactUUID = buffer.readUUID(); - ResourceLocation category = buffer.readResourceLocation(); - int enabledSize = buffer.readInt(), disabledSize = buffer.readInt(); - ImmutableList.Builder enabledBuilder = ImmutableList.builder(); - ImmutableList.Builder disabledBuilder = ImmutableList.builder(); - for (int i = 0; i < enabledSize; ++i) { - enabledBuilder.add(buffer.readResourceLocation()); - } - for (int i = 0; i < disabledSize; ++i) { - disabledBuilder.add(buffer.readResourceLocation()); } - return new ChangePropsByCounterPacket(inventoryIndex, artifactUUID, category, enabledBuilder.build(), disabledBuilder.build()); } public static ChangePropsByCounterPacket create(int inventoryIndex, UUID artifactUUID, ResourceLocation category, diff --git a/src/main/java/org/teacon/voteme/network/ShowCounterPacket.java b/src/main/java/org/teacon/voteme/network/ShowCounterPacket.java index e640f5f..ddb9fab 100644 --- a/src/main/java/org/teacon/voteme/network/ShowCounterPacket.java +++ b/src/main/java/org/teacon/voteme/network/ShowCounterPacket.java @@ -1,16 +1,20 @@ package org.teacon.voteme.network; import com.google.common.collect.ImmutableList; -import com.google.common.primitives.ImmutableIntArray; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.UUIDUtil; +import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.network.handling.IPayloadContext; import org.apache.commons.lang3.tuple.Pair; import org.teacon.voteme.category.VoteCategory; import org.teacon.voteme.category.VoteCategoryHandler; @@ -25,84 +29,48 @@ import java.util.Optional; import java.util.UUID; import java.util.function.Consumer; -import java.util.function.Supplier; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public final class ShowCounterPacket { +public final class ShowCounterPacket implements CustomPacketPayload { + + public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath("voteme", "show_counter")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.VAR_INT, p -> p.invIndex, + UUIDUtil.STREAM_CODEC, p -> p.artifactUUID, + ResourceLocation.STREAM_CODEC, p -> p.category, + Info.STREAM_CODEC.apply(ByteBufCodecs.list()), p -> p.infos, + ShowCounterPacket::new + ); + public final int invIndex; public final UUID artifactUUID; public final ResourceLocation category; public final ImmutableList infos; - private ShowCounterPacket(int invIndex, UUID uuid, ResourceLocation category, ImmutableList infos) { + private ShowCounterPacket(int invIndex, UUID uuid, ResourceLocation category, List infos) { this.invIndex = invIndex; this.artifactUUID = uuid; this.category = category; - this.infos = infos; - } - - public void handle(Supplier supplier) { - if (!this.infos.isEmpty()) { - // forge needs a separate class - // noinspection Convert2Lambda - DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> new DistExecutor.SafeRunnable() { - @Override - public void run() { - ShowCounterPacket p = ShowCounterPacket.this; - String artifactName = VoteArtifactNames.client().getName(p.artifactUUID); - CounterScreen gui = new CounterScreen(p.artifactUUID, artifactName, p.invIndex, p.category, p.infos); - supplier.get().enqueueWork(() -> Minecraft.getInstance().setScreen(gui)); - } - }); - } - supplier.get().setPacketHandled(true); + this.infos = ImmutableList.copyOf(infos); } - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(this.invIndex); - buffer.writeUUID(this.artifactUUID); - buffer.writeResourceLocation(this.category); - buffer.writeVarInt(this.infos.size()); - for (Info info : this.infos) { - for (Pair entry : info.scores) { - VoteList.Stats stats = entry.getValue(); - buffer.writeFloat(stats.getWeight()); - buffer.writeFloat(stats.getFinalScore(Float.NaN)); - buffer.writeVarInt(stats.getEffectiveCount()); - buffer.writeVarIntArray(stats.getVoteCountArray()); - buffer.writeComponent(entry.getKey()); - } - buffer.writeFloat(Float.NaN); - buffer.writeResourceLocation(info.id); - buffer.writeBoolean(info.enabledCurrently); - } + @Override + public Type type() { + return TYPE; } - public static ShowCounterPacket read(FriendlyByteBuf buffer) { - int inventoryIndex = buffer.readInt(); - UUID artifactUUID = buffer.readUUID(); - ResourceLocation category = buffer.readResourceLocation(); - ImmutableList.Builder builder = ImmutableList.builder(); - for (int i = 0, size = buffer.readVarInt(); i < size; ++i) { - ImmutableList.Builder> scoresBuilder = ImmutableList.builder(); - for (float weight = buffer.readFloat(); !Float.isNaN(weight); weight = buffer.readFloat()) { - float finalScore = buffer.readFloat(); - int effectiveVoteCount = buffer.readVarInt(); - // noinspection UnstableApiUsage - ImmutableIntArray countsByLevel = ImmutableIntArray.copyOf(buffer.readVarIntArray(6)); - Component subgroup = buffer.readComponent(); - scoresBuilder.add(Pair.of(subgroup, new VoteList.Stats(weight, finalScore, effectiveVoteCount, countsByLevel))); - } - ResourceLocation id = buffer.readResourceLocation(); - boolean categoryEnabledCurrently = buffer.readBoolean(); - Optional categoryOptional = VoteCategoryHandler.getCategory(id); - if (categoryOptional.isPresent()) { - Info info = new Info(id, categoryOptional.get(), scoresBuilder.build(), categoryEnabledCurrently); - builder.add(info); + public void handle(IPayloadContext context) { + if (!this.infos.isEmpty()) { + // neoforge claims this is sufficient + if (FMLEnvironment.dist == Dist.CLIENT) { + ShowCounterPacket p = ShowCounterPacket.this; + String artifactName = VoteArtifactNames.client().getName(p.artifactUUID); + CounterScreen gui = new CounterScreen(p.artifactUUID, artifactName, p.invIndex, p.category, p.infos); + context.enqueueWork(() -> Minecraft.getInstance().setScreen(gui)); } } - return new ShowCounterPacket(inventoryIndex, artifactUUID, category, builder.build()); } public static Optional create(int inventoryId, UUID artifactID, ResourceLocation categoryID, MinecraftServer server) { @@ -174,5 +142,13 @@ public Info(ResourceLocation id, VoteCategory category, List roleMap = ImmutableSortedMap.of(); - public VoteRoleHandler() { + private final HolderLookup.Provider registries; + + public VoteRoleHandler(HolderLookup.Provider registries) { super(GSON, "vote_roles"); + this.registries = registries; } public static Collection getRoles(ServerPlayer player) { @@ -64,12 +68,12 @@ public static Collection getIds() { @Override protected void apply(Map objects, ResourceManager manager, ProfilerFiller profiler) { - roleMap = ImmutableSortedMap.copyOf(Maps.transformEntries(objects, VoteRole::fromJson), Comparator.naturalOrder()); + roleMap = ImmutableSortedMap.copyOf(Maps.transformEntries(objects, (k, v) -> VoteRole.fromJson(k, v, this.registries)), Comparator.naturalOrder()); } @SubscribeEvent public static void addReloadListener(AddReloadListenerEvent event) { - event.addListener(new VoteRoleHandler()); + event.addListener(new VoteRoleHandler(event.getRegistryAccess())); } public static MutableComponent getText(ResourceLocation id) { diff --git a/src/main/java/org/teacon/voteme/screen/CommentScreen.java b/src/main/java/org/teacon/voteme/screen/CommentScreen.java index 5e65e8b..1866bc5 100644 --- a/src/main/java/org/teacon/voteme/screen/CommentScreen.java +++ b/src/main/java/org/teacon/voteme/screen/CommentScreen.java @@ -22,9 +22,11 @@ import net.minecraft.client.gui.screens.inventory.BookViewScreen; import net.minecraft.client.gui.screens.inventory.PageButton; import net.minecraft.client.renderer.Rect2i; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; +import net.minecraft.util.StringUtil; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableInt; @@ -171,7 +173,7 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { public boolean charTyped(char p_231042_1_, int p_231042_2_) { if (super.charTyped(p_231042_1_, p_231042_2_)) { return true; - } else if (SharedConstants.isAllowedChatCharacter(p_231042_1_)) { + } else if (StringUtil.isAllowedChatCharacter(p_231042_1_)) { this.pageEdit.insertText(Character.toString(p_231042_1_)); this.clearDisplayCache(); return true; @@ -276,7 +278,7 @@ private void setCurrentPageText(String text) { @Override public void render(GuiGraphics matrixStack, int mouseX, int mouseY, float partialTick) { - this.renderBackground(matrixStack); + this.renderBackground(matrixStack, mouseX, mouseY, partialTick); this.setFocused(null); // 1.17: no longer needed due to programmable pipeline usage RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); @@ -292,7 +294,7 @@ public void render(GuiGraphics matrixStack, int mouseX, int mouseY, float partia for (CommentScreen.Line line : page.lines) { matrixStack.drawString(this.font, line.asComponent, line.x, line.y, 0xFF000000, false); } - this.renderHighlight(page.selection); + this.renderHighlight(matrixStack, page.selection); this.renderCursor(matrixStack, page.cursor, page.cursorAtEnd); } @@ -311,30 +313,14 @@ private void renderCursor(GuiGraphics matrixStack, CommentScreen.Point cursorPos } - private void renderHighlight(Rect2i[] highlights) { - Tesselator t = Tesselator.getInstance(); - BufferBuilder builder = t.getBuilder(); - // 1.17: no longer needed due to programmable pipeline usage - RenderSystem.setShaderColor(0.0F, 0.0F, 1.0F, 1.0F); - // RenderSystem.disableTexture(); - RenderSystem.enableColorLogicOp(); - RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE); - builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION); - - for (Rect2i highlight : highlights) { - int minX = highlight.getX(); - int minY = highlight.getY(); - int maxX = minX + highlight.getWidth(); - int maxY = minY + highlight.getHeight(); - builder.vertex(minX, maxY, 0.0D).endVertex(); - builder.vertex(maxX, maxY, 0.0D).endVertex(); - builder.vertex(maxX, minY, 0.0D).endVertex(); - builder.vertex(minX, minY, 0.0D).endVertex(); + private void renderHighlight(GuiGraphics guiGraphics, Rect2i[] highlights) { + for (Rect2i rect2i : highlights) { + int i = rect2i.getX(); + int j = rect2i.getY(); + int k = i + rect2i.getWidth(); + int l = j + rect2i.getHeight(); + guiGraphics.fill(RenderType.guiTextHighlight(), i, j, k, l, -16776961); } - - t.end(); - RenderSystem.disableColorLogicOp(); - // RenderSystem.enableTexture(); } private CommentScreen.Point convertScreenToLocal(CommentScreen.Point point) { diff --git a/src/main/java/org/teacon/voteme/screen/CounterScreen.java b/src/main/java/org/teacon/voteme/screen/CounterScreen.java index e09aabd..84b5286 100644 --- a/src/main/java/org/teacon/voteme/screen/CounterScreen.java +++ b/src/main/java/org/teacon/voteme/screen/CounterScreen.java @@ -10,17 +10,18 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.ImageButton; +import net.minecraft.client.gui.components.WidgetSprites; import net.minecraft.client.gui.font.TextFieldHelper; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.FormattedCharSequence; import net.minecraft.world.item.DyeColor; +import net.neoforged.neoforge.network.PacketDistributor; import org.apache.commons.lang3.tuple.Pair; import org.teacon.voteme.network.ChangeNameByCounterPacket; import org.teacon.voteme.network.ChangePropsByCounterPacket; import org.teacon.voteme.network.ShowCounterPacket; -import org.teacon.voteme.network.VoteMePacketManager; import org.teacon.voteme.vote.VoteList; import javax.annotation.ParametersAreNonnullByDefault; @@ -33,9 +34,16 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public final class CounterScreen extends Screen { - private static final ResourceLocation TEXTURE = new ResourceLocation("voteme:textures/gui/counter.png"); + private static final ResourceLocation TEXTURE = ResourceLocation.parse("voteme:textures/gui/counter.png"); private static final Component EMPTY_ARTIFACT_TEXT = Component.translatable("gui.voteme.counter.empty_artifact").withStyle(style -> style.withItalic(true)); + // FIXME Please split the widget texture out + public static final WidgetSprites PREV_BUTTON_SPRITE = new WidgetSprites(TEXTURE, TEXTURE, TEXTURE, TEXTURE); + public static final WidgetSprites NEXT_BUTTON_SPRITE = new WidgetSprites(TEXTURE, TEXTURE, TEXTURE, TEXTURE); + // 原始数据如下。依次是:画布 X,画布 Y,贴图宽,贴图高,贴图高度差值(啥意思?),贴图起始 X(U),贴图起始 Y(V) + // this.width / 2 - 99, this.height / 2 - 20, 18, 19, 12, 207, 0 + // this.width / 2 - 79, this.height / 2 - 20, 18, 19, 32, 207, 0 + private static final int BUTTON_TEXT_COLOR = 0xFF9DA95D; private static final int TEXT_COLOR = 0xFF000000 | DyeColor.BLACK.getTextColor(); private static final int SELECTION_COLOR = 0xFF000000 | DyeColor.BLUE.getTextColor(); @@ -72,8 +80,10 @@ public CounterScreen(UUID artifactUUID, String artifactName, int inventoryIndex, @Override protected void init() { Minecraft mc = Objects.requireNonNull(this.minecraft); - this.addRenderableWidget(new ImageButton(this.width / 2 - 99, this.height / 2 - 20, 18, 19, 12, 207, 0, TEXTURE, this::onPrevButtonClick)); - this.addRenderableWidget(new ImageButton(this.width / 2 - 79, this.height / 2 - 20, 18, 19, 32, 207, 0, TEXTURE, this::onNextButtonClick)); + //this.addRenderableWidget(new ImageButton(this.width / 2 - 99, this.height / 2 - 20, 18, 19, 12, 207, 0, TEXTURE, this::onPrevButtonClick)); + //this.addRenderableWidget(new ImageButton(this.width / 2 - 79, this.height / 2 - 20, 18, 19, 32, 207, 0, TEXTURE, this::onNextButtonClick)); + this.addRenderableWidget(new ImageButton(this.width / 2 - 79, this.height / 2 - 20, 18, 19, PREV_BUTTON_SPRITE, this::onPrevButtonClick)); + this.addRenderableWidget(new ImageButton(this.width / 2 - 79, this.height / 2 - 20, 18, 19, NEXT_BUTTON_SPRITE, this::onNextButtonClick)); this.okButton = this.addRenderableWidget(new BottomButton(this.width / 2 + 61, this.height / 2 + 77, this::onOKButtonClick, Component.translatable("gui.voteme.counter.ok"))); this.cancelButton = this.addRenderableWidget(new BottomButton(this.width / 2 + 61, this.height / 2 + 77, this::onCancelButtonClick, Component.translatable("gui.voteme.counter.cancel"))); this.renameButton = this.addRenderableWidget(new BottomButton(this.width / 2 + 19, this.height / 2 + 77, this::onRenameButtonClick, Component.translatable("gui.voteme.counter.rename"))); @@ -84,7 +94,7 @@ protected void init() { @Override public void render(GuiGraphics matrixStack, int mouseX, int mouseY, float partialTicks) { - this.renderBackground(matrixStack); + this.renderBackground(matrixStack, mouseX, mouseY, partialTicks); this.drawGuiContainerBackgroundLayer(matrixStack, partialTicks, mouseX, mouseY); super.render(matrixStack, mouseX, mouseY, partialTicks); this.drawGuiContainerForegroundLayer(matrixStack, partialTicks, mouseX, mouseY); @@ -125,7 +135,7 @@ public void removed() { .filter(i -> !i.enabledCurrently && this.enabledInfos.contains(i.id)).map(i -> i.id).iterator(); Iterable disabled = () -> this.infoCollection.stream() .filter(i -> i.enabledCurrently && !this.enabledInfos.contains(i.id)).map(i -> i.id).iterator(); - VoteMePacketManager.CHANNEL.sendToServer(ChangePropsByCounterPacket.create( + PacketDistributor.sendToServer(ChangePropsByCounterPacket.create( this.inventoryIndex, this.artifactUUID, info.id, enabled, disabled)); } } @@ -148,7 +158,7 @@ private void onCancelButtonClick(Button button) { private void onRenameButtonClick(Button button) { ChangeNameByCounterPacket packet = ChangeNameByCounterPacket.create(this.inventoryIndex, this.artifactUUID, this.oldArtifact = this.artifact); - VoteMePacketManager.CHANNEL.sendToServer(packet); + PacketDistributor.sendToServer(packet); } private void onSwitchClick(Button button) { @@ -285,8 +295,13 @@ private static List rotateAsFirst(List initial, Predicate filter) { } private static class BottomButton extends ImageButton { + + // FIXME Split texture out as separate file + public static final WidgetSprites BOTTOM_BUTTON_SPRITE = new WidgetSprites(CounterScreen.TEXTURE, CounterScreen.TEXTURE); + public BottomButton(int x, int y, Button.OnPress onPress, Component title) { - super(x, y, 39, 19, 136, 207, 0, CounterScreen.TEXTURE, 256, 256, onPress, title); + super(x, y, 39, 19, BOTTOM_BUTTON_SPRITE, onPress, title); + // u = 136, v = 207, vDiff = 0, texture total width = 256, texture total height = 256, } @Override diff --git a/src/main/java/org/teacon/voteme/screen/VoterScreen.java b/src/main/java/org/teacon/voteme/screen/VoterScreen.java index 0463def..2193f81 100644 --- a/src/main/java/org/teacon/voteme/screen/VoterScreen.java +++ b/src/main/java/org/teacon/voteme/screen/VoterScreen.java @@ -19,6 +19,7 @@ import net.minecraft.util.FormattedCharSequence; import net.minecraft.util.Mth; import net.minecraft.world.item.DyeColor; +import net.neoforged.neoforge.network.PacketDistributor; import org.teacon.voteme.network.ShowVoterPacket; import org.teacon.voteme.network.SubmitCommentPacket; import org.teacon.voteme.network.SubmitVotePacket; @@ -30,7 +31,7 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public final class VoterScreen extends Screen { - private static final ResourceLocation TEXTURE = new ResourceLocation("voteme:textures/gui/voter.png"); + private static final ResourceLocation TEXTURE = ResourceLocation.parse("voteme:textures/gui/voter.png"); private static final int BUTTON_TEXT_COLOR = 0xFFFFFFFF; private static final int TEXT_COLOR = 0xFF000000 | DyeColor.BLACK.getTextColor(); @@ -70,7 +71,7 @@ protected void init() { @Override public void render(GuiGraphics matrixStack, int mouseX, int mouseY, float partialTicks) { - this.renderBackground(matrixStack); + this.renderBackground(matrixStack, mouseX, mouseY, partialTicks); this.drawGuiContainerBackgroundLayer(matrixStack, partialTicks, mouseX, mouseY); super.render(matrixStack, mouseX, mouseY, partialTicks); this.drawGuiContainerForegroundLayer(matrixStack, partialTicks, mouseX, mouseY); @@ -92,11 +93,11 @@ public boolean isPauseScreen() { public void removed() { if (!this.votes.isEmpty()) { SubmitVotePacket packet = SubmitVotePacket.create(this.artifactID, this.votes); - VoteMePacketManager.CHANNEL.sendToServer(packet); + PacketDistributor.sendToServer(packet); } if (!this.currentComments.equals(this.oldComments)) { SubmitCommentPacket packet = SubmitCommentPacket.create(this.artifactID, this.currentComments); - VoteMePacketManager.CHANNEL.sendToServer(packet); + PacketDistributor.sendToServer(packet); } } @@ -276,9 +277,9 @@ public void renderWidget(GuiGraphics matrixStack, int mouseX, int mouseY, float } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double delta) { - if (delta != 0) { - this.changeSlideCenter(this.slideCenter - 12 * delta); + public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) { + if (scrollY != 0) { + this.changeSlideCenter(this.slideCenter - 12 * scrollY); return true; } return false; diff --git a/src/main/java/org/teacon/voteme/sync/AnnouncementSerializer.java b/src/main/java/org/teacon/voteme/sync/AnnouncementSerializer.java index 1418952..94ef2d7 100644 --- a/src/main/java/org/teacon/voteme/sync/AnnouncementSerializer.java +++ b/src/main/java/org/teacon/voteme/sync/AnnouncementSerializer.java @@ -110,21 +110,21 @@ yield new Comments(key, nbt.getList(KEY_COMMENTS, Tag.TAG_STRING) } case VOTE -> { VoteKey key = new VoteKey(nbt.getUUID(KEY_ARTIFACT), - new ResourceLocation(nbt.getString(KEY_CATEGORY)), nbt.getUUID(KEY_VOTER)); + ResourceLocation.parse(nbt.getString(KEY_CATEGORY)), nbt.getUUID(KEY_VOTER)); Instant time = nbt.contains(KEY_VOTE_TIME, Tag.TAG_LONG) ? Instant.ofEpochMilli(nbt.getLong(KEY_VOTE_TIME)) : VoteList.DEFAULT_VOTE_TIME; yield new Vote(key, nbt.getInt(KEY_LEVEL), nbt.getList(KEY_VOTE_ROLES, Tag.TAG_STRING) - .stream().map(t -> new ResourceLocation(t.getAsString())).collect(toImmutableSet()), time); + .stream().map(t -> ResourceLocation.parse(t.getAsString())).collect(toImmutableSet()), time); } case VOTE_DISABLED -> { VoteDisabledKey key = new VoteDisabledKey(nbt - .getUUID(KEY_ARTIFACT), new ResourceLocation(nbt.getString(KEY_CATEGORY))); + .getUUID(KEY_ARTIFACT), ResourceLocation.parse(nbt.getString(KEY_CATEGORY))); yield new VoteDisabled(key, nbt.contains(KEY_DISABLED, Tag.TAG_BYTE) ? Optional.of(nbt.getBoolean(KEY_DISABLED)) : Optional.empty()); } case VOTE_STATS -> { - VoteStatsKey key = new VoteStatsKey(nbt.getUUID(KEY_ARTIFACT), new ResourceLocation(nbt - .getString(KEY_CATEGORY)), new ResourceLocation(nbt.getString(KEY_VOTE_ROLE))); + VoteStatsKey key = new VoteStatsKey(nbt.getUUID(KEY_ARTIFACT), ResourceLocation.parse(nbt + .getString(KEY_CATEGORY)), ResourceLocation.parse(nbt.getString(KEY_VOTE_ROLE))); // noinspection UnstableApiUsage yield new VoteStats(key, copyOf(nbt.getIntArray(KEY_LEVEL_COUNTS))); } diff --git a/src/main/java/org/teacon/voteme/sync/RedisSynchronizer.java b/src/main/java/org/teacon/voteme/sync/RedisSynchronizer.java index f1f1e61..e6c569f 100644 --- a/src/main/java/org/teacon/voteme/sync/RedisSynchronizer.java +++ b/src/main/java/org/teacon/voteme/sync/RedisSynchronizer.java @@ -192,7 +192,7 @@ private static AnnounceKey fromRedisKey(String redisKey) { String[] parts = redisKeyParts[2].split(":"); checkArgument(parts.length == 4, "invalid message"); UUID artifactID = UUID.fromString(parts[0]); - ResourceLocation categoryID = new ResourceLocation(parts[1], parts[2]); + ResourceLocation categoryID = ResourceLocation.fromNamespaceAndPath(parts[1], parts[2]); UUID voterID = UUID.fromString(parts[3]); return new VoteKey(artifactID, categoryID, voterID); } @@ -200,15 +200,15 @@ private static AnnounceKey fromRedisKey(String redisKey) { String[] parts = redisKeyParts[2].split(":"); checkArgument(parts.length == 3, "invalid message"); UUID artifactID = UUID.fromString(parts[0]); - ResourceLocation categoryID = new ResourceLocation(parts[1], parts[2]); + ResourceLocation categoryID = ResourceLocation.fromNamespaceAndPath(parts[1], parts[2]); return new VoteDisabledKey(artifactID, categoryID); } case VOTE_STATS -> { String[] parts = redisKeyParts[2].split(":"); checkArgument(parts.length == 5, "invalid message"); UUID artifactID = UUID.fromString(parts[0]); - ResourceLocation categoryID = new ResourceLocation(parts[1], parts[2]); - ResourceLocation roleID = new ResourceLocation(parts[3], parts[4]); + ResourceLocation categoryID = ResourceLocation.fromNamespaceAndPath(parts[1], parts[2]); + ResourceLocation roleID = ResourceLocation.fromNamespaceAndPath(parts[3], parts[4]); return new VoteStatsKey(artifactID, categoryID, roleID); } default -> throw new IllegalArgumentException("unsupported announce key: " + announceKey); @@ -245,7 +245,7 @@ private static CompletableFuture dispatch(AnnounceKe // noinspection UnstableApiUsage ImmutableSet.Builder roles = ImmutableSet.builderWithExpectedSize(expectedSize); for (int i = 0; map.containsKey("role:" + i); ++i) { - ResourceLocation role = new ResourceLocation(map.get("role:" + i)); + ResourceLocation role = ResourceLocation.parse(map.get("role:" + i)); roles.add(role); } Instant time = Instant.parse(checkNotNull(map.getOrDefault("time", Instant.EPOCH.toString()))); diff --git a/src/main/java/org/teacon/voteme/vote/VoteArtifactNames.java b/src/main/java/org/teacon/voteme/vote/VoteArtifactNames.java index 054914a..d0e0b5d 100644 --- a/src/main/java/org/teacon/voteme/vote/VoteArtifactNames.java +++ b/src/main/java/org/teacon/voteme/vote/VoteArtifactNames.java @@ -15,13 +15,13 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.util.thread.EffectiveSide; -import net.minecraftforge.network.PacketDistributor; -import net.minecraftforge.server.ServerLifecycleHooks; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.fml.util.thread.EffectiveSide; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.event.tick.ServerTickEvent; +import net.neoforged.neoforge.network.PacketDistributor; +import net.neoforged.neoforge.server.ServerLifecycleHooks; import org.teacon.voteme.VoteMe; import org.teacon.voteme.network.SyncArtifactNamePacket; import org.teacon.voteme.network.VoteMePacketManager; @@ -35,7 +35,7 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.GAME) public final class VoteArtifactNames { private boolean needsSynchronizationToClient = false; private final Map names = new TreeMap<>(); @@ -247,16 +247,16 @@ public static void onLogin(PlayerEvent.PlayerLoggedInEvent event) { VoteArtifactNames instance = VoteDataStorage.get(Objects.requireNonNull(player.getServer())).getArtifactNames(); if (player instanceof ServerPlayer serverPlayer) { SyncArtifactNamePacket packet = SyncArtifactNamePacket.create(instance.names, instance.aliases); - VoteMePacketManager.CHANNEL.send(PacketDistributor.PLAYER.with(() -> serverPlayer), packet); + PacketDistributor.sendToPlayer(serverPlayer, packet); } } @SubscribeEvent - public static void onTick(TickEvent.ServerTickEvent event) { + public static void onTick(ServerTickEvent.Pre event) { VoteArtifactNames instance = VoteDataStorage.get(ServerLifecycleHooks.getCurrentServer()).getArtifactNames(); - if (instance.needsSynchronizationToClient && event.phase == TickEvent.Phase.START) { + if (instance.needsSynchronizationToClient) { SyncArtifactNamePacket packet = SyncArtifactNamePacket.create(instance.names, instance.aliases); - VoteMePacketManager.CHANNEL.send(PacketDistributor.ALL.noArg(), packet); + PacketDistributor.sendToAllPlayers(packet); } } diff --git a/src/main/java/org/teacon/voteme/vote/VoteDataStorage.java b/src/main/java/org/teacon/voteme/vote/VoteDataStorage.java index 8120a0a..a820010 100644 --- a/src/main/java/org/teacon/voteme/vote/VoteDataStorage.java +++ b/src/main/java/org/teacon/voteme/vote/VoteDataStorage.java @@ -11,6 +11,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.Util; +import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; @@ -18,12 +19,12 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.saveddata.SavedData; import net.minecraft.world.level.storage.DimensionDataStorage; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.server.ServerStartingEvent; -import net.minecraftforge.event.server.ServerStoppingEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.neoforged.neoforge.event.server.ServerStoppingEvent; +import net.neoforged.neoforge.event.tick.ServerTickEvent; +import net.neoforged.neoforge.server.ServerLifecycleHooks; import org.apache.commons.lang3.text.StrSubstitutor; import org.teacon.voteme.VoteMe; import org.teacon.voteme.category.VoteCategoryHandler; @@ -42,7 +43,7 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) +@EventBusSubscriber(bus = EventBusSubscriber.Bus.GAME) public final class VoteDataStorage extends SavedData implements Closeable { private int nextIndex; @@ -55,7 +56,7 @@ public final class VoteDataStorage extends SavedData implements Closeable { public static VoteDataStorage get(MinecraftServer server) { DimensionDataStorage manager = server.overworld().getDataStorage(); - return manager.computeIfAbsent(VoteDataStorage::new, VoteDataStorage::new, "vote_lists"); + return manager.computeIfAbsent(new Factory<>(VoteDataStorage::new, VoteDataStorage::new), "vote_lists"); } public VoteDataStorage() { @@ -67,14 +68,14 @@ public VoteDataStorage() { this.sync = this.loadSynchronizer(); } - public VoteDataStorage(CompoundTag nbt) { + public VoteDataStorage(CompoundTag nbt, HolderLookup.Provider holderLookupProvider) { this.nextIndex = 1; this.artifactNames = new VoteArtifactNames(); this.voteLists = new Int2ObjectRBTreeMap<>(); this.voteListIDs = TreeBasedTable.create(); this.voteComments = HashBasedTable.create(); this.sync = this.loadSynchronizer(); - this.load(nbt); + this.load(nbt, holderLookupProvider); } @SuppressWarnings("deprecation") @@ -291,11 +292,8 @@ private static JsonElement toVoteStatsJson(SortedMap sco } @SubscribeEvent - public static void onServerTick(TickEvent.ServerTickEvent event) { - if (event.phase == TickEvent.Phase.START) { - MinecraftServer currentServer = ServerLifecycleHooks.getCurrentServer(); - VoteDataStorage.get(currentServer).tick(); - } + public static void onServerTick(ServerTickEvent.Pre event) { + VoteDataStorage.get(event.getServer()).tick(); } @SubscribeEvent @@ -312,7 +310,7 @@ public static void onServerStopping(ServerStoppingEvent event) { } } - public void load(CompoundTag nbt) { + public void load(CompoundTag nbt, HolderLookup.Provider holderLookupProvider) { VoteMe.LOGGER.info("Loading vote list data on server ..."); // vote list next index and index hints @@ -322,7 +320,7 @@ public void load(CompoundTag nbt) { for (Tag tag : hintTags) { CompoundTag child = (CompoundTag) tag; int hint = child.contains("VoteListIndex", Tag.TAG_INT) ? child.getInt("VoteListIndex") : this.nextIndex; - this.getIdOrCreate(child.getUUID("ArtifactUUID"), new ResourceLocation(child.getString("Category")), hint); + this.getIdOrCreate(child.getUUID("ArtifactUUID"), ResourceLocation.parse(child.getString("Category")), hint); } // announcements @@ -380,7 +378,7 @@ public void load(CompoundTag nbt) { } @Override - public CompoundTag save(CompoundTag nbt) { + public CompoundTag save(CompoundTag nbt, HolderLookup.Provider holderLookupProvider) { VoteMe.LOGGER.info("Saving vote list data on server ..."); // vote list next index and index hints diff --git a/src/main/java/org/teacon/voteme/vote/VoteList.java b/src/main/java/org/teacon/voteme/vote/VoteList.java index bf5f44f..7d3953a 100644 --- a/src/main/java/org/teacon/voteme/vote/VoteList.java +++ b/src/main/java/org/teacon/voteme/vote/VoteList.java @@ -5,14 +5,19 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.ListMultimap; import com.google.common.primitives.ImmutableIntArray; +import io.netty.buffer.ByteBuf; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import org.apache.commons.lang3.tuple.Triple; +import org.teacon.voteme.network.VoteMeStreamUtils; import org.teacon.voteme.roles.VoteRole; import org.teacon.voteme.roles.VoteRoleHandler; import org.teacon.voteme.sync.VoteSynchronizer.Announcement; @@ -219,7 +224,7 @@ public void loadLegacyNBT(CompoundTag source) { int level = Mth.clamp(child.getInt("Level"), 1, 5); ImmutableSet.Builder roleBuilder = ImmutableSet.builder(); for (Tag roleNBT : child.getList("VoteRoles", Tag.TAG_STRING)) { - roleBuilder.add(new ResourceLocation(roleNBT.getAsString())); + roleBuilder.add(ResourceLocation.parse(roleNBT.getAsString())); } ImmutableSet roles = roleBuilder.build(); Instant voteTime = DEFAULT_VOTE_TIME; @@ -281,12 +286,21 @@ public float getFinalScore() { } public static VoteDisabledKey deserializeKey(CompoundTag source) { - return new VoteDisabledKey(source.getUUID("ArtifactUUID"), new ResourceLocation(source.getString("Category"))); + return new VoteDisabledKey(source.getUUID("ArtifactUUID"), ResourceLocation.parse(source.getString("Category"))); } @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public static final class Stats { + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.FLOAT, stats -> stats.weight, + ByteBufCodecs.FLOAT, stats -> stats.finalScore, + ByteBufCodecs.VAR_INT, stats -> stats.effectiveCount, + VoteMeStreamUtils.IMMUTABLE_INT_ARRAY, stats -> stats.voteCountsByLevel, + Stats::new + ); + private final float weight; private final float finalScore; private final int effectiveCount; diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/neoforge.mods.toml similarity index 74% rename from src/main/resources/META-INF/mods.toml rename to src/main/resources/META-INF/neoforge.mods.toml index f0f4785..a481842 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -1,5 +1,5 @@ modLoader="javafml" -loaderVersion="[47,)" +loaderVersion="[4,)" license="BSD-3-Clause" [[mods]] @@ -10,16 +10,16 @@ authors="TeaConMC, yuriscat (Yuri's Cat), 3TUSK, ustc-zzzz" description="Minecraft mod for in-game voting." [[dependencies.voteme]] -modId="forge" -mandatory=true -versionRange="[47,)" +modId="neoforge" +type="required" +versionRange="[21,)" ordering="NONE" side="BOTH" [[dependencies.voteme]] modId="minecraft" -mandatory=true -versionRange="[1.20.1,)" +type="required" +versionRange="[1.21,1.21.2)" ordering="NONE" side="BOTH" diff --git a/src/test/java/org/teacon/voteme/VoteMeTest.java b/src/test/java/org/teacon/voteme/VoteMeTest.java index 9c910f2..3be197a 100644 --- a/src/test/java/org/teacon/voteme/VoteMeTest.java +++ b/src/test/java/org/teacon/voteme/VoteMeTest.java @@ -1,6 +1,6 @@ package org.teacon.voteme; -import net.minecraftforge.fml.common.Mod; +import net.neoforged.fml.common.Mod; @Mod("voteme_test") public class VoteMeTest {