diff --git a/build.gradle b/build.gradle index 149fbc3..abdbe45 100644 --- a/build.gradle +++ b/build.gradle @@ -98,6 +98,7 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "com.github.UselessSolutions:serverlibe:${project.serverlibe_version}" + modImplementation("turniplabs:halplibe:${project.halplibe_version}") implementation "org.slf4j:slf4j-api:1.8.0-beta4" implementation "org.apache.logging.log4j:log4j-slf4j18-impl:2.16.0" diff --git a/gradle.properties b/gradle.properties index 5e6514e..f8c2241 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,10 @@ loader_version=0.15.6-bta.7 # ServerLibe serverlibe_version=beta.2.7-7.3_03 +# Halplibe +halplibe_version=5.2.4 + # Mod -mod_version=1.0.1-7.3_03 +mod_version=1.0.3-7.3_03 mod_group=MelonModding mod_name=MelonUtilities diff --git a/src/main/java/MelonUtilities/MelonUtilities.java b/src/main/java/MelonUtilities/MelonUtilities.java index c1d6cda..787311e 100644 --- a/src/main/java/MelonUtilities/MelonUtilities.java +++ b/src/main/java/MelonUtilities/MelonUtilities.java @@ -1,25 +1,35 @@ package MelonUtilities; -import MelonUtilities.utility.discord.DiscordChatRelay; -import MelonUtilities.utility.discord.DiscordClient; import MelonUtilities.command.commands.*; import MelonUtilities.config.Data; import MelonUtilities.config.datatypes.data.Config; import MelonUtilities.listeners.ChatInputListener; import MelonUtilities.utility.MUtil; +import MelonUtilities.utility.discord.DiscordChatRelay; +import MelonUtilities.utility.discord.DiscordClient; +import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.core.item.ItemStack; +import net.minecraft.core.item.Items; import net.minecraft.core.net.command.CommandManager; +import net.minecraft.core.net.command.TextFormatting; +import net.minecraft.core.util.helper.DyeColor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.useless.serverlibe.ServerLibe; +import turniplabs.halplibe.helper.RecipeBuilder; +import turniplabs.halplibe.util.GameStartEntrypoint; +import turniplabs.halplibe.util.RecipeEntrypoint; -public class MelonUtilities implements ModInitializer { +public class MelonUtilities implements ModInitializer, RecipeEntrypoint, GameStartEntrypoint { + public static final boolean isServer = FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER; public static final String MOD_ID = "melonutilities"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); - public static final int mainConfigVersion = 0; - //public static final int crewConfigVersion = 0; + + public static final int mainConfigVersion = 1; public static final int kitConfigVersion = 0; public static final int roleConfigVersion = 0; public static final int userConfigVersion = 0; @@ -30,7 +40,7 @@ public static void reloadAll() { if(Data.MainConfig.config.enableRoles) Data.Roles.reload(); } - public static void registerCommands(){ + public static void registerServerCommands(){ if(Data.MainConfig.config.enableContainerLocking) CommandManager.registerCommand(new CommandLock()); if(Data.MainConfig.config.enableRoles) CommandManager.registerCommand(new CommandRole()); if(Data.MainConfig.config.enableRollback) CommandManager.registerCommand(new CommandRollback()); @@ -44,6 +54,9 @@ public static void registerCommands(){ CommandManager.registerCommand(new CommandMelonUtilities()); } + public static void registerClientCommands(){ + } + public void loadData(){ LOGGER.info("Loading Utility Data..."); reloadAll(); @@ -71,15 +84,17 @@ public void onInitialize() { } public static void afterServerStart(){ - Data.Users.reload(); - MUtil.timeOnInit = System.currentTimeMillis(); - - Config config = Data.MainConfig.config; - config.lastSnapshot = correctTimeIfZERO(config.lastSnapshot); - config.lastBackup = correctTimeIfZERO(config.lastBackup); - config.lastSnapshotPrune = correctTimeIfZERO(config.lastSnapshotPrune); - config.lastBackupPrune = correctTimeIfZERO(config.lastBackupPrune); - Data.MainConfig.save(); + if(isServer){ + Data.Users.reload(); + MUtil.timeOnInit = System.currentTimeMillis(); + + Config config = Data.MainConfig.config; + config.lastSnapshot = correctTimeIfZERO(config.lastSnapshot); + config.lastBackup = correctTimeIfZERO(config.lastBackup); + config.lastSnapshotPrune = correctTimeIfZERO(config.lastSnapshotPrune); + config.lastBackupPrune = correctTimeIfZERO(config.lastBackupPrune); + Data.MainConfig.save(); + } } public static double correctTimeIfZERO(double d){ @@ -92,4 +107,37 @@ public static double correctTimeIfZERO(double d){ public static void info(String s) { LOGGER.info(s); } + + @Override + public void beforeGameStart() { + + } + + @Override + public void afterGameStart() { + + } + + @Override + public void onRecipesReady() { + if(Data.MainConfig.config.enableMagnets){ + ItemStack magnet = new ItemStack(Items.AMMO_FIREBALL, 1, 1); + magnet.setCustomName(TextFormatting.RESET + "Magnet"); + + RecipeBuilder.Shaped("minecraft") + .setShape( + "R L", + "S S", + "SSS") + .addInput('R', Items.DUST_REDSTONE) + .addInput('L', Items.DYE, DyeColor.BLUE.itemMeta) + .addInput('S', Items.INGOT_STEEL) + .create("magnet", magnet); + } + } + + @Override + public void initNamespaces() { + + } } diff --git a/src/main/java/MelonUtilities/command/commandlogic/CommandLogicElevator.java b/src/main/java/MelonUtilities/command/commandlogic/CommandLogicElevator.java index 206ccc5..2a24acb 100644 --- a/src/main/java/MelonUtilities/command/commandlogic/CommandLogicElevator.java +++ b/src/main/java/MelonUtilities/command/commandlogic/CommandLogicElevator.java @@ -1,29 +1,50 @@ package MelonUtilities.command.commandlogic; +import MelonUtilities.MelonUtilities; import MelonUtilities.config.Data; +import MelonUtilities.utility.feedback.FeedbackHandlerClient; import MelonUtilities.utility.feedback.FeedbackHandlerServer; import MelonUtilities.utility.feedback.FeedbackType; import com.mojang.brigadier.Command; +import net.minecraft.core.entity.player.Player; import net.minecraft.server.entity.player.PlayerServer; public class CommandLogicElevator { - public static int elevatorAllowobstructions(PlayerServer sender){ - if(Data.MainConfig.config.allowObstructions){ - Data.MainConfig.config.allowObstructions = false; - Data.MainConfig.save(); - FeedbackHandlerServer.sendFeedback(FeedbackType.destructive, sender, "Allow Obstructions Disabled"); + public static int elevatorAllowobstructions(Player sender){ + if(MelonUtilities.isServer){ + if(Data.MainConfig.config.allowObstructions){ + Data.MainConfig.config.allowObstructions = false; + Data.MainConfig.save(); + FeedbackHandlerServer.sendFeedback(FeedbackType.destructive, (PlayerServer) sender, "Allow Obstructions Disabled"); + } else { + Data.MainConfig.config.allowObstructions = true; + Data.MainConfig.save(); + FeedbackHandlerServer.sendFeedback(FeedbackType.success, (PlayerServer) sender, "Allow Obstructions Enabled!"); + } } else { - Data.MainConfig.config.allowObstructions = true; - Data.MainConfig.save(); - FeedbackHandlerServer.sendFeedback(FeedbackType.success, sender, "Allow Obstructions Enabled!"); + if(Data.MainConfig.config.allowObstructions){ + Data.MainConfig.config.allowObstructions = false; + Data.MainConfig.save(); + FeedbackHandlerClient.sendFeedback(FeedbackType.destructive, sender, "Allow Obstructions Disabled"); + } else { + Data.MainConfig.config.allowObstructions = true; + Data.MainConfig.save(); + FeedbackHandlerClient.sendFeedback(FeedbackType.success, sender, "Allow Obstructions Enabled!"); + } } return Command.SINGLE_SUCCESS; } - public static int elevatorCooldown(PlayerServer sender, int cooldownValue) { - Data.MainConfig.config.elevatorCooldown = cooldownValue; - Data.MainConfig.save(); - FeedbackHandlerServer.sendFeedback(FeedbackType.success, sender, "Elevator Cooldown Set to %" + cooldownValue); + public static int elevatorCooldown(Player sender, int cooldownValue) { + if(MelonUtilities.isServer){ + Data.MainConfig.config.elevatorCooldown = cooldownValue; + Data.MainConfig.save(); + FeedbackHandlerServer.sendFeedback(FeedbackType.success, (PlayerServer) sender, "Elevator Cooldown Set to %" + cooldownValue); + } else { + Data.MainConfig.config.elevatorCooldown = cooldownValue; + Data.MainConfig.save(); + FeedbackHandlerClient.sendFeedback(FeedbackType.success, sender, "Elevator Cooldown Set to %" + cooldownValue); + } return Command.SINGLE_SUCCESS; } } diff --git a/src/main/java/MelonUtilities/command/commandlogic/CommandLogicWarp.java b/src/main/java/MelonUtilities/command/commandlogic/CommandLogicWarp.java index 648dc55..0305aa1 100644 --- a/src/main/java/MelonUtilities/command/commandlogic/CommandLogicWarp.java +++ b/src/main/java/MelonUtilities/command/commandlogic/CommandLogicWarp.java @@ -33,14 +33,14 @@ public static int warpList(PlayerServer sender){ public static int warpDelete(PlayerServer sender, Warp targetWarp){ Data.MainConfig.config.warpData.remove(targetWarp); - Data.Users.save(sender.uuid); + Data.MainConfig.save(); FeedbackHandlerServer.sendFeedback(FeedbackType.destructive, sender, "Deleted Warp %s", new FeedbackArg(targetWarp)); return Command.SINGLE_SUCCESS; } public static int warpCreate(PlayerServer sender, String name){ Data.MainConfig.config.warpData.add(new Warp(name, sender.x, sender.y, sender.z, sender.dimension)); - Data.Users.save(sender.uuid); + Data.MainConfig.save(); FeedbackHandlerServer.sendFeedback(FeedbackType.success, sender, "Created Warp %s", new FeedbackArg(name)); return Command.SINGLE_SUCCESS; } @@ -49,7 +49,7 @@ public static int warpRename(PlayerServer sender, Warp targetWarp, String name){ Data.MainConfig.config.warpData.remove(targetWarp); targetWarp.name = name; Data.MainConfig.config.warpData.add(targetWarp); - Data.Users.save(sender.uuid); + Data.MainConfig.save(); FeedbackHandlerServer.sendFeedback(FeedbackType.success, sender, "Renamed Warp %s to %s", new FeedbackArg(targetWarp), new FeedbackArg(name)); return Command.SINGLE_SUCCESS; } diff --git a/src/main/java/MelonUtilities/config/datatypes/data/Config.java b/src/main/java/MelonUtilities/config/datatypes/data/Config.java index 4559ac5..160eda1 100644 --- a/src/main/java/MelonUtilities/config/datatypes/data/Config.java +++ b/src/main/java/MelonUtilities/config/datatypes/data/Config.java @@ -23,6 +23,7 @@ public class Config { public boolean enableSQLPlayerLogging = true; public boolean enableTXTPlayerLogging = true; public boolean enableDiscordIntegration = false; + public boolean enableMagnets = true; public String defaultRole = null; public String displayMode = "multi"; diff --git a/src/main/java/MelonUtilities/config/datatypes/jsonadapters/ConfigJsonAdapter.java b/src/main/java/MelonUtilities/config/datatypes/jsonadapters/ConfigJsonAdapter.java index 049cbf2..72ccf6a 100644 --- a/src/main/java/MelonUtilities/config/datatypes/jsonadapters/ConfigJsonAdapter.java +++ b/src/main/java/MelonUtilities/config/datatypes/jsonadapters/ConfigJsonAdapter.java @@ -47,6 +47,7 @@ public Config deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon config.enableSQLPlayerLogging = mainConfig.get("enableSQLPlayerLogging").getAsBoolean(); config.enableTXTPlayerLogging = mainConfig.get("enableTXTPlayerLogging").getAsBoolean(); config.enableDiscordIntegration = mainConfig.get("enableDiscordIntegration").getAsBoolean(); + config.enableMagnets = mainConfig.get("enableMagnets").getAsBoolean(); //Role Options if(roleConfig.has("defaultRole")){ @@ -85,9 +86,11 @@ public Config deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon config.serverName = discordIntegrationConfig.get("serverName").getAsString(); //Warp Options - JsonArray warps = warpConfig.getAsJsonArray("warps"); - for(JsonElement element : warps){ - config.warpData.add(context.deserialize(element, Warp.class)); + if(warpConfig != null){ + JsonArray warps = warpConfig.getAsJsonArray("warps"); + for(JsonElement element : warps){ + config.warpData.add(context.deserialize(element, Warp.class)); + } } return config; @@ -121,6 +124,7 @@ public JsonElement serialize(Config src, Type typeOfSrc, JsonSerializationContex mainConfig.addProperty("enableSQLPlayerLogging", src.enableSQLPlayerLogging); mainConfig.addProperty("enableTXTPlayerLogging", src.enableTXTPlayerLogging); mainConfig.addProperty("enableDiscordIntegration", src.enableDiscordIntegration); + mainConfig.addProperty("enableMagnets", src.enableMagnets); obj.add("Main Config", mainConfig); roleConfig.addProperty("defaultRole", src.defaultRole); diff --git a/src/main/java/MelonUtilities/config/datatypes/legacydeserializers/ConfigLDs.java b/src/main/java/MelonUtilities/config/datatypes/legacydeserializers/ConfigLDs.java index 73ea9f8..3701509 100644 --- a/src/main/java/MelonUtilities/config/datatypes/legacydeserializers/ConfigLDs.java +++ b/src/main/java/MelonUtilities/config/datatypes/legacydeserializers/ConfigLDs.java @@ -77,9 +77,89 @@ public static Config legacyDeserialize0(JsonDeserializationContext context, Json config.serverName = discordIntegrationConfig.get("serverName").getAsString(); //Warp Options - JsonArray warps = warpConfig.getAsJsonArray("warps"); - for(JsonElement element : warps){ - config.warpData.add(context.deserialize(element, Warp.class)); + if(warpConfig != null){ + JsonArray warps = warpConfig.getAsJsonArray("warps"); + for(JsonElement element : warps){ + config.warpData.add(context.deserialize(element, Warp.class)); + } + } + + return config; + } + public static Config legacyDeserialize1(JsonDeserializationContext context, JsonObject obj){ + //New Config + Config config = new Config(); + config.configVersion = MelonUtilities.mainConfigVersion; + + //Extra Categories + JsonObject mainConfig = obj.getAsJsonObject("Main Config"); + JsonObject roleConfig = obj.getAsJsonObject("Role Config"); + JsonObject rollbackConfig = obj.getAsJsonObject("Rollback Config"); + JsonObject elevatorConfig = obj.getAsJsonObject("Elevator Config"); + JsonObject sqlLogConfig = obj.getAsJsonObject("SQL Log Config"); + JsonObject warpConfig = obj.getAsJsonObject("Warp Config"); + JsonObject discordIntegrationConfig = obj.getAsJsonObject("Discord Integration Config"); + + + //Main Options + config.enableContainerLocking = mainConfig.get("enableContainerLocking").getAsBoolean(); + config.enableRoles = mainConfig.get("enableRoles").getAsBoolean(); + config.enableRollback = mainConfig.get("enableRollback").getAsBoolean(); + config.enableTPA = mainConfig.get("enableTPA").getAsBoolean(); + config.enableHomes = mainConfig.get("enableHomes").getAsBoolean(); + config.enableWarps = mainConfig.get("enableWarps").getAsBoolean(); + config.enableElevators = mainConfig.get("enableElevators").getAsBoolean(); + config.enableKits = mainConfig.get("enableKits").getAsBoolean(); + config.enableRules = mainConfig.get("enableRules").getAsBoolean(); + config.enableSmite = mainConfig.get("enableSmite").getAsBoolean(); + config.enableCrews = mainConfig.get("enableCrews").getAsBoolean(); + config.enableSQLPlayerLogging = mainConfig.get("enableSQLPlayerLogging").getAsBoolean(); + config.enableTXTPlayerLogging = mainConfig.get("enableTXTPlayerLogging").getAsBoolean(); + config.enableDiscordIntegration = mainConfig.get("enableDiscordIntegration").getAsBoolean(); + config.enableMagnets = mainConfig.get("enableMagnets").getAsBoolean(); + + //Role Options + if(roleConfig.has("defaultRole")){ + config.defaultRole = roleConfig.get("defaultRole").getAsString(); + } + config.displayMode = roleConfig.get("displayMode").getAsString(); + + //Rollback Options + config.snapshotsEnabled = rollbackConfig.get("snapshotsEnabled").getAsBoolean(); + config.backupsEnabled = rollbackConfig.get("backupsEnabled").getAsBoolean(); + config.snapshotsImmune = rollbackConfig.get("snapshotsImmune").getAsInt(); + config.backupsImmune = rollbackConfig.get("backupsImmune").getAsInt(); + config.snapshotsLimit = rollbackConfig.get("snapshotsLimit").getAsInt(); + config.backupsLimit = rollbackConfig.get("backupsLimit").getAsInt(); + config.sizeLimit = rollbackConfig.get("sizeLimit").getAsString(); + config.timeBetweenSnapshots = rollbackConfig.get("timeBetweenSnapshots").getAsInt(); + config.timeBetweenBackups = rollbackConfig.get("timeBetweenBackups").getAsInt(); + config.timeBetweenBackupPruning = rollbackConfig.get("timeBetweenBackupPruning").getAsInt(); + config.timeBetweenSnapshotPruning = rollbackConfig.get("timeBetweenSnapshotPruning").getAsInt(); + config.lastSnapshot = rollbackConfig.get("lastSnapshot").getAsDouble(); + config.lastBackup = rollbackConfig.get("lastBackup").getAsDouble(); + config.lastBackupPrune = rollbackConfig.get("lastBackupPrune").getAsDouble(); + config.lastSnapshotPrune = rollbackConfig.get("lastSnapshotPrune").getAsDouble(); + + //Elevator Options + config.allowObstructions = elevatorConfig.get("allowObstructions").getAsBoolean(); + config.elevatorCooldown = elevatorConfig.get("elevatorCooldown").getAsInt(); + + //SQL Options + config.JDBCConnectionUrl = sqlLogConfig.get("JDBCConnectionUrl").getAsString(); + + //Discord Options + config.token = discordIntegrationConfig.get("token").getAsString(); + config.channelID = discordIntegrationConfig.get("channelID").getAsString(); + config.serverPFPURL = discordIntegrationConfig.get("serverPFPURL").getAsString(); + config.serverName = discordIntegrationConfig.get("serverName").getAsString(); + + //Warp Options + if(warpConfig != null){ + JsonArray warps = warpConfig.getAsJsonArray("warps"); + for(JsonElement element : warps){ + config.warpData.add(context.deserialize(element, Warp.class)); + } } return config; diff --git a/src/main/java/MelonUtilities/interfaces/PlayerMagnetInterface.java b/src/main/java/MelonUtilities/interfaces/PlayerMagnetInterface.java new file mode 100644 index 0000000..2208aee --- /dev/null +++ b/src/main/java/MelonUtilities/interfaces/PlayerMagnetInterface.java @@ -0,0 +1,5 @@ +package MelonUtilities.interfaces; + +public interface PlayerMagnetInterface { + boolean hasMagnet(); +} diff --git a/src/main/java/MelonUtilities/mixins/CommandManagerMixin.java b/src/main/java/MelonUtilities/mixins/CommandManagerMixin.java index 3db1145..18fdf5f 100644 --- a/src/main/java/MelonUtilities/mixins/CommandManagerMixin.java +++ b/src/main/java/MelonUtilities/mixins/CommandManagerMixin.java @@ -14,7 +14,9 @@ public class CommandManagerMixin { @Inject(at = @At("HEAD"), method = "init") public void initInject(CallbackInfo ci) { if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER){ - MelonUtilities.registerCommands(); + MelonUtilities.registerServerCommands(); + } else { + MelonUtilities.registerClientCommands(); } } } diff --git a/src/main/java/MelonUtilities/mixins/EntityItemMixin.java b/src/main/java/MelonUtilities/mixins/EntityItemMixin.java new file mode 100644 index 0000000..41eebcf --- /dev/null +++ b/src/main/java/MelonUtilities/mixins/EntityItemMixin.java @@ -0,0 +1,45 @@ +package MelonUtilities.mixins; + +import MelonUtilities.config.Data; +import MelonUtilities.utility.MUtil; +import net.minecraft.core.entity.Entity; +import net.minecraft.core.entity.EntityItem; +import net.minecraft.core.entity.player.Player; +import net.minecraft.core.util.phys.Vec3; +import net.minecraft.core.world.World; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = EntityItem.class, remap = false) +public abstract class EntityItemMixin extends Entity { + + //ignore, constructor is useless + public EntityItemMixin(@Nullable World world) { + super(world); + } + + @Inject(method = "tick", at = @At("TAIL")) + void tick(CallbackInfo ci){ + if(Data.MainConfig.config.enableMagnets){ + if((Entity) this instanceof EntityItem){ + Player closestPlayer = MUtil.closestPlayerWithMagnetToItem(this.world, this); + if(closestPlayer != null && closestPlayer.distanceTo(this) < 15){ + //magnet stuff + Vec3 item = Vec3.getTempVec3(this.x, this.y, this.z); + Vec3 target = Vec3.getTempVec3(closestPlayer.x, closestPlayer.y + closestPlayer.getHeadHeight() - 1.05, closestPlayer.z); + double strength = 0.06; + + Vec3 normal = item.vectorTo(target).normalize().scale(strength).add(0,0.032,0); + this.xd += normal.x; + this.yd += normal.y; + this.zd += normal.z; + } + } + } + } + + +} diff --git a/src/main/java/MelonUtilities/mixins/MinecraftServerMixin.java b/src/main/java/MelonUtilities/mixins/MinecraftServerMixin.java index aca1976..a796bf3 100644 --- a/src/main/java/MelonUtilities/mixins/MinecraftServerMixin.java +++ b/src/main/java/MelonUtilities/mixins/MinecraftServerMixin.java @@ -22,5 +22,4 @@ private void doTick(CallbackInfo ci) { private void startServerInject(CallbackInfoReturnable cir){ MelonUtilities.afterServerStart(); } - } diff --git a/src/main/java/MelonUtilities/mixins/NetEntryItemMixin.java b/src/main/java/MelonUtilities/mixins/NetEntryItemMixin.java new file mode 100644 index 0000000..cf57689 --- /dev/null +++ b/src/main/java/MelonUtilities/mixins/NetEntryItemMixin.java @@ -0,0 +1,19 @@ +package MelonUtilities.mixins; + +import MelonUtilities.config.Data; +import net.minecraft.core.net.entity.entries.NetEntryItem; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = NetEntryItem.class, remap = false) +public class NetEntryItemMixin { + @Inject(method = "getPacketDelay", at = @At("HEAD"), cancellable = true) + void getPacketDelay(CallbackInfoReturnable cir){ + if (Data.MainConfig.config.enableMagnets) { + cir.setReturnValue(6); + return; + } + } +} diff --git a/src/main/java/MelonUtilities/mixins/PacketHandlerServerMixin.java b/src/main/java/MelonUtilities/mixins/PacketHandlerServerMixin.java index 423cf24..4eac1ec 100644 --- a/src/main/java/MelonUtilities/mixins/PacketHandlerServerMixin.java +++ b/src/main/java/MelonUtilities/mixins/PacketHandlerServerMixin.java @@ -221,7 +221,6 @@ private void handleBlockDigInject(PacketPlayerAction packet, CallbackInfo ci){ && lockable.getLockOwner().equals(player.uuid)) { FeedbackHandlerServer.sendFeedback(FeedbackType.error, player, "Failed to Lock Container! (Already Locked)"); - FeedbackHandlerServer.sendFeedback(FeedbackType.error, player, packet.toString()); ci.cancel(); return; } diff --git a/src/main/java/MelonUtilities/mixins/PlayerMixinMagnet.java b/src/main/java/MelonUtilities/mixins/PlayerMixinMagnet.java new file mode 100644 index 0000000..a8a96db --- /dev/null +++ b/src/main/java/MelonUtilities/mixins/PlayerMixinMagnet.java @@ -0,0 +1,51 @@ +package MelonUtilities.mixins; + +import MelonUtilities.config.Data; +import MelonUtilities.interfaces.PlayerMagnetInterface; +import net.minecraft.core.entity.player.Player; +import net.minecraft.core.item.IArmorItem; +import net.minecraft.core.item.ItemStack; +import net.minecraft.core.item.Items; +import net.minecraft.core.player.inventory.container.ContainerInventory; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = Player.class, remap = false) +public abstract class PlayerMixinMagnet implements PlayerMagnetInterface { + + @Shadow + public ContainerInventory inventory; + + @Shadow + public abstract ItemStack getHeldItem(); + + @Unique + boolean hasMagnet = false; + + @Inject(method = "tick", at = @At("TAIL")) + void tick(CallbackInfo ci){ + if (Data.MainConfig.config.enableMagnets) { + ItemStack headItem = this.inventory.armorInventory[IArmorItem.PIECE_HEAD]; + ItemStack heldItem = this.getHeldItem(); + + hasMagnet = + //item on head check + headItem != null && + headItem.getItem().equals(Items.AMMO_FIREBALL) && + headItem.getMetadata() == 1 || + //held item check + heldItem != null && + heldItem.getItem().equals(Items.AMMO_FIREBALL) && + heldItem.getMetadata() == 1; + } + } + + @Override + public boolean hasMagnet() { + return hasMagnet; + } +} diff --git a/src/main/java/MelonUtilities/mixins/tile_entities/dispenser/TileEntityDispenserMixin.java b/src/main/java/MelonUtilities/mixins/tile_entities/dispenser/TileEntityDispenserMixin.java index 63976ee..afc2510 100644 --- a/src/main/java/MelonUtilities/mixins/tile_entities/dispenser/TileEntityDispenserMixin.java +++ b/src/main/java/MelonUtilities/mixins/tile_entities/dispenser/TileEntityDispenserMixin.java @@ -71,7 +71,7 @@ public void readFromNBTInject(CompoundTag nbttagcompound, CallbackInfo ci){ @Inject(at = @At("HEAD"), method = "stillValid", cancellable = true) public void canInteractWithInject(Player entityplayer, CallbackInfoReturnable cir) { - if(entityplayer instanceof PlayerServer && LockManager.determineAuthStatus(this, (PlayerServer) entityplayer) <= LockManager.UNTRUSTED){ + if(entityplayer instanceof Player && LockManager.determineAuthStatus(this, (PlayerServer) entityplayer) <= LockManager.UNTRUSTED){ cir.setReturnValue(false); return; } diff --git a/src/main/java/MelonUtilities/utility/MUtil.java b/src/main/java/MelonUtilities/utility/MUtil.java index 979dcb0..df6565f 100644 --- a/src/main/java/MelonUtilities/utility/MUtil.java +++ b/src/main/java/MelonUtilities/utility/MUtil.java @@ -1,19 +1,21 @@ package MelonUtilities.utility; +import MelonUtilities.MelonUtilities; import MelonUtilities.config.Data; import MelonUtilities.config.datatypes.data.Home; import MelonUtilities.config.datatypes.data.Warp; import MelonUtilities.interfaces.Lockable; +import MelonUtilities.interfaces.PlayerMagnetInterface; import MelonUtilities.utility.feedback.FeedbackHandlerServer; import MelonUtilities.utility.feedback.FeedbackType; import MelonUtilities.utility.managers.RollbackManager; import com.b100.json.JsonParser; import com.b100.json.element.JsonObject; import com.b100.utils.StringUtils; -import net.minecraft.client.entity.player.PlayerLocal; import net.minecraft.core.block.BlockLogicChest; import net.minecraft.core.block.Blocks; import net.minecraft.core.block.entity.TileEntityChest; +import net.minecraft.core.entity.Entity; import net.minecraft.core.entity.player.Player; import net.minecraft.core.net.command.TextFormatting; import net.minecraft.core.util.collection.Pair; @@ -23,9 +25,11 @@ import net.minecraft.core.util.helper.UUIDHelper; import net.minecraft.core.util.phys.HitResult; import net.minecraft.core.util.phys.Vec3; +import net.minecraft.core.world.Dimension; import net.minecraft.core.world.World; import net.minecraft.server.MinecraftServer; import net.minecraft.server.entity.player.PlayerServer; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -129,6 +133,122 @@ public static void runUUIDConversionAction(UUID uuid, @Nullable UsernameFunction }).start(); } + public static @Nullable Player closestPlayerToEntity(World world, Entity entity){ + Player closestPlayer = null; + float closestDistance = Float.MAX_VALUE; + for(Player player : world.players){ + float distanceTo = player.distanceTo(entity); + if(distanceTo < closestDistance){ + closestPlayer = player; + closestDistance = distanceTo; + } + } + return closestPlayer; + } + + public static @Nullable Player closestPlayerWithMagnetToItem(World world, Entity entity){ + Player closestPlayer = null; + float closestDistance = Float.MAX_VALUE; + for(Player player : world.players){ + if(!(PlayerMagnetInterface.class.cast(player).hasMagnet())){ + continue; + } + float distanceTo = player.distanceTo(entity); + if(distanceTo < closestDistance){ + closestPlayer = player; + closestDistance = distanceTo; + } + } + return closestPlayer; + } + + public static String hmsConversion(long systemTimeMillis) { + + Duration duration = Duration.ofMillis(systemTimeMillis); + + long h = duration.toHours(); + long m = duration.toMinutes() % 60; + long s = duration.getSeconds() % 60; + + return String.format("%02d:%02d:%02d [h:m:s]", h, m, s); + } + + //TODO simplify + public static String formatHexString(String dirtyHex){ + StringBuilder output = new StringBuilder(); + output.append("§<"); + char[] charArray = dirtyHex.toCharArray(); + for (int i = 0; i < charArray.length; i++) { + char c = charArray[i]; + if (i < 6 && Character.isDigit(c)) { + output.append(c); + } else { + break; + } + } + output.append(">"); + return output.toString(); + } + + // returns true if we teleported + public static boolean jumpOnElevator(World world, int x, int y, int z, Player player){ + for(int y2 = y+1; y2 < 255; y2++){ + if(world.getBlock(x, y2, z) == Blocks.BLOCK_STEEL && !Blocks.solid[world.getBlockId(x, y2+1, z)] && !Blocks.solid[world.getBlockId(x, y2+2, z)]){ + teleport(x+0.5, y2+1, z+0.5, player); + return true; + } + else if (world.getBlockId(x, y2, z) != 0 && !Data.MainConfig.config.allowObstructions) { + break; + } + } + return false; + } + + // returns true if we teleported + public static boolean sneakOnElevator(World world, int x, int y, int z, Player player){ + for(int y2 = y-1; y2 > 0; y2--){ + if(world.getBlock(x, y2, z) == Blocks.BLOCK_STEEL && !Blocks.solid[world.getBlockId(x, y2+1, z)] && !Blocks.solid[world.getBlockId(x, y2+2, z)]){ + teleport(x+0.5, y2+1, z+0.5, player); + return true; + } + else if (world.getBlockId(x, y2, z) != 0 && !Data.MainConfig.config.allowObstructions) { + break; + } + } + return false; + } + + public static void teleport(double x, double y, double z, @NotNull Player player, @NotNull Dimension dimension){ + + assert player.world != null; + player.world.playSoundAtEntity(null, player, "mob.ghast.fireball", 1f, 2f); + if (MelonUtilities.isServer){ + if(player.dimension != dimension.id){ + MinecraftServer mc = MinecraftServer.getInstance(); + mc.playerList.sendPlayerToOtherDimension((PlayerServer) player, dimension.id, DyeColor.WHITE, false); + } + ((PlayerServer) player).playerNetServerHandler.teleport(x, y + 0.2, z); + } else { + if(player.dimension != dimension.id){ + //client stuff + } + player.setPos(x, y + player.bbHeight + 0.2, z); + } + player.world.playSoundAtEntity(null, player, "mob.ghast.fireball", 1f, 2f); + + } + + public static void teleport(double x, double y, double z, @NotNull Player player){ + assert player.world != null; + player.world.playSoundAtEntity(null, player, "mob.ghast.fireball", 1f, 2f); + if (MelonUtilities.isServer){ + ((PlayerServer) player).playerNetServerHandler.teleport(x, y + 0.2, z); + } else { + player.setPos(x, y + player.bbHeight + 0.2, z); + } + player.world.playSoundAtEntity(null, player, "mob.ghast.fireball", 1f, 2f); + } + public interface UsernameFunction { void run(String username); } @@ -327,97 +447,12 @@ public static TileEntityChest getOtherChest(World world, TileEntityChest chest){ return null; } - // returns true if we teleported - public static boolean jumpOnElevator(World world, int x, int y, int z, Player player){ - for(int y2 = y+1; y2 < 255; y2++){ - if(world.getBlock(x, y2, z) == Blocks.BLOCK_STEEL && !Blocks.solid[world.getBlockId(x, y2+1, z)] && !Blocks.solid[world.getBlockId(x, y2+2, z)]){ - teleport(x+0.5, y2+1, z+0.5, player); - return true; - } - else if (world.getBlockId(x, y2, z) != 0 && !Data.MainConfig.config.allowObstructions) { - break; - } - } - return false; - } - - // returns true if we teleported - public static boolean sneakOnElevator(World world, int x, int y, int z, Player player){ - for(int y2 = y-1; y2 > 0; y2--){ - if(world.getBlock(x, y2, z) == Blocks.BLOCK_STEEL && !Blocks.solid[world.getBlockId(x, y2+1, z)] && !Blocks.solid[world.getBlockId(x, y2+2, z)]){ - teleport(x+0.5, y2+1, z+0.5, player); - return true; - } - else if (world.getBlockId(x, y2, z) != 0 && !Data.MainConfig.config.allowObstructions) { - break; - } - } - return false; - } - public static void sendToHome(Player player, Home home) { - if (player instanceof PlayerServer) { - if (player.dimension != home.dimID) { - MinecraftServer mc = MinecraftServer.getInstance(); - mc.playerList.sendPlayerToOtherDimension((PlayerServer) player, home.dimID, DyeColor.WHITE, false); - } - } else if (player instanceof PlayerLocal){ - //IDK and IDC - } - teleport(home.x, home.y, home.z, player); + teleport(home.x, home.y, home.z, player, Dimension.getDimensionList().get(home.dimID)); } public static void sendToWarp(Player player, Warp warp) { - if (player instanceof PlayerServer) { - if (player.dimension != warp.dimID) { - MinecraftServer mc = MinecraftServer.getInstance(); - mc.playerList.sendPlayerToOtherDimension((PlayerServer) player, warp.dimID, DyeColor.WHITE, false); - } - } else if (player instanceof PlayerLocal){ - //IDK and IDC - } - teleport(warp.x, warp.y, warp.z, player); - } - - public static void teleport(double x, double y, double z, Player player){ - if (player.world.isClientSide) return; - - if (player instanceof PlayerServer){ - player.world.playSoundAtEntity(null, player, "mob.ghast.fireball", 1f, 2f); - //FeedbackHandlerServer.sendFeedback((PlayerServer) player, TextFormatting.ORANGE, "☁ Whoosh! ☁"); - ((PlayerServer) player).playerNetServerHandler.teleport(x, y + 0.2, z); - } else if (player instanceof PlayerLocal) { - player.world.playSoundAtEntity(null, player, "mob.ghast.fireball", 1f, 2f); - //player.sendMessage(TextFormatting.ORANGE + "☁ Whoosh! ☁"); - player.setPos(x, y + player.bbHeight + 0.2, z); - } - player.world.playSoundAtEntity(null, player, "mob.ghast.fireball", 1f, 2f); + teleport(warp.x, warp.y, warp.z, player, Dimension.getDimensionList().get(warp.dimID)); } - public static String hmsConversion(long systemTimeMillis) { - - Duration duration = Duration.ofMillis(systemTimeMillis); - - long h = duration.toHours(); - long m = duration.toMinutes() % 60; - long s = duration.getSeconds() % 60; - - return String.format("%02d:%02d:%02d [h:m:s]", h, m, s); - } - - public static String formatHexString(String dirtyHex){ - StringBuilder output = new StringBuilder(); - output.append("§<"); - char[] charArray = dirtyHex.toCharArray(); - for (int i = 0; i < charArray.length; i++) { - char c = charArray[i]; - if (i < 6 && Character.isDigit(c)) { - output.append(c); - } else { - break; - } - } - output.append(">"); - return output.toString(); - } } diff --git a/src/main/java/MelonUtilities/utility/feedback/FeedbackHandlerClient.java b/src/main/java/MelonUtilities/utility/feedback/FeedbackHandlerClient.java new file mode 100644 index 0000000..27b594c --- /dev/null +++ b/src/main/java/MelonUtilities/utility/feedback/FeedbackHandlerClient.java @@ -0,0 +1,106 @@ +package MelonUtilities.utility.feedback; + +import MelonUtilities.MelonUtilities; +import net.minecraft.core.entity.player.Player; +import net.minecraft.core.lang.I18n; +import net.minecraft.core.net.command.TextFormatting; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + +public class FeedbackHandlerClient { + + public static void sendTranslatedFeedback(@NotNull FeedbackType feedbackType, @NotNull Player player, @NotNull String formatKey, FeedbackArg... args) { + player.sendMessage(translateKeyAndFormat(feedbackType, formatKey, args)); + MelonUtilities.LOGGER.info(String.format("Sent command feedback: [%s] to player: [username: %s, uuid: %s]", translateKeyAndFormatRaw(formatKey, args), player.username, player.uuid)); + playFeedbackSound(player, feedbackType); + } + + public static void sendFeedback(@NotNull FeedbackType feedbackType, @NotNull Player player, @NotNull String message, FeedbackArg... args) { + player.sendMessage(format(feedbackType, message, args)); + MelonUtilities.LOGGER.info(String.format("Sent command feedback: [%s] to player: [username: %s, uuid: %s]", formatRaw(message, args), player.username, player.uuid)); + playFeedbackSound(player, feedbackType); + } + + public static void sendFeedback(@NotNull Player player, @NotNull TextFormatting color, @NotNull String message, FeedbackArg... args) { + player.sendMessage(format(color, message, args)); + MelonUtilities.LOGGER.info(String.format("Sent command feedback: [%s] to player: [username: %s, uuid: %s]", formatRaw(message, args), player.username, player.uuid)); + } + + public static @NotNull String translateKeyAndFormat(@NotNull FeedbackType feedbackType, @NotNull String formatKey, FeedbackArg... args){ + ArrayList argStrings = new ArrayList<>(); + for(FeedbackArg arg : args){ + String argString = ( + arg.getBorderColor() + arg.getBorderOpener() + + arg.getArgSpecial() + arg.getArgColor() + arg.getAllArgs() + + TextFormatting.RESET + + arg.getBorderColor() + arg.getBorderCloser() + + feedbackType.getColor() + ); + argStrings.add(argString); + } + return feedbackType.getColor() + I18n.getInstance().translateKeyAndFormat(formatKey, argStrings.toArray()); + } + + public static @NotNull String format(@NotNull FeedbackType feedbackType, @NotNull String message, FeedbackArg... args){ + ArrayList argStrings = new ArrayList<>(); + for(FeedbackArg arg : args){ + String argString = ( + arg.getBorderColor() + arg.getBorderOpener() + + arg.getArgSpecial() + arg.getArgColor() + arg.getAllArgs() + + TextFormatting.RESET + + arg.getBorderColor() + arg.getBorderCloser() + + feedbackType.getColor() + ); + argStrings.add(argString); + } + return feedbackType.getColor() + String.format(message, argStrings.toArray()); + } + + public static @NotNull String format(@NotNull TextFormatting color, @NotNull String message, FeedbackArg... args){ + ArrayList argStrings = new ArrayList<>(); + for(FeedbackArg arg : args){ + String argString = ( + arg.getBorderColor() + arg.getBorderOpener() + + arg.getArgSpecial() + arg.getArgColor() + arg.getAllArgs() + + TextFormatting.RESET + + arg.getBorderColor() + arg.getBorderCloser() + + color + ); + argStrings.add(argString); + } + return color + String.format(message, argStrings.toArray()); + } + + private static @NotNull String translateKeyAndFormatRaw(@NotNull String formatKey, FeedbackArg... args){ + ArrayList argStrings = new ArrayList<>(); + for(FeedbackArg arg : args){ + String argString = ( + arg.getBorderOpener() + + arg.getAllArgs() + + arg.getBorderCloser() + ); + argStrings.add(argString); + } + return I18n.getInstance().translateKeyAndFormat(formatKey, argStrings.toArray()); + } + + private static @NotNull String formatRaw(@NotNull String message, FeedbackArg... args){ + ArrayList argStrings = new ArrayList<>(); + for(FeedbackArg arg : args){ + String argString = ( + arg.getBorderOpener() + + arg.getAllArgs() + + arg.getBorderCloser() + ); + argStrings.add(argString); + } + return String.format(message, argStrings.toArray()); + } + + public static void playFeedbackSound(@NotNull Player player, @NotNull FeedbackType feedbackType){ + if(feedbackType.getSoundPath().equals("NO_SOUND_PATH")){return;} + assert player.world != null; + player.world.playSoundAtEntity(player, player, feedbackType.getSoundPath(), 1f, 1f); + } +} diff --git a/src/main/resources/MelonUtilities.mixins.json b/src/main/resources/MelonUtilities.mixins.json index c78cdef..d6855f2 100644 --- a/src/main/resources/MelonUtilities.mixins.json +++ b/src/main/resources/MelonUtilities.mixins.json @@ -5,15 +5,34 @@ "compatibilityLevel": "JAVA_8", "mixins": [ "CommandManagerMixin", + "PlayerMixinElevator" + ], + "client": [ + ], + "server": [ + "ChunkMixin", + "PlayerMixinMagnet", + "EntityItemMixin", + "ChunkProviderServerMixin", + "EntityTrackerEntryImplMixin", + "ExplosionMixin", + "MinecraftServerMixin", + "MinecraftServerMixinDiscord", "MobMixin", + "NetEntryItemMixin", + "PacketAddPlayerMixin", + "PacketHandlerLoginMixinDiscord", "PacketHandlerServerMixin", - "PlayerMixinElevator", + "PacketHandlerServerMixinDiscord", + "PacketLoginHandlerMixin", + "PlayerListMixin", "PlayerMixinInputInterface", "WorldMixin", "tile_entities.activator.BlockLogicActivatorMixin", "tile_entities.activator.TileEntityActivatorMixin", "tile_entities.basket.BlockLogicBasketMixin", "tile_entities.basket.TileEntityBasketMixin", + "tile_entities.blast_furnace.BlockLogicFurnaceBlastMixin", "tile_entities.chest.BlockLogicChestMixin", "tile_entities.chest.TileEntityChestMixin", "tile_entities.dispenser.BlockLogicDispenserMixin", @@ -25,22 +44,6 @@ "tile_entities.trommel.BlockLogicTrommelMixin", "tile_entities.trommel.TileEntityTrommelMixin" ], - "client": [ - ], - "server": [ - "ChunkMixin", - "ChunkProviderServerMixin", - "EntityTrackerEntryImplMixin", - "ExplosionMixin", - "MinecraftServerMixin", - "MinecraftServerMixinDiscord", - "PacketAddPlayerMixin", - "PacketHandlerLoginMixinDiscord", - "PacketHandlerServerMixinDiscord", - "PacketLoginHandlerMixin", - "PlayerListMixin", - "tile_entities.blast_furnace.BlockLogicFurnaceBlastMixin" - ], "injectors": { "defaultRequire": 1 } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 7e61554..da0bdfc 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -20,7 +20,10 @@ "entrypoints": { "main": [ "MelonUtilities.MelonUtilities" - ] + ], + "recipesReady": [ + "MelonUtilities.MelonUtilities" + ] }, "mixins": [ "MelonUtilities.mixins.json" diff --git a/src/main/resources/lang/MelonUtilities/en_US.lang b/src/main/resources/lang/MelonUtilities/en_US.lang index e69de29..44442dd 100644 --- a/src/main/resources/lang/MelonUtilities/en_US.lang +++ b/src/main/resources/lang/MelonUtilities/en_US.lang @@ -0,0 +1,4 @@ +options.melonutilities.category.elevators.allowObstructions=Allow Obstructions +options.melonutilities.category.elevators.cooldown=Cooldown +options.melonutilities.title=Melon Utilities +options.melonutilities.category.elevators=Elevators