From 668ec161d9c2def901b62e3fb31e38aefae875c6 Mon Sep 17 00:00:00 2001 From: Daniel Norris Date: Thu, 24 Aug 2023 13:25:54 +0100 Subject: [PATCH] feat(forge20): port to 1.20.1 --- build.gradle | 3 - forge20/build.gradle | 67 +++++ .../java/com/envyful/crates/EnvyCrates.java | 176 ++++++++++++ .../crates/command/CrateTabCompleter.java | 27 ++ .../crates/command/EnvyCrateCommand.java | 29 ++ .../crates/command/ForgeEnvyPlayerSender.java | 25 ++ .../crates/command/GiveKeyAllCommand.java | 38 +++ .../crates/command/GiveKeyCommand.java | 36 +++ .../envyful/crates/command/ReloadCommand.java | 30 +++ .../crates/command/SetCrateCommand.java | 47 ++++ .../crates/config/EnvyCratesLocale.java | 65 +++++ .../crates/listener/CrateBreakListener.java | 33 +++ .../listener/CrateInteractListener.java | 88 ++++++ .../com/envyful/crates/type/CrateFactory.java | 124 +++++++++ .../envyful/crates/type/crate/CrateType.java | 27 ++ .../crates/type/crate/CrateTypeFactory.java | 105 ++++++++ .../type/crate/impl/AbstractCrateType.java | 73 +++++ .../type/crate/impl/SimpleItemCrate.java | 251 ++++++++++++++++++ .../crates/type/reward/RewardType.java | 26 ++ .../crates/type/reward/RewardTypeFactory.java | 38 +++ .../type/reward/impl/AbstractRewardType.java | 49 ++++ .../reward/impl/SimpleCommandRewardType.java | 67 +++++ forge20/src/main/resources/META-INF/mods.toml | 29 ++ forge20/src/main/resources/pack.mcmeta | 6 + settings.gradle | 1 + 25 files changed, 1457 insertions(+), 3 deletions(-) create mode 100644 forge20/build.gradle create mode 100644 forge20/src/main/java/com/envyful/crates/EnvyCrates.java create mode 100644 forge20/src/main/java/com/envyful/crates/command/CrateTabCompleter.java create mode 100644 forge20/src/main/java/com/envyful/crates/command/EnvyCrateCommand.java create mode 100644 forge20/src/main/java/com/envyful/crates/command/ForgeEnvyPlayerSender.java create mode 100644 forge20/src/main/java/com/envyful/crates/command/GiveKeyAllCommand.java create mode 100644 forge20/src/main/java/com/envyful/crates/command/GiveKeyCommand.java create mode 100644 forge20/src/main/java/com/envyful/crates/command/ReloadCommand.java create mode 100644 forge20/src/main/java/com/envyful/crates/command/SetCrateCommand.java create mode 100644 forge20/src/main/java/com/envyful/crates/config/EnvyCratesLocale.java create mode 100644 forge20/src/main/java/com/envyful/crates/listener/CrateBreakListener.java create mode 100644 forge20/src/main/java/com/envyful/crates/listener/CrateInteractListener.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/CrateFactory.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/crate/CrateType.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/crate/CrateTypeFactory.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/crate/impl/AbstractCrateType.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/crate/impl/SimpleItemCrate.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/reward/RewardType.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/reward/RewardTypeFactory.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/reward/impl/AbstractRewardType.java create mode 100644 forge20/src/main/java/com/envyful/crates/type/reward/impl/SimpleCommandRewardType.java create mode 100644 forge20/src/main/resources/META-INF/mods.toml create mode 100644 forge20/src/main/resources/pack.mcmeta diff --git a/build.gradle b/build.gradle index 90405aa..3eb5046 100644 --- a/build.gradle +++ b/build.gradle @@ -4,9 +4,6 @@ subprojects { group = 'com.envyful.crates' version = '1.1.2' - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } diff --git a/forge20/build.gradle b/forge20/build.gradle new file mode 100644 index 0000000..9f45edc --- /dev/null +++ b/forge20/build.gradle @@ -0,0 +1,67 @@ +plugins { + id 'net.minecraftforge.gradle' version '[6.0,6.2)' + id("com.github.johnrengelman.shadow") version "8.1.1" +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +forgeVersion = "1.20.1" + +minecraft { + mappings channel: 'official', version: '1.20.1' +} + +sourceSets.main.resources { srcDir 'src/generated/resources' } + +repositories { + maven { + name = 'spongepowered-repo' + url = 'https://repo.spongepowered.org/maven' + } + + maven { url 'https://jitpack.io' } + + ivy { + setUrl('https://download.nodecdn.net/containers/reforged/server/release') + metadataSources { + artifact() + } + patternLayout { + artifact('[revision]/[artifact].[ext]') + } + } +} + +dependencies { + minecraft "net.minecraftforge:forge:1.20.1-47.1.44" + + implementation group: 'org.spongepowered', name: 'configurate-yaml', version: '4.0.0' + + shadow group: 'com.envyful.api', name: 'commons', version: '5.0.1' + shadow (group: 'com.envyful.api', name: 'forge20', version: '5.0.1') { + transitive = false; + } +} + +shadowJar { + finalizedBy('reobfJar') + configurations = [project.configurations.shadow] + zip64 = true + setArchiveClassifier('') + setArchiveBaseName(rootProject.name + "-Forge") + + relocate('org.spongepowered.configurate', 'com.envyful.crates.forge.shade.configurate') + relocate('org.yaml.snakeyaml', 'com.envyful.crates.forge.shade.snakeyaml') + relocate('io.leangen.geantyref', 'com.envyful.crates.forge.shade.geantyref') + relocate('com.google.gson', 'com.envyful.crates.forge.shade.gson') + relocate('com.zaxxer', 'com.envyful.crates.forge.shade.hikari') + relocate('org.slf4j', 'com.envyful.crates.forge.shade.slf4j') + relocate('com.envyful.api', 'com.envyful.crates.forge.shade.envy.api') + relocate('org.bstats', 'com.envyful.crates.forge.shade.bstats') + + + exclude "**/module-info.class" +} + +jar.finalizedBy('shadowJar') +build.finalizedBy('versionedRelease') \ No newline at end of file diff --git a/forge20/src/main/java/com/envyful/crates/EnvyCrates.java b/forge20/src/main/java/com/envyful/crates/EnvyCrates.java new file mode 100644 index 0000000..026b9cc --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/EnvyCrates.java @@ -0,0 +1,176 @@ +package com.envyful.crates; + +import com.envyful.api.command.sender.SenderTypeFactory; +import com.envyful.api.concurrency.UtilLogger; +import com.envyful.api.config.yaml.YamlConfigFactory; +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.api.forge.command.ForgeCommandFactory; +import com.envyful.api.forge.gui.factory.ForgeGuiFactory; +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.api.forge.player.ForgePlayerManager; +import com.envyful.api.gui.factory.GuiFactory; +import com.envyful.api.type.UtilParse; +import com.envyful.crates.command.CrateTabCompleter; +import com.envyful.crates.command.EnvyCrateCommand; +import com.envyful.crates.command.ForgeEnvyPlayerSender; +import com.envyful.crates.config.EnvyCratesLocale; +import com.envyful.crates.listener.CrateBreakListener; +import com.envyful.crates.listener.CrateInteractListener; +import com.envyful.crates.type.CrateFactory; +import com.envyful.crates.type.crate.CrateType; +import com.envyful.crates.type.crate.CrateTypeFactory; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; +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 org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; + +@Mod("envycrates") +public class EnvyCrates { + + public static final String KEY_NBT_TAG = "ENVY_CRATES"; + + private static EnvyCrates instance; + + private Logger logger = LogManager.getLogger("envycrates"); + + private ForgePlayerManager playerManager = new ForgePlayerManager(); + private ForgeCommandFactory commandFactory = new ForgeCommandFactory(); + + private EnvyCratesLocale locale; + + public EnvyCrates() { + instance = this; + UtilLogger.setLogger(this.logger); + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onServerStopping(ServerStoppingEvent event) { + CrateFactory.save(); + } + + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) { + CrateTypeFactory.read(); + reloadConfig(); + GuiFactory.setPlatformFactory(new ForgeGuiFactory()); + + CrateFactory.load(); + + MinecraftForge.EVENT_BUS.register(new CrateInteractListener()); + MinecraftForge.EVENT_BUS.register(new CrateBreakListener()); + } + + public void reloadConfig() { + try { + this.locale = YamlConfigFactory.getInstance(EnvyCratesLocale.class); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @SubscribeEvent + public void onCommandRegister(RegisterCommandsEvent event) { + SenderTypeFactory.register(new ForgeEnvyPlayerSender()); + this.commandFactory.registerCompleter(new CrateTabCompleter()); + this.commandFactory.registerInjector(ForgeEnvyPlayer.class, (source, args) -> { + ForgeEnvyPlayer onlinePlayer = this.playerManager.getOnlinePlayer(args[0]); + + if (onlinePlayer == null) { + for (String s : this.locale.getNotOnline()) { + source.sendSystemMessage(UtilChatColour.colour(s)); + } + } + + return onlinePlayer; + }); + this.commandFactory.registerInjector(BlockPos.class, (source, args) -> { + ServerPlayer player = (ServerPlayer) source; + + if (args[0].equals("below_me")) { + BlockPos pos = player.blockPosition().below(); + BlockState blockState = player.level().getBlockState(pos); + + if (blockState.isAir()) { + for (String s : this.locale.getCannotSetAir()) { + player.sendSystemMessage(UtilChatColour.colour(s)); + } + return null; + } + + return pos; + } + + if (args[0].equalsIgnoreCase("looking")) { + BlockHitResult clip = player.level().clip(new ClipContext( + player.position(), + player.position().add(player.getLookAngle().scale(5)), + ClipContext.Block.COLLIDER, + ClipContext.Fluid.NONE, player)); + + if (clip.getType() == BlockHitResult.Type.MISS) { + for (String s : this.locale.getCannotSetAir()) { + player.sendSystemMessage(UtilChatColour.colour(s)); + } + return null; + } + + return clip.getBlockPos(); + } + + String[] split = args[0].split(","); + + if (split.length != 3) { + return null; + } + + BlockPos pos = new BlockPos( + UtilParse.parseInteger(split[0].replace("~", player.position().x + "")).orElse(-1), + UtilParse.parseInteger(split[1].replace("~", player.position().y + "")).orElse(-1), + UtilParse.parseInteger(split[2].replace("~", player.position().z + "")).orElse(-1) + ); + + BlockState blockState = player.level().getBlockState(pos); + + if (blockState.isAir()) { + for (String s : this.locale.getCannotSetAir()) { + player.sendSystemMessage(UtilChatColour.colour(s)); + } + return null; + } + + return pos; + }); + this.commandFactory.registerInjector(CrateType.class, (source, args) -> { + return CrateFactory.get(args[0]); //TODO + }); + this.commandFactory.registerCommand(event.getDispatcher(), new EnvyCrateCommand()); + } + + public static EnvyCrates getInstance() { + return instance; + } + + public static Logger getLogger() { + return instance.logger; + } + + public ForgePlayerManager getPlayerManager() { + return this.playerManager; + } + + public EnvyCratesLocale getLocale() { + return this.locale; + } +} diff --git a/forge20/src/main/java/com/envyful/crates/command/CrateTabCompleter.java b/forge20/src/main/java/com/envyful/crates/command/CrateTabCompleter.java new file mode 100644 index 0000000..2b3bafa --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/command/CrateTabCompleter.java @@ -0,0 +1,27 @@ +package com.envyful.crates.command; + +import com.envyful.api.command.injector.TabCompleter; +import com.envyful.crates.type.CrateFactory; +import com.envyful.crates.type.crate.CrateType; +import net.minecraft.commands.CommandSource; + +import java.lang.annotation.Annotation; +import java.util.List; +import java.util.stream.Collectors; + +public class CrateTabCompleter implements TabCompleter { + @Override + public Class getSenderClass() { + return CommandSource.class; + } + + @Override + public Class getCompletedClass() { + return CrateType.class; + } + + @Override + public List getCompletions(CommandSource sender, String[] currentData, Annotation... completionData) { + return CrateFactory.getAll().stream().map(CrateType::id).collect(Collectors.toList()); + } +} diff --git a/forge20/src/main/java/com/envyful/crates/command/EnvyCrateCommand.java b/forge20/src/main/java/com/envyful/crates/command/EnvyCrateCommand.java new file mode 100644 index 0000000..b9ff875 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/command/EnvyCrateCommand.java @@ -0,0 +1,29 @@ +package com.envyful.crates.command; + +import com.envyful.api.command.annotate.Command; +import com.envyful.api.command.annotate.Permissible; +import com.envyful.api.command.annotate.SubCommands; +import com.envyful.api.command.annotate.executor.CommandProcessor; +import com.envyful.api.command.annotate.executor.Sender; +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.crates.EnvyCrates; +import net.minecraft.commands.CommandSource; + +@Command( + value = "envycrates", + description = "Root crates command", + aliases = { + "crates" + } +) +@Permissible("com.envyful.crates.command") +@SubCommands({ReloadCommand.class, GiveKeyCommand.class, SetCrateCommand.class, GiveKeyAllCommand.class}) +public class EnvyCrateCommand { + + @CommandProcessor + public void onCommand(@Sender CommandSource sender, String[] args) { + for (String s : EnvyCrates.getInstance().getLocale().getRootCommand()) { + sender.sendSystemMessage(UtilChatColour.colour(s)); + } + } +} diff --git a/forge20/src/main/java/com/envyful/crates/command/ForgeEnvyPlayerSender.java b/forge20/src/main/java/com/envyful/crates/command/ForgeEnvyPlayerSender.java new file mode 100644 index 0000000..f3c4d2e --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/command/ForgeEnvyPlayerSender.java @@ -0,0 +1,25 @@ +package com.envyful.crates.command; + +import com.envyful.api.command.sender.SenderType; +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.crates.EnvyCrates; +import net.minecraft.commands.CommandSource; +import net.minecraft.server.level.ServerPlayer; + +public class ForgeEnvyPlayerSender implements SenderType { + + @Override + public Class getType() { + return ForgeEnvyPlayer.class; + } + + @Override + public boolean isAccepted(CommandSource sender) { + return sender instanceof ServerPlayer; + } + + @Override + public ForgeEnvyPlayer getInstance(CommandSource sender) { + return EnvyCrates.getInstance().getPlayerManager().getPlayer((ServerPlayer) sender); + } +} \ No newline at end of file diff --git a/forge20/src/main/java/com/envyful/crates/command/GiveKeyAllCommand.java b/forge20/src/main/java/com/envyful/crates/command/GiveKeyAllCommand.java new file mode 100644 index 0000000..15f237b --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/command/GiveKeyAllCommand.java @@ -0,0 +1,38 @@ +package com.envyful.crates.command; + +import com.envyful.api.command.annotate.Child; +import com.envyful.api.command.annotate.Command; +import com.envyful.api.command.annotate.Permissible; +import com.envyful.api.command.annotate.executor.Argument; +import com.envyful.api.command.annotate.executor.CommandProcessor; +import com.envyful.api.command.annotate.executor.Completable; +import com.envyful.api.command.annotate.executor.Sender; +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.crates.EnvyCrates; +import com.envyful.crates.type.crate.CrateType; +import net.minecraft.commands.CommandSource; + +@Command( + value = "giveall", + description = "Gives a key to the command", + aliases = { + "givekeyall", + "gka" + } +) +@Permissible("com.envyful.crates.command.give.all") +@Child +public class GiveKeyAllCommand { + + @CommandProcessor + public void onCommand(@Sender CommandSource sender, + @Completable(CrateTabCompleter.class) @Argument CrateType crate, + @Argument(defaultValue = "1") int amount) { + sender.sendSystemMessage(UtilChatColour.colour("&e&l(!) &eGiving keys to all online players")); + + for (ForgeEnvyPlayer player : EnvyCrates.getInstance().getPlayerManager().getOnlinePlayers()) { + crate.giveKey(player, amount); + } + } +} diff --git a/forge20/src/main/java/com/envyful/crates/command/GiveKeyCommand.java b/forge20/src/main/java/com/envyful/crates/command/GiveKeyCommand.java new file mode 100644 index 0000000..e5a39df --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/command/GiveKeyCommand.java @@ -0,0 +1,36 @@ +package com.envyful.crates.command; + +import com.envyful.api.command.annotate.Child; +import com.envyful.api.command.annotate.Command; +import com.envyful.api.command.annotate.Permissible; +import com.envyful.api.command.annotate.executor.Argument; +import com.envyful.api.command.annotate.executor.CommandProcessor; +import com.envyful.api.command.annotate.executor.Completable; +import com.envyful.api.command.annotate.executor.Sender; +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.api.forge.command.completion.player.PlayerTabCompleter; +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.crates.type.crate.CrateType; +import net.minecraft.commands.CommandSource; + +@Command( + value = "givekey", + description = "Gives a key to the command", + aliases = { + "give", + "gk" + } +) +@Permissible("com.envyful.crates.command.give") +@Child +public class GiveKeyCommand { + + @CommandProcessor + public void onCommand(@Sender CommandSource sender, + @Completable(PlayerTabCompleter.class) @Argument ForgeEnvyPlayer target, + @Completable(CrateTabCompleter.class) @Argument CrateType crate, + @Argument(defaultValue = "1") int amount) { + sender.sendSystemMessage(UtilChatColour.colour("&e&l(!) &eGiving keys")); + crate.giveKey(target, amount); + } +} diff --git a/forge20/src/main/java/com/envyful/crates/command/ReloadCommand.java b/forge20/src/main/java/com/envyful/crates/command/ReloadCommand.java new file mode 100644 index 0000000..d9e24d0 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/command/ReloadCommand.java @@ -0,0 +1,30 @@ +package com.envyful.crates.command; + +import com.envyful.api.command.annotate.Child; +import com.envyful.api.command.annotate.Command; +import com.envyful.api.command.annotate.Permissible; +import com.envyful.api.command.annotate.executor.CommandProcessor; +import com.envyful.api.command.annotate.executor.Sender; +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.crates.EnvyCrates; +import com.envyful.crates.type.crate.CrateTypeFactory; +import net.minecraft.commands.CommandSource; + +@Command( + value = "reload", + description = "Reload the config", + aliases = { + "reload" + } +) +@Permissible("com.envyful.crates.command.reload") +@Child +public class ReloadCommand { + + @CommandProcessor + public void onCommand(@Sender CommandSource sender, String[] args) { + EnvyCrates.getInstance().reloadConfig(); + CrateTypeFactory.reload(); + sender.sendSystemMessage(UtilChatColour.colour("&e&l(!) &eReloaded configs & crates.")); + } +} diff --git a/forge20/src/main/java/com/envyful/crates/command/SetCrateCommand.java b/forge20/src/main/java/com/envyful/crates/command/SetCrateCommand.java new file mode 100644 index 0000000..d8367b2 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/command/SetCrateCommand.java @@ -0,0 +1,47 @@ +package com.envyful.crates.command; + +import com.envyful.api.command.annotate.Child; +import com.envyful.api.command.annotate.Command; +import com.envyful.api.command.annotate.Permissible; +import com.envyful.api.command.annotate.executor.Argument; +import com.envyful.api.command.annotate.executor.CommandProcessor; +import com.envyful.api.command.annotate.executor.Completable; +import com.envyful.api.command.annotate.executor.Sender; +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.crates.EnvyCrates; +import com.envyful.crates.type.CrateFactory; +import com.envyful.crates.type.crate.CrateType; +import net.minecraft.core.BlockPos; + +@Command( + value = "setcrate", + description = "Sets a crate position", + aliases = { + "sc", + "set" + } +) +@Permissible("com.envyful.crates.command.set") +@Child +public class SetCrateCommand { + + @CommandProcessor + public void onCommand(@Sender ForgeEnvyPlayer sender, + @Completable(CrateTabCompleter.class) @Argument CrateType crate, + @Argument(defaultValue = "looking") BlockPos block) { + if (CrateFactory.isCrate(sender.getParent().level(), block)) { + for (String s : EnvyCrates.getInstance().getLocale().getCrateAlreadyThere()) { + sender.message(UtilChatColour.colour(s)); + } + return; + } + + CrateFactory.add(sender.getParent().level(), block, crate); + for (String s : EnvyCrates.getInstance().getLocale().getCrateAdded()) { + sender.message(UtilChatColour.colour(s + .replace("%pos%", block.getX() + "," + block.getY() + "," + block.getZ()) + .replace("%crate%", crate.id()))); + } + } +} diff --git a/forge20/src/main/java/com/envyful/crates/config/EnvyCratesLocale.java b/forge20/src/main/java/com/envyful/crates/config/EnvyCratesLocale.java new file mode 100644 index 0000000..2597027 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/config/EnvyCratesLocale.java @@ -0,0 +1,65 @@ +package com.envyful.crates.config; + +import com.envyful.api.config.data.ConfigPath; +import com.envyful.api.config.yaml.AbstractYamlConfig; +import com.google.common.collect.Lists; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +import java.util.List; + +@ConfigSerializable +@ConfigPath("config/EnvyCrates/locale.yml") +public class EnvyCratesLocale extends AbstractYamlConfig { + + private List rootCommand = Lists.newArrayList( + "&e&l(!) &eYou can give crates with /crates givekey " + ); + + private List notOnline = Lists.newArrayList( + "&c&l(!) &cThat player is not online" + ); + + private List crateAlreadyThere = Lists.newArrayList( + "&c&l(!) &cThat block is already a crate block!" + ); + + private List crateAdded = Lists.newArrayList( + "&e&l(!) &eSet %pos% to %crate%" + ); + + private List crateRemoved = Lists.newArrayList( + "&e&l(!) &eRemoved crate at %pos% for %crate%" + ); + + private List cannotSetAir = Lists.newArrayList( + "&c&l(!) &cCannot set air" + ); + + public EnvyCratesLocale() { + super(); + } + + public List getRootCommand() { + return this.rootCommand; + } + + public List getNotOnline() { + return this.notOnline; + } + + public List getCrateAlreadyThere() { + return this.crateAlreadyThere; + } + + public List getCrateAdded() { + return this.crateAdded; + } + + public List getCrateRemoved() { + return this.crateRemoved; + } + + public List getCannotSetAir() { + return this.cannotSetAir; + } +} diff --git a/forge20/src/main/java/com/envyful/crates/listener/CrateBreakListener.java b/forge20/src/main/java/com/envyful/crates/listener/CrateBreakListener.java new file mode 100644 index 0000000..60eb8e6 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/listener/CrateBreakListener.java @@ -0,0 +1,33 @@ +package com.envyful.crates.listener; + +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.crates.EnvyCrates; +import com.envyful.crates.type.CrateFactory; +import com.envyful.crates.type.crate.CrateType; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.event.level.BlockEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +public class CrateBreakListener { + + @SubscribeEvent + public void onPlayerRightClick(BlockEvent.BreakEvent event) { + Player player = event.getPlayer(); + + CrateType crateType = CrateFactory.getCrateType(event.getPlayer().level(), event.getPos()); + + if (crateType == null || !player.isCreative() || !player.isCrouching()) { + return; + } + + event.setCanceled(true); + CrateFactory.remove(event.getPlayer().level(), event.getPos()); + + for (String s : EnvyCrates.getInstance().getLocale().getCrateRemoved()) { + player.sendSystemMessage(UtilChatColour.colour(s + .replace("%pos%", event.getPos().getX() + "," + event.getPos().getY() + "," + event.getPos().getZ()) + .replace("%crate%", crateType.id()) + )); + } + } +} diff --git a/forge20/src/main/java/com/envyful/crates/listener/CrateInteractListener.java b/forge20/src/main/java/com/envyful/crates/listener/CrateInteractListener.java new file mode 100644 index 0000000..8514f7a --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/listener/CrateInteractListener.java @@ -0,0 +1,88 @@ +package com.envyful.crates.listener; + +import com.envyful.crates.EnvyCrates; +import com.envyful.crates.type.CrateFactory; +import com.envyful.crates.type.crate.CrateType; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +public class CrateInteractListener { + + @SubscribeEvent + public void onPlayerRightClickAir(PlayerInteractEvent.RightClickItem event) { + this.handleKeyInteract(event); + } + + @SubscribeEvent + public void onPlayerRightClickAir(PlayerInteractEvent.EntityInteractSpecific event) { + this.handleKeyInteract(event); + } + + @SubscribeEvent + public void onPlayerRightClick(PlayerInteractEvent.RightClickBlock event) { + Player player = event.getEntity(); + ItemStack itemStack = event.getItemStack(); + + CrateType crateType = CrateFactory.getCrateType(event.getEntity().level(), event.getHitVec().getBlockPos()); + + if (crateType == null) { + this.handleKeyInteract(event); + return; + } + + event.setCanceled(true); + event.setUseBlock(Event.Result.DENY); + + if (event.getHand() != InteractionHand.MAIN_HAND) { + return; + } + + if (itemStack.getCount() < 1 || itemStack.getTag() == null || !itemStack.getTag().contains(EnvyCrates.KEY_NBT_TAG) || + !crateType.id().equalsIgnoreCase(itemStack.getTag().get(EnvyCrates.KEY_NBT_TAG).getAsString())) { + crateType.needAKey(EnvyCrates.getInstance().getPlayerManager().getPlayer((ServerPlayer) player)); + return; + } + + if (!player.isCreative()) { + if (event.getItemStack().getCount() <= 1) { + event.getEntity().getInventory().removeItem(event.getItemStack()); + } else { + event.getItemStack().shrink(1); + } + } + + crateType.open(EnvyCrates.getInstance().getPlayerManager().getPlayer((ServerPlayer) player)); + } + + private void handleKeyInteract(PlayerInteractEvent event) { + if (event.getItemStack().getTag() == null || !event.getItemStack().getTag().contains(EnvyCrates.KEY_NBT_TAG)) { + return; + } + + CrateType crateType = CrateFactory.get(event.getItemStack().getTag().get(EnvyCrates.KEY_NBT_TAG).getAsString()); + event.setCanceled(true); + event.setCancellationResult(InteractionResult.FAIL); + crateType.preview(EnvyCrates.getInstance().getPlayerManager().getPlayer((ServerPlayer) event.getEntity()), 1); + } + + + @SubscribeEvent + public void onPlayerLeftClick(PlayerInteractEvent.LeftClickBlock event) { + Player player = event.getEntity(); + + CrateType crateType = CrateFactory.getCrateType(event.getEntity().level(), event.getPos()); + + if (crateType == null || (player.isCreative() && player.isCrouching())) { + return; + } + + event.setCanceled(true); + crateType.preview(EnvyCrates.getInstance().getPlayerManager().getPlayer((ServerPlayer) player), 1); + } +} diff --git a/forge20/src/main/java/com/envyful/crates/type/CrateFactory.java b/forge20/src/main/java/com/envyful/crates/type/CrateFactory.java new file mode 100644 index 0000000..c0014e6 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/CrateFactory.java @@ -0,0 +1,124 @@ +package com.envyful.crates.type; + +import com.envyful.api.forge.world.UtilWorld; +import com.envyful.api.type.Pair; +import com.envyful.api.type.UtilParse; +import com.envyful.crates.type.crate.CrateType; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +import javax.annotation.Nullable; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +public class CrateFactory { + + private static final Map LOADED_CRATES = Maps.newHashMap(); + private static final Map, String> CRATES = Maps.newConcurrentMap(); + + private CrateFactory() { + throw new UnsupportedOperationException("Static factory"); + } + + public static CrateType get(String id) { + return LOADED_CRATES.get(id.toLowerCase(Locale.ROOT)); + } + + public static void clear() { + LOADED_CRATES.clear(); + } + + public static void register(CrateType crateType) { + LOADED_CRATES.put(crateType.id().toLowerCase(Locale.ROOT), crateType); + } + + public static List getAll() { + return Lists.newArrayList(LOADED_CRATES.values()); + } + + public static boolean isCrate(Level level, BlockPos pos) { + return CRATES.containsKey(Pair.of(UtilWorld.getName(level), pos)); + } + + @Nullable + public static CrateType getCrateType(Level level, BlockPos pos) { + return Optional.ofNullable(CRATES.get(Pair.of(UtilWorld.getName(level), pos))).map(CrateFactory::get).orElse(null); + } + + public static void remove(Level level, BlockPos pos) { + CRATES.remove(Pair.of(UtilWorld.getName(level), pos)); + } + + public static void add(Level level, BlockPos pos, CrateType crateType) { + CRATES.put(Pair.of(UtilWorld.getName(level), pos), crateType.id()); + } + + public static void save() { + File cratePositions = Paths.get("config/EnvyCrates/crates.yml").toFile(); + + if (cratePositions.exists()) { + try { + Files.delete(cratePositions.toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + if (!cratePositions.exists()) { + try { + cratePositions.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + try (FileWriter fileWriter = new FileWriter(cratePositions); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { + for (Map.Entry, String> entry : CRATES.entrySet()) { + bufferedWriter.write(entry.getKey().getX() + " " + entry.getKey().getY().getX() + "," + + entry.getKey().getY().getY() + "," + entry.getKey().getY().getZ() + " " + entry.getValue()); + bufferedWriter.newLine(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void load() { + File cratePositions = Paths.get("config/EnvyCrates/crates.yml").toFile(); + + if (!cratePositions.exists()) { + try { + cratePositions.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + try (FileReader fileReader = new FileReader(cratePositions); + BufferedReader bufferedReader = new BufferedReader(fileReader)) { + String line; + + while ((line = bufferedReader.readLine()) != null) { + String[] args = line.split(" "); + String world = args[0]; + String[] split = args[1].split(","); + BlockPos pos = new BlockPos( + UtilParse.parseInteger(split[0]).orElse(0), + UtilParse.parseInteger(split[1]).orElse(0), + UtilParse.parseInteger(split[2]).orElse(0) + ); + CRATES.put(Pair.of(world, pos), args[2]); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/forge20/src/main/java/com/envyful/crates/type/crate/CrateType.java b/forge20/src/main/java/com/envyful/crates/type/crate/CrateType.java new file mode 100644 index 0000000..eb580f5 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/crate/CrateType.java @@ -0,0 +1,27 @@ +package com.envyful.crates.type.crate; + +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.crates.type.reward.RewardType; +import com.google.gson.JsonElement; +import com.mojang.brigadier.exceptions.CommandSyntaxException; + +import java.util.List; + +public interface CrateType { + + String id(); + + void giveKey(ForgeEnvyPlayer player, int amount); + + RewardType generateRandomReward(); + + List getAllRewards(); + + void read(JsonElement element) throws CommandSyntaxException; + + void preview(ForgeEnvyPlayer player, int page); + + void open(ForgeEnvyPlayer player); + + void needAKey(ForgeEnvyPlayer player); +} diff --git a/forge20/src/main/java/com/envyful/crates/type/crate/CrateTypeFactory.java b/forge20/src/main/java/com/envyful/crates/type/crate/CrateTypeFactory.java new file mode 100644 index 0000000..a26c31f --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/crate/CrateTypeFactory.java @@ -0,0 +1,105 @@ +package com.envyful.crates.type.crate; + +import com.envyful.crates.EnvyCrates; +import com.envyful.crates.type.CrateFactory; +import com.envyful.crates.type.crate.impl.SimpleItemCrate; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.brigadier.exceptions.CommandSyntaxException; + +import javax.annotation.Nullable; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Locale; +import java.util.Map; +import java.util.function.Supplier; + +public class CrateTypeFactory { + + private static final Gson GSON = new GsonBuilder().create(); + private static final Map> TYPES = Maps.newHashMap(); + + static { + register("simple", SimpleItemCrate::new); + } + + private CrateTypeFactory() { + throw new UnsupportedOperationException("Static factory"); + } + + public static void register(String id, Supplier crateType) { + TYPES.put(id.toLowerCase(Locale.ROOT), crateType); + } + + @Nullable + public static CrateType getInstance(String id) { + Supplier crateTypeSupplier = TYPES.get(id.toLowerCase(Locale.ROOT)); + + if (crateTypeSupplier == null) { + return null; + } + + return crateTypeSupplier.get(); + } + + public static void reload() { + CrateFactory.clear(); + read(); + } + + public static void read() { + File cratesFolder = Paths.get("config/EnvyCrates/crates").toFile(); + + if (!cratesFolder.exists()) { + cratesFolder.mkdirs(); + } + + loadCrateFromDirectory(cratesFolder); + } + + private static void loadCrateFromDirectory(File directory) { + for (File file : directory.listFiles()) { + if (file.isDirectory()) { + loadCrateFromDirectory(directory); + continue; + } + + JsonElement json = getJson(file); + + if (json == null) { + continue; + } + + JsonObject jsonObject = json.getAsJsonObject(); + String type = jsonObject.getAsJsonPrimitive("type").getAsString(); + CrateType instance = getInstance(type); + + if (instance == null) { + EnvyCrates.getLogger().error("Invalid crate type `{}` in file `{}`.", type, file.getAbsolutePath()); + continue; + } + + try { + instance.read(json); + CrateFactory.register(instance); + } catch (CommandSyntaxException e) { + e.printStackTrace(); + } + } + } + + private static JsonElement getJson(File file) { + try (FileReader fileReader = new FileReader(file)) { + return GSON.fromJson(fileReader, JsonElement.class); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } +} diff --git a/forge20/src/main/java/com/envyful/crates/type/crate/impl/AbstractCrateType.java b/forge20/src/main/java/com/envyful/crates/type/crate/impl/AbstractCrateType.java new file mode 100644 index 0000000..c999378 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/crate/impl/AbstractCrateType.java @@ -0,0 +1,73 @@ +package com.envyful.crates.type.crate.impl; + +import com.envyful.api.config.type.ExtendedConfigItem; +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.api.forge.concurrency.UtilForgeConcurrency; +import com.envyful.api.forge.config.UtilConfigItem; +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.api.json.UtilGson; +import com.envyful.crates.type.crate.CrateType; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.nbt.StringTag; +import net.minecraft.world.item.ItemStack; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public abstract class AbstractCrateType implements CrateType { + + protected String id; + protected String displayName; + protected ExtendedConfigItem itemStack; + protected List givenKeyMessage; + protected List needAKeyMessage; + + protected AbstractCrateType() {} + + @Override + public String id() { + return this.id; + } + + @Override + public void giveKey(ForgeEnvyPlayer player, int amount) { + ItemStack copy = UtilConfigItem.fromConfigItem(this.itemStack); + copy.setCount(amount); + copy.getOrCreateTag().put("ENVY_CRATES", StringTag.valueOf(this.id)); + + UtilForgeConcurrency.runSync(() -> { + player.getParent().addItem(copy); + player.getParent().getInventory().setChanged(); + }); + + if (this.givenKeyMessage != null) { + for (String s : this.givenKeyMessage) { + player.message(UtilChatColour.colour(s + .replace("%display_name%", this.displayName) + .replace("%amount%", String.valueOf(amount))) + ); + } + } + } + + @Override + public void needAKey(ForgeEnvyPlayer player) { + for (String s : this.needAKeyMessage) { + player.message(UtilChatColour.colour(s)); + } + } + + @Override + public void read(JsonElement element) throws CommandSyntaxException { + JsonObject jsonObject = element.getAsJsonObject(); + + this.id = jsonObject.get("id").getAsString(); + this.displayName = jsonObject.get("display_name").getAsString(); + this.itemStack = UtilGson.GSON.fromJson(jsonObject.get("key"), ExtendedConfigItem.class); + this.givenKeyMessage = Stream.of(jsonObject.get("given_key_message").getAsJsonArray()).map(JsonElement::getAsString).collect(Collectors.toList()); + this.needAKeyMessage = Stream.of(jsonObject.get("need_a_key").getAsJsonArray()).map(JsonElement::getAsString).collect(Collectors.toList()); + } +} diff --git a/forge20/src/main/java/com/envyful/crates/type/crate/impl/SimpleItemCrate.java b/forge20/src/main/java/com/envyful/crates/type/crate/impl/SimpleItemCrate.java new file mode 100644 index 0000000..2308eb7 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/crate/impl/SimpleItemCrate.java @@ -0,0 +1,251 @@ +package com.envyful.crates.type.crate.impl; + +import com.envyful.api.config.type.ConfigInterface; +import com.envyful.api.config.type.ConfigItem; +import com.envyful.api.config.type.ExtendedConfigItem; +import com.envyful.api.forge.chat.UtilChatColour; +import com.envyful.api.forge.config.UtilConfigInterface; +import com.envyful.api.forge.config.UtilConfigItem; +import com.envyful.api.forge.items.ItemBuilder; +import com.envyful.api.forge.items.ItemFlag; +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.api.gui.factory.GuiFactory; +import com.envyful.api.gui.pane.Pane; +import com.envyful.api.json.UtilGson; +import com.envyful.api.math.RandomWeightedSet; +import com.envyful.crates.EnvyCrates; +import com.envyful.crates.type.reward.RewardType; +import com.envyful.crates.type.reward.RewardTypeFactory; +import com.google.common.collect.Lists; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +public class SimpleItemCrate extends AbstractCrateType { + + private RandomWeightedSet rewards; + private ConfigInterface previewGuiSettings; + private ConfigInterface displayGuiSettings; + private List displaySlots; + private int spinDuration; + private int finalRewardPosition; + private int previewPages; + private ExtendedConfigItem nextPageItem; + private ExtendedConfigItem previousPageItem; + private String sound; + + public SimpleItemCrate() { + super(); + } + + @Override + public void read(JsonElement element) throws CommandSyntaxException { + super.read(element); + + JsonObject jsonObject = element.getAsJsonObject(); + + this.rewards = new RandomWeightedSet<>(); + + for (JsonElement jsonElement : jsonObject.getAsJsonArray("rewards")) { + JsonObject rewardObject = jsonElement.getAsJsonObject(); + String type = rewardObject.get("type").getAsString(); + RewardType rewardType = RewardTypeFactory.getInstance(type); + + if (rewardType == null) { + EnvyCrates.getLogger().error("Invalid reward type `{}` in `{}`", type, this.id); + continue; + } + + rewardType.read(jsonElement); + this.rewards.add(rewardType, rewardType.getWeight()); + } + + this.previewGuiSettings = UtilGson.GSON.fromJson(jsonObject.get("preview_gui_settings"), ConfigInterface.class); + this.displayGuiSettings = UtilGson.GSON.fromJson(jsonObject.get("display_gui_settings"), ConfigInterface.class); + this.displaySlots = this.parsePositions(jsonObject.get("display_slots").getAsJsonArray()); + this.spinDuration = jsonObject.get("spin_duration").getAsInt(); + this.finalRewardPosition = jsonObject.get("final_reward_position").getAsInt(); + this.previewPages = jsonObject.get("preview_pages").getAsInt(); + this.nextPageItem = UtilGson.GSON.fromJson(jsonObject.get("preview_next_page"), ExtendedConfigItem.class); + this.previousPageItem = UtilGson.GSON.fromJson(jsonObject.get("preview_previous_page"), ExtendedConfigItem.class); + + if (jsonObject.has("sound")) { + this.sound = jsonObject.get("sound").getAsString(); + } + } + + private List parsePositions(JsonArray object) { + List positions = Lists.newArrayList(); + + for (JsonElement slots : object) { + positions.add(slots.getAsInt()); + } + + return positions; + } + + @Override + public RewardType generateRandomReward() { + return this.rewards.getRandom(); + } + + @Override + public List getAllRewards() { + return Lists.newArrayList(this.rewards.keySet()); + } + + @Override + public void preview(ForgeEnvyPlayer player, int page) { + Pane pane = GuiFactory.paneBuilder() + .height(this.previewGuiSettings.getHeight()) + .width(9) + .topLeftX(0) + .topLeftY(0) + .build(); + + UtilConfigInterface.fillBackground(pane, this.previewGuiSettings); + + for (RewardType allReward : this.getAllRewards()) { + allReward.display(pane, page); + } + + if (page != this.previewPages) { + UtilConfigItem.builder() + .clickHandler((envyPlayer, clickType) -> { + if (page == this.previewPages) { + preview(player, 1); + } else { + preview(player, page + 1); + } + }) + .extendedConfigItem(player, pane, this.nextPageItem); + } + + if (page != 1) { + UtilConfigItem.builder() + .clickHandler((envyPlayer, clickType) -> { + if (page == 1) { + preview(player, this.previewPages); + } else { + preview(player, page - 1); + } + }) + .extendedConfigItem(player, pane, this.previousPageItem); + } + + GuiFactory.guiBuilder() + .addPane(pane) + .title(UtilChatColour.colour(this.previewGuiSettings.getTitle())) + .height(this.previewGuiSettings.getHeight()) + .setPlayerManager(EnvyCrates.getInstance().getPlayerManager()) + .build() + .open(EnvyCrates.getInstance().getPlayerManager().getPlayer(player.getParent())); + } + + @Override + public void open(ForgeEnvyPlayer player) { + AtomicInteger timer = new AtomicInteger(0); + RewardType finalReward = this.generateRandomReward(); + AtomicBoolean cleared = new AtomicBoolean(false); + + Pane pane = GuiFactory.paneBuilder() + .height(this.displayGuiSettings.getHeight()) + .width(9) + .topLeftX(0) + .topLeftY(0) + .tickHandler(GuiFactory.tickBuilder() + .async() + .initialDelay(10) + .repeatDelay(10) + .handler(pane1 -> { + timer.incrementAndGet(); + + if (timer.get() >= (2 * this.spinDuration)) { + finalReward.playSound(player.getParent()); + + if (!cleared.get()) { + cleared.set(true); + int counter = 0; + for (ConfigItem fillerItem : this.displayGuiSettings.getFillerItems()) { + if (!fillerItem.isEnabled() || counter == this.finalRewardPosition) { + ++counter; + continue; + } + + pane1.set(counter % 9, counter / 9, GuiFactory.displayable(UtilConfigItem.fromConfigItem(fillerItem))); + ++counter; + } + } + + pane1.set(this.finalRewardPosition % 9, this.finalRewardPosition / 9, GuiFactory.displayable(new ItemBuilder(finalReward.getDisplayItem()) + .enchant(Enchantments.UNBREAKING, 1) + .itemFlag(ItemFlag.HIDE_ENCHANTS) + .build())); + return; + } + + if (this.sound != null) { + player.getParent().connection.send(new ClientboundSoundPacket(ForgeRegistries.SOUND_EVENTS.getDelegateOrThrow(ResourceLocation.tryParse(this.sound)), SoundSource.MUSIC, + player.getParent().getX(), player.getParent().getY(), player.getParent().getZ(), 1.0f, 1.0f, 0L)); + } + + List spinSlots = this.displaySlots; + + for (int i = spinSlots.size() - 1; i > 0; i--) { + int slot = spinSlots.get(i); + int lastSlot = spinSlots.get(i - 1); + + pane1.set(slot % 9, slot / 9, pane1.get(lastSlot % 9, lastSlot / 9)); + } + + int slot = spinSlots.get(0); + + int subtraction = this.displaySlots.indexOf(this.finalRewardPosition); + + if (subtraction == -1) { + subtraction = 5; + } else { + subtraction = this.displaySlots.size() - subtraction; + } + + if (timer.get() == ((2 * this.spinDuration) - subtraction)) { + pane1.set(slot % 9, slot / 9, GuiFactory.displayable(new ItemBuilder(finalReward.getDisplayItem()) + .enchant(Enchantments.UNBREAKING, 1) + .itemFlag(ItemFlag.HIDE_ENCHANTS) + .build())); + } else { + pane1.set(slot % 9, slot / 9, GuiFactory.displayable(this.generateRandomReward().getDisplayItem())); + } + }) + .build()) + .build(); + + UtilConfigInterface.fillBackground(pane, this.displayGuiSettings); + + for (Integer spinSlot : this.displaySlots) { + pane.set(spinSlot % 9, spinSlot / 9, GuiFactory.displayable(this.generateRandomReward().getDisplayItem())); + } + + GuiFactory.guiBuilder() + .addPane(pane) + .title(UtilChatColour.colour(this.displayGuiSettings.getTitle())) + .height(this.displayGuiSettings.getHeight()) + .setPlayerManager(EnvyCrates.getInstance().getPlayerManager()) + .closeConsumer(GuiFactory.closeConsumerBuilder() + .async() + .handler(envyPlayer -> finalReward.give(player)) + .build()) + .build() + .open(EnvyCrates.getInstance().getPlayerManager().getPlayer(player.getParent())); + } +} diff --git a/forge20/src/main/java/com/envyful/crates/type/reward/RewardType.java b/forge20/src/main/java/com/envyful/crates/type/reward/RewardType.java new file mode 100644 index 0000000..48a462c --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/reward/RewardType.java @@ -0,0 +1,26 @@ +package com.envyful.crates.type.reward; + +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.api.gui.pane.Pane; +import com.google.gson.JsonElement; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; + +public interface RewardType { + + String id(); + + double getWeight(); + + void give(ForgeEnvyPlayer player); + + void display(Pane pane, int page); + + ItemStack getDisplayItem(); + + void read(JsonElement element) throws CommandSyntaxException; + + void playSound(Player player); + +} diff --git a/forge20/src/main/java/com/envyful/crates/type/reward/RewardTypeFactory.java b/forge20/src/main/java/com/envyful/crates/type/reward/RewardTypeFactory.java new file mode 100644 index 0000000..3ab893d --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/reward/RewardTypeFactory.java @@ -0,0 +1,38 @@ +package com.envyful.crates.type.reward; + +import com.envyful.crates.type.reward.impl.SimpleCommandRewardType; +import com.google.common.collect.Maps; + +import javax.annotation.Nullable; +import java.util.Locale; +import java.util.Map; +import java.util.function.Supplier; + +public class RewardTypeFactory { + + private static final Map> REGISTERED_REWARDS = Maps.newHashMap(); + + static { + register("simple_commands", SimpleCommandRewardType::new); + } + + private RewardTypeFactory() { + throw new UnsupportedOperationException("Static Factory"); + } + + public static void register(String id, Supplier supplier) { + REGISTERED_REWARDS.put(id.toLowerCase(Locale.ROOT), supplier); + } + + @Nullable + public static RewardType getInstance(String id) { + Supplier rewardTypeSupplier = REGISTERED_REWARDS.get(id.toLowerCase(Locale.ROOT)); + + if (rewardTypeSupplier == null) { + return null; + } + + return rewardTypeSupplier.get(); + } + +} diff --git a/forge20/src/main/java/com/envyful/crates/type/reward/impl/AbstractRewardType.java b/forge20/src/main/java/com/envyful/crates/type/reward/impl/AbstractRewardType.java new file mode 100644 index 0000000..b6b40d3 --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/reward/impl/AbstractRewardType.java @@ -0,0 +1,49 @@ +package com.envyful.crates.type.reward.impl; + +import com.envyful.api.forge.config.ConfigSound; +import com.envyful.api.json.UtilGson; +import com.envyful.crates.type.reward.RewardType; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; + +public abstract class AbstractRewardType implements RewardType { + + protected String id; + protected double weight; + private ConfigSound winSound; + + protected AbstractRewardType() { + } + + @Override + public String id() { + return this.id; + } + + @Override + public double getWeight() { + return this.weight; + } + + @Override + public void read(JsonElement element) throws CommandSyntaxException { + JsonObject object = element.getAsJsonObject(); + + this.id = object.get("id").getAsString(); + this.weight = object.get("weight").getAsDouble(); + + if (object.has("win_sound")) { + this.winSound = UtilGson.GSON.fromJson(object.get("win_sound"), ConfigSound.class); + } + } + + @Override + public void playSound(Player player) { + if (this.winSound != null) { + this.winSound.playSound((ServerPlayer) player); + } + } +} diff --git a/forge20/src/main/java/com/envyful/crates/type/reward/impl/SimpleCommandRewardType.java b/forge20/src/main/java/com/envyful/crates/type/reward/impl/SimpleCommandRewardType.java new file mode 100644 index 0000000..d1fb8bd --- /dev/null +++ b/forge20/src/main/java/com/envyful/crates/type/reward/impl/SimpleCommandRewardType.java @@ -0,0 +1,67 @@ +package com.envyful.crates.type.reward.impl; + +import com.envyful.api.config.type.ExtendedConfigItem; +import com.envyful.api.forge.config.UtilConfigItem; +import com.envyful.api.forge.player.ForgeEnvyPlayer; +import com.envyful.api.forge.server.UtilForgeServer; +import com.envyful.api.gui.factory.GuiFactory; +import com.envyful.api.gui.pane.Pane; +import com.envyful.api.json.UtilGson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.world.item.ItemStack; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +public class SimpleCommandRewardType extends AbstractRewardType { + + private List commands; + private ExtendedConfigItem display; + private int displayX; + private int displayY; + private int page; + + public SimpleCommandRewardType() { + super(); + } + + @Override + public void give(ForgeEnvyPlayer player) { + for (String command : this.commands) { + UtilForgeServer.executeCommand(command.replace("%player%", player.getName())); + } + } + + @Override + public void read(JsonElement element) throws CommandSyntaxException { + super.read(element); + + JsonObject object = element.getAsJsonObject(); + + this.commands = StreamSupport.stream(object.get("commands").getAsJsonArray().spliterator(), false).map(JsonElement::getAsString).collect(Collectors.toList()); + this.display = UtilGson.GSON.fromJson(object.get("display"), ExtendedConfigItem.class); + + JsonObject displayData = object.getAsJsonObject("display_data"); + + this.displayX = displayData.get("x").getAsInt(); + this.displayY = displayData.get("y").getAsInt(); + this.page = displayData.get("page").getAsInt(); + } + + @Override + public void display(Pane pane, int page) { + if (this.page != page) { + return; + } + + pane.set(this.displayX, this.displayY, GuiFactory.displayable(UtilConfigItem.fromConfigItem(this.display))); + } + + @Override + public ItemStack getDisplayItem() { + return UtilConfigItem.fromConfigItem(this.display); + } +} diff --git a/forge20/src/main/resources/META-INF/mods.toml b/forge20/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..be59ac4 --- /dev/null +++ b/forge20/src/main/resources/META-INF/mods.toml @@ -0,0 +1,29 @@ +modLoader="javafml" +loaderVersion="[36,)" +license="MIT" +issueTrackerURL="https://github.com/EnvyWare/EnvyCrates/issues" + +[[mods]] +modId="envycrates" +version="1.1.2" +displayName="EnvyCrates" +displayURL="https://github.com/EnvyWare" +credits="https://github.com/EnvyWare" +authors="https://github.com/EnvyWare" +description=''' +Crates +''' + +[[dependencies.envycrates]] +modId="forge" +mandatory=true +versionRange="[47.1.28,)" +ordering="NONE" +side="BOTH" + +[[dependencies.envycrates]] +modId="minecraft" +mandatory=true +versionRange="[1.20.1,1.21)" +ordering="NONE" +side="BOTH" diff --git a/forge20/src/main/resources/pack.mcmeta b/forge20/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..7003830 --- /dev/null +++ b/forge20/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "EnvyCrates", + "pack_format": 15 + } +} diff --git a/settings.gradle b/settings.gradle index 973b7c7..2248319 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,4 +16,5 @@ plugins { rootProject.name = 'EnvyCrates' include 'forge16' +include 'forge20' include 'pixelmon16' \ No newline at end of file