├── src └── main │ ├── resources │ ├── lang │ │ └── BTE │ │ │ └── en_US.lang │ ├── icon.png │ ├── BTE.mixins.json │ └── fabric.mod.json │ └── java │ └── wyspr │ └── BTE │ ├── utils │ ├── TPARequestType.java │ ├── InstantTypeAdapter.java │ ├── WorldPosition.java │ ├── ContainerInvsee.java │ ├── Warps.java │ ├── Utils.java │ ├── Teleport.java │ ├── ConfigBuilder.java │ └── PlayerData.java │ ├── commands │ ├── PingCommand.java │ ├── CraftingCommand.java │ ├── VanishCommand.java │ ├── MOTDCommand.java │ ├── warp │ │ ├── WarpsCommand.java │ │ ├── DelWarpCommand.java │ │ ├── SetWarpCommand.java │ │ └── WarpCommand.java │ ├── InvseeCommand.java │ ├── TPA │ │ ├── TPRequestsCommand.java │ │ ├── TPAAllCommand.java │ │ ├── TPACommand.java │ │ ├── TPAHereCommand.java │ │ ├── TPDenyCommand.java │ │ └── TPConfirmCommand.java │ ├── RulesCommand.java │ ├── InfoCommand.java │ ├── FireballCommand.java │ ├── MuteCommand.java │ ├── UnmuteCommand.java │ ├── ColorsCommand.java │ ├── OPChatCommand.java │ ├── arguments │ │ ├── ArgumentTypeUser.java │ │ ├── ArgumentTypeWarp.java │ │ ├── ArgumentTypeCommand.java │ │ └── ArgumentTypeHome.java │ ├── PayCommand.java │ ├── BackCommand.java │ ├── gamemode │ │ ├── CreativeCommand.java │ │ ├── SurvivalCommand.java │ │ └── SpectatorCommand.java │ ├── FixCommand.java │ ├── GodCommand.java │ ├── home │ │ ├── HomesCommand.java │ │ ├── SethomeCommand.java │ │ ├── DelhomeCommand.java │ │ └── HomeCommand.java │ ├── RTPCommand.java │ ├── SmiteCommand.java │ ├── TntCommand.java │ ├── SudoCommand.java │ ├── TrollCommand.java │ └── ImportMelonUtilsCommand.java │ └── mixins │ ├── PlayerDataInterfaceMixin.java │ ├── MenuCraftingMixin.java │ ├── BlockFarmlandMixin.java │ ├── BlockBedMixin.java │ ├── EntityPrimedTNTMixin.java │ ├── PlayerListBoxMixin.java │ ├── PlayerListMixin.java │ ├── BlockTNTMixin.java │ ├── SpawnCommandMixin.java │ ├── PlayerServerMixin.java │ ├── CommandGameModeMixin.java │ ├── PacketHandlerServerMixin.java │ ├── CommandGiveMixin.java │ ├── CommandNicknameMixin.java │ └── EntityFishingBobberMixin.java ├── .gitignore ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── .editorconfig ├── settings.gradle.kts ├── .github └── workflows │ └── build.yml ├── gradlew.bat ├── gradlew └── LICENSE /src/main/resources/lang/BTE/en_US.lang: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | .vscode/ 4 | bin/ 5 | build/ 6 | out/ 7 | run/ 8 | run-server/ 9 | -------------------------------------------------------------------------------- /src/main/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/preprocessor/BetterThanEssentials/7.3/src/main/resources/icon.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/preprocessor/BetterThanEssentials/7.3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx2G 2 | 3 | # BTA 4 | bta_version=7.3_04 5 | bta_channel=release 6 | 7 | # Loader 8 | loader_version=0.15.6-bta.7 9 | 10 | # Other Mods 11 | mod_menu_version=3.0.0 12 | halplibe_version=5.2.4 13 | 14 | # Mod 15 | mod_version=1.1.0 16 | mod_group=wyspr 17 | mod_name=BTEssentials 18 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/TPARequestType.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | 4 | public enum TPARequestType { 5 | TPA { 6 | @Override 7 | public String toString() { 8 | return "To you"; 9 | } 10 | }, TPAHERE { 11 | @Override 12 | public String toString() { 13 | return "To them"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | tab_width = 4 8 | trim_trailing_whitespace = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | 13 | [*.gradle.kts] 14 | indent_style = tab 15 | 16 | [*.java] 17 | indent_style = tab 18 | 19 | [*.json] 20 | indent_style = space 21 | indent_size = 2 22 | 23 | [fabric.mod.json] 24 | indent_style = tab 25 | tab_width = 2 26 | 27 | [*.properties] 28 | indent_style = space 29 | indent_size = 2 30 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | maven { 5 | name = "Fabric" 6 | url = uri("https://maven.fabricmc.net/") 7 | } 8 | maven { 9 | name = "Jitpack" 10 | url = uri("https://jitpack.io") 11 | } 12 | maven { 13 | name = "Babric" 14 | url = uri("https://maven.glass-launcher.net/babric") 15 | } 16 | maven { 17 | name = "SignalumMavenInfrastructure" 18 | url = uri("https://maven.thesignalumproject.net/infrastructure") 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/InstantTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | import com.google.gson.TypeAdapter; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | 7 | import java.io.IOException; 8 | import java.time.Instant; 9 | 10 | public class InstantTypeAdapter extends TypeAdapter { 11 | @Override 12 | public void write(JsonWriter out, Instant value) throws IOException { 13 | out.value(value.toString()); // ISO-8601 string 14 | } 15 | 16 | @Override 17 | public Instant read(JsonReader in) throws IOException { 18 | return Instant.parse(in.nextString()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/PingCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import net.minecraft.core.net.command.CommandManager; 6 | import net.minecraft.core.net.command.CommandSource; 7 | 8 | @SuppressWarnings("ALL") public class PingCommand implements CommandManager.CommandRegistry { 9 | @Override 10 | public void register(CommandDispatcher commandDispatcher) { 11 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 12 | .literal("ping") 13 | .executes(context -> { 14 | ((CommandSource) context.getSource()).sendMessage("Pong!"); 15 | return 1; 16 | })); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/resources/BTE.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.8", 4 | "package": "wyspr.BTE.mixins", 5 | "compatibilityLevel": "JAVA_8", 6 | "mixins": [ 7 | ], 8 | "client": [ 9 | ], 10 | "injectors": { 11 | "defaultRequire": 1 12 | }, 13 | "server": [ 14 | "BlockBedMixin", 15 | "BlockFarmlandMixin", 16 | "BlockTNTMixin", 17 | "CommandGiveMixin", 18 | "CommandGameModeMixin", 19 | "CommandNicknameMixin", 20 | "EntityFishingBobberMixin", 21 | "EntityPrimedTNTMixin", 22 | "MenuCraftingMixin", 23 | "PacketHandlerServerMixin", 24 | "PlayerDataInterfaceMixin", 25 | "PlayerListBoxMixin", 26 | "PlayerListMixin", 27 | "PlayerServerMixin", 28 | "SpawnCommandMixin" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "btessentials", 4 | "version": "${version}", 5 | "name": "Better Than Essentials", 6 | "description": "An Essentials-like plugin for Better Than Adventure servers!", 7 | "authors": [ 8 | "wyspr" 9 | ], 10 | "contact": { 11 | "homepage": "", 12 | "sources": "" 13 | }, 14 | "icon": "icon.png", 15 | "license": "CC0-1.0", 16 | "environment": "server", 17 | "entrypoints": { 18 | "main": [ 19 | "wyspr.BTE.Essentials" 20 | ], 21 | "beforeGameStart": [ 22 | "wyspr.BTE.Essentials" 23 | ], 24 | "afterGameStart": [ 25 | "wyspr.BTE.Essentials" 26 | ], 27 | "recipesReady": [ 28 | "wyspr.BTE.Essentials" 29 | ] 30 | }, 31 | "mixins": [ 32 | "BTE.mixins.json" 33 | ], 34 | "depends": { 35 | "minecraft": "*", 36 | "fabricloader": ">=0.15.5" 37 | }, 38 | "suggests": { 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/PlayerDataInterfaceMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.core.entity.player.Player; 6 | import net.minecraft.server.entity.player.PlayerServer; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Unique; 9 | import wyspr.BTE.utils.PlayerData; 10 | 11 | @Environment(EnvType.SERVER) @Mixin(value = PlayerServer.class, remap = false) public class PlayerDataInterfaceMixin implements PlayerData.Interface { 12 | @Unique 13 | PlayerData playerData; 14 | 15 | @Override 16 | public PlayerData betterThanEssentials$getPlayerData(Player player) { 17 | if (this.playerData == null) this.playerData = new PlayerData(player); 18 | 19 | return this.playerData; 20 | } 21 | 22 | @Override 23 | public void betterThanEssentials$setPlayerData(Player player) { 24 | this.playerData = new PlayerData(player); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/WorldPosition.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | import java.io.Serializable; 4 | import java.util.Objects; 5 | 6 | public class WorldPosition implements Serializable { 7 | private static final long serialVersionUID = 1L; // Ensures version compatibility during deserialization 8 | 9 | public double x, y, z; 10 | public int dimID; 11 | 12 | public WorldPosition(double x, double y, double z, int dimID) { 13 | this.x = x; 14 | this.y = y; 15 | this.z = z; 16 | this.dimID = dimID; 17 | } 18 | 19 | @Override 20 | public int hashCode() { 21 | return Objects.hash(x, y, z, dimID); 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (this == o) return true; 27 | if (o == null || getClass() != o.getClass()) return false; 28 | WorldPosition that = (WorldPosition) o; 29 | return Double.compare(that.x, x) == 0 && Double.compare(that.y, y) == 0 && Double.compare( 30 | that.z, 31 | z 32 | ) == 0 && dimID == that.dimID; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/MenuCraftingMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.minecraft.core.entity.player.Player; 4 | import net.minecraft.core.player.inventory.menu.MenuCrafting; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 10 | import wyspr.BTE.utils.PlayerData; 11 | 12 | @Mixin(value = MenuCrafting.class, remap = false) 13 | public abstract class MenuCraftingMixin { 14 | @Inject(method = "stillValid", at = @At("HEAD"), cancellable = true) 15 | public void stillValid(Player player, CallbackInfoReturnable cir) { 16 | if (PlayerData.get(player).craftCommandOpen) { 17 | cir.setReturnValue(true); 18 | } 19 | } 20 | 21 | @Inject(method = "onCraftGuiClosed", at = @At("HEAD")) 22 | public void commandClose(Player player, CallbackInfo ci) { 23 | PlayerData.get(player).craftCommandOpen = false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/CraftingCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import net.minecraft.core.entity.player.Player; 6 | import net.minecraft.core.net.command.CommandManager; 7 | import net.minecraft.core.net.command.CommandSource; 8 | import wyspr.BTE.Essentials; 9 | import wyspr.BTE.utils.PlayerData; 10 | 11 | @SuppressWarnings("ALL") public class CraftingCommand implements CommandManager.CommandRegistry { 12 | @Override 13 | public void register(CommandDispatcher commandDispatcher) { 14 | String[] literals = {"craft", "crafting", "cb", "craftingtable"}; 15 | for (String literal : literals) { 16 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 17 | .literal(literal) 18 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.CraftCommand) 19 | .executes(context -> { 20 | CommandSource source = (CommandSource) context.getSource(); 21 | Player player = source.getSender(); 22 | PlayerData.get(player).craftCommandOpen = true; 23 | player.displayWorkbenchScreen((int) player.x, (int) player.y, (int) player.z); 24 | return 1; 25 | })); 26 | 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/BlockFarmlandMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.core.block.Block; 6 | import net.minecraft.core.block.BlockLogicFarmland; 7 | import net.minecraft.core.block.Blocks; 8 | import net.minecraft.core.entity.Entity; 9 | import net.minecraft.core.world.World; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | import wyspr.BTE.Essentials; 15 | 16 | @Environment(EnvType.SERVER) @Mixin(value = BlockLogicFarmland.class, remap = false) public class BlockFarmlandMixin { 17 | @Inject( 18 | method = "onEntityWalking", at = @At("HEAD"), cancellable = true 19 | ) 20 | public void trampleControl(World world, int x, int y, int z, Entity entity, CallbackInfo ci) { 21 | if (Essentials.DisableTrample) { 22 | ci.cancel(); 23 | } 24 | 25 | if (Essentials.EnableAntiTrampleFence) { 26 | Block blockBelow = world.getBlock(x, y - 1, z); 27 | if (blockBelow == Blocks.FENCE_PLANKS_OAK || blockBelow == Blocks.FENCE_PLANKS_OAK_PAINTED) { 28 | ci.cancel(); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/VanishCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import net.minecraft.core.entity.player.Player; 6 | import net.minecraft.core.net.command.CommandManager; 7 | import net.minecraft.core.net.command.CommandSource; 8 | import net.minecraft.core.net.command.TextFormatting; 9 | import net.minecraft.server.player.PlayerListBox; 10 | import wyspr.BTE.utils.PlayerData; 11 | 12 | @SuppressWarnings("ALL") public class VanishCommand implements CommandManager.CommandRegistry { 13 | 14 | @Override 15 | public void register(CommandDispatcher commandDispatcher) { 16 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral.literal("vanish") 17 | .requires(source -> ((CommandSource) source).hasAdmin()) 18 | .executes(context -> { 19 | CommandSource source = (CommandSource) context.getSource(); 20 | Player player = source.getSender(); 21 | boolean isVanished = PlayerData.get(player) 22 | .toggleVanished(); 23 | 24 | PlayerListBox.updateList(); 25 | 26 | if (isVanished) { 27 | player.sendMessage(TextFormatting.YELLOW + "You have vanished."); 28 | } else { 29 | player.sendMessage(TextFormatting.YELLOW + "You have reappeared."); 30 | } 31 | 32 | return 1; 33 | })); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/BlockBedMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.core.block.BlockLogicBed; 6 | import net.minecraft.core.entity.player.Player; 7 | import net.minecraft.core.net.command.TextFormatting; 8 | import net.minecraft.core.util.helper.Side; 9 | import net.minecraft.core.world.World; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 14 | import wyspr.BTE.Essentials; 15 | 16 | @Environment(EnvType.SERVER) @Mixin(value = BlockLogicBed.class, remap = false) public class BlockBedMixin { 17 | @Inject( 18 | method = "onBlockRightClicked", at = @At( 19 | value = "INVOKE", target = "Lnet/minecraft/core/world/World;setBlockWithNotify(IIII)Z", shift = At.Shift.BEFORE, by = 1 20 | ), cancellable = true 21 | ) 22 | public void bedBoomStop( 23 | World world, 24 | int x, 25 | int y, 26 | int z, 27 | Player player, 28 | Side side, 29 | double xPlaced, 30 | double yPlaced, 31 | CallbackInfoReturnable cir 32 | ) 33 | { 34 | if (Essentials.DisableBedExplosion) { 35 | player.sendMessage(TextFormatting.ORANGE + "You may not sleep here."); 36 | cir.setReturnValue(true); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/MOTDCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeString; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import net.minecraft.core.net.command.CommandManager; 8 | import net.minecraft.core.net.command.CommandSource; 9 | import net.minecraft.server.MinecraftServer; 10 | 11 | @SuppressWarnings("ALL") public class MOTDCommand implements CommandManager.CommandRegistry { 12 | @Override 13 | public void register(CommandDispatcher commandDispatcher) { 14 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 15 | .literal("motd") 16 | .executes(context -> { 17 | CommandSource source = (CommandSource) context.getSource(); 18 | source.sendMessage(MinecraftServer.getInstance().motd); 19 | return 1; 20 | }) 21 | .then(ArgumentBuilderLiteral 22 | .literal("set") 23 | .requires(source -> ((CommandSource) source).hasAdmin()) 24 | .then(ArgumentBuilderRequired 25 | .argument("motd", ArgumentTypeString.greedyString()) 26 | .executes(context -> { 27 | String newMOTD = context.getArgument("motd", String.class); 28 | MinecraftServer.getInstance().motd = newMOTD.replace("$$", "§"); 29 | return 1; 30 | })))); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/warp/WarpsCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.warp; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import net.minecraft.core.entity.player.Player; 6 | import net.minecraft.core.net.command.CommandManager; 7 | import net.minecraft.core.net.command.CommandSource; 8 | import net.minecraft.core.net.command.TextFormatting; 9 | import wyspr.BTE.Essentials; 10 | import wyspr.BTE.utils.Warps; 11 | 12 | import java.util.List; 13 | 14 | @SuppressWarnings("ALL") public class WarpsCommand implements CommandManager.CommandRegistry { 15 | @Override 16 | public void register(CommandDispatcher commandDispatcher) { 17 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 18 | .literal("warps") 19 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.WarpCommand) 20 | .executes(context -> { 21 | CommandSource source = (CommandSource) context.getSource(); 22 | Player player = source.getSender(); 23 | List warps = Warps.getWarps(); 24 | 25 | if (warps.isEmpty()) { 26 | player.sendMessage(TextFormatting.ORANGE + "There are no warps!"); 27 | return 1; 28 | } 29 | 30 | String warpsString = String.join(", ", warps); 31 | player.sendMessage(TextFormatting.ORANGE + "Warps: " + TextFormatting.YELLOW + warpsString); 32 | 33 | return 1; 34 | })); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/InvseeCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import net.minecraft.core.entity.player.Player; 7 | import net.minecraft.core.net.command.CommandManager; 8 | import net.minecraft.core.net.command.CommandSource; 9 | import net.minecraft.server.entity.player.PlayerServer; 10 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 11 | import wyspr.BTE.utils.ContainerInvsee; 12 | 13 | @SuppressWarnings("ALL") public class InvseeCommand implements CommandManager.CommandRegistry { 14 | @Override 15 | public void register(CommandDispatcher commandDispatcher) { 16 | String[] literals = {"invsee", "openinv"}; 17 | for (String literal : literals) { 18 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 19 | .literal(literal) 20 | .requires(source -> ((CommandSource) source).hasAdmin()) 21 | .then(ArgumentBuilderRequired 22 | .argument("target", ArgumentTypeUser.user()) 23 | .executes(context -> { 24 | CommandSource source = (CommandSource) context.getSource(); 25 | PlayerServer target = context.getArgument("target", PlayerServer.class); 26 | Player player = source.getSender(); 27 | player.displayContainerScreen(new ContainerInvsee(target)); 28 | 29 | return 1; 30 | }))); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # Automatically build the project and run any configured tests for every push 2 | # and submitted pull request. This can help catch issues that only occur on 3 | # certain platforms or Java versions, and provides a first line of defence 4 | # against bad commits. 5 | 6 | name: build 7 | on: [pull_request, push] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | # Use these Java versions 14 | java: [ 15 | 17, # Current Java LTS & minimum supported by Minecraft 16 | ] 17 | # and run on both Linux and Windows 18 | os: [ubuntu-latest, windows-latest] 19 | runs-on: ${{ matrix.os }} 20 | steps: 21 | - name: checkout repository 22 | uses: actions/checkout@v4 23 | - name: validate gradle wrapper 24 | uses: gradle/wrapper-validation-action@v2 25 | - name: setup jdk ${{ matrix.java }} 26 | uses: actions/setup-java@v4 27 | with: 28 | java-version: ${{ matrix.java }} 29 | distribution: 'temurin' 30 | - name: make gradle wrapper executable 31 | if: ${{ runner.os != 'Windows' }} 32 | run: chmod +x ./gradlew 33 | - name: build 34 | run: ./gradlew build 35 | - name: capture build artifacts 36 | if: ${{ runner.os == 'Linux' && matrix.java == '17' }} # Only upload artifacts built from latest java on one OS 37 | uses: actions/upload-artifact@v4 38 | with: 39 | name: Artifacts 40 | path: build/libs/ 41 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/EntityPrimedTNTMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.core.entity.Entity; 6 | import net.minecraft.core.entity.EntityPrimedTNT; 7 | import net.minecraft.core.world.Explosion; 8 | import net.minecraft.core.world.World; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Redirect; 12 | import wyspr.BTE.Essentials; 13 | 14 | @Environment(EnvType.SERVER) @Mixin(value = EntityPrimedTNT.class, remap = false) public class EntityPrimedTNTMixin { 15 | @Redirect( 16 | method = "tick", at = @At( 17 | value = "INVOKE", target = "Lnet/minecraft/core/world/World;createExplosion(Lnet/minecraft/core/entity/Entity;DDDF)Lnet/minecraft/core/world/Explosion;" 18 | ) 19 | ) 20 | public Explosion stopTNTBoom( 21 | World instance, 22 | Entity entity, 23 | double x, 24 | double y, 25 | double z, 26 | float explosionSize 27 | ) 28 | { 29 | 30 | if (instance.dimension.id == 0 && Essentials.DisableTNTOverworld <= (int) y) { 31 | entity.remove(); 32 | return null; 33 | } 34 | if (instance.dimension.id == 1 && Essentials.DisableTNTNether <= (int) y) { 35 | entity.remove(); 36 | return null; 37 | } 38 | if (instance.dimension.id == 2 && Essentials.DisableTNTSky <= (int) y) { 39 | entity.remove(); 40 | return null; 41 | } 42 | instance.createExplosion(null, x, y + 0.5, z, 4.0F); 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/PlayerListBoxMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.minecraft.core.net.packet.PacketPlayerList; 4 | import net.minecraft.core.player.gamemode.Gamemode; 5 | import net.minecraft.server.MinecraftServer; 6 | import net.minecraft.server.entity.player.PlayerServer; 7 | import net.minecraft.server.player.PlayerListBox; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Overwrite; 10 | import wyspr.BTE.utils.PlayerData; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | @Mixin(value = PlayerListBox.class, remap = false) public class PlayerListBoxMixin { 16 | /** 17 | * @author wyspr 18 | * @reason hide spectators from playerlist 19 | */ 20 | @Overwrite 21 | public static void updateList() { 22 | MinecraftServer server = MinecraftServer.getInstance(); 23 | List playersList = new ArrayList<>(); 24 | List scoresList = new ArrayList<>(); 25 | 26 | for (PlayerServer player : server.playerList.playerEntities) { 27 | if (PlayerData.get(player).vanished && player.gamemode == Gamemode.spectator) 28 | continue; // skip spectators 29 | playersList.add(player.getDisplayName()); 30 | scoresList.add(String.valueOf(player.getScore())); 31 | } 32 | 33 | int playerCount = playersList.size(); 34 | 35 | String[] players = new String[playerCount]; 36 | String[] scores = new String[playerCount]; 37 | 38 | for (int i = 0; i < playerCount; i++) players[i] = playersList.get(i); 39 | for (int i = 0; i < playerCount; i++) scores[i] = scoresList.get(i); 40 | 41 | server.playerList.sendPacketToAllPlayers(new PacketPlayerList(playerCount, players, scores)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/TPA/TPRequestsCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.TPA; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import net.minecraft.core.entity.player.Player; 6 | import net.minecraft.core.net.command.CommandManager; 7 | import net.minecraft.core.net.command.CommandSource; 8 | import net.minecraft.core.net.command.TextFormatting; 9 | import wyspr.BTE.Essentials; 10 | import wyspr.BTE.utils.PlayerData; 11 | 12 | import java.util.List; 13 | 14 | @SuppressWarnings("ALL") public class TPRequestsCommand implements CommandManager.CommandRegistry { 15 | @Override 16 | public void register(CommandDispatcher commandDispatcher) { 17 | 18 | String[] literals = {"tpreq", "tpr", "tprequests"}; 19 | for (String literal : literals) { 20 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 21 | .literal(literal) 22 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.TPACommand) 23 | .executes(context -> { 24 | CommandSource source = (CommandSource) context.getSource(); 25 | boolean isAdmin = source.hasAdmin(); 26 | Player player = source.getSender(); 27 | PlayerData playerData = PlayerData.get(player); 28 | List allRequests = playerData.tpManager.getAllRequests(); 29 | 30 | if (allRequests.isEmpty()) { 31 | player.sendMessage(TextFormatting.ORANGE + "No current TP requests"); 32 | } 33 | 34 | String requests = String.join(", ", allRequests); 35 | 36 | player.sendMessage(TextFormatting.ORANGE + "Current TP requests: " + requests); 37 | 38 | return 1; 39 | })); 40 | 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/PlayerListMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import com.llamalad7.mixinextras.sugar.Local; 4 | import net.fabricmc.api.EnvType; 5 | import net.fabricmc.api.Environment; 6 | import net.minecraft.server.entity.player.PlayerServer; 7 | import net.minecraft.server.net.PlayerList; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 13 | import wyspr.BTE.Essentials; 14 | import wyspr.BTE.utils.PlayerData; 15 | 16 | @Environment(EnvType.SERVER) @Mixin(value = PlayerList.class, remap = false) public class PlayerListMixin { 17 | @Inject(at = @At("TAIL"), method = "playerLoggedIn") 18 | public void onLogin(PlayerServer player, CallbackInfo ci) { 19 | PlayerData.set(player); 20 | Essentials.LOGGER.info("Loading player data for: {}", player.username); 21 | } 22 | 23 | @Inject(at = @At("HEAD"), method = "playerLoggedOut") 24 | public void onLogout(PlayerServer entityplayermp, CallbackInfo ci) { 25 | PlayerData.set(entityplayermp); 26 | } 27 | 28 | 29 | @Inject(method = "recreatePlayerEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/player/inventory/container/ContainerInventory;transferAllContents(Lnet/minecraft/core/player/inventory/container/ContainerInventory;)V"), remap = false) 30 | public void keepInfoMP( 31 | PlayerServer previousPlayer, 32 | int dimension, 33 | CallbackInfoReturnable cir, 34 | @Local(name = "newPlayer") final PlayerServer newPlayer 35 | ) 36 | { 37 | newPlayer.score = (int) (previousPlayer.score * Essentials.DeathCost); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/RulesCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeInteger; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import com.mojang.brigadier.context.CommandContext; 8 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 9 | import net.minecraft.core.entity.player.Player; 10 | import net.minecraft.core.net.command.CommandManager; 11 | import net.minecraft.core.net.command.CommandSource; 12 | import org.jetbrains.annotations.NotNull; 13 | import wyspr.BTE.Essentials; 14 | 15 | @SuppressWarnings("ALL") public class RulesCommand implements CommandManager.CommandRegistry { 16 | @Override 17 | public void register(CommandDispatcher dispatcher) { 18 | dispatcher.register((ArgumentBuilderLiteral) (ArgumentBuilderLiteral 19 | .literal("rules") 20 | .executes(this::noArg)).then(ArgumentBuilderRequired 21 | .argument("page", ArgumentTypeInteger.integer(1)) 22 | .executes(this::pageArg))); 23 | } 24 | 25 | private @NotNull int noArg(CommandContext context) throws CommandSyntaxException { 26 | CommandSource source = (CommandSource) context.getSource(); 27 | Player player = source.getSender(); 28 | 29 | for (String line : Essentials.rules.get(1)) player.sendMessage(line); 30 | 31 | return 1; 32 | } 33 | 34 | private @NotNull int pageArg(CommandContext context) throws CommandSyntaxException { 35 | CommandSource source = (CommandSource) context.getSource(); 36 | Player player = source.getSender(); 37 | int page = context.getArgument("page", Integer.class); 38 | 39 | for (String line : Essentials.rules.get(page)) player.sendMessage(line); 40 | 41 | return 1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/InfoCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeInteger; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import com.mojang.brigadier.context.CommandContext; 8 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 9 | import net.minecraft.core.entity.player.Player; 10 | import net.minecraft.core.net.command.CommandManager; 11 | import net.minecraft.core.net.command.CommandSource; 12 | import org.jetbrains.annotations.NotNull; 13 | import wyspr.BTE.Essentials; 14 | 15 | @SuppressWarnings("ALL") public class InfoCommand implements CommandManager.CommandRegistry { 16 | @Override 17 | public void register(CommandDispatcher commandDispatcher) { 18 | commandDispatcher.register((ArgumentBuilderLiteral) (ArgumentBuilderLiteral 19 | .literal("info") 20 | .executes(this::noArg)).then(ArgumentBuilderRequired 21 | .argument("page", ArgumentTypeInteger.integer(1)) 22 | .executes(this::pageArg))); 23 | } 24 | 25 | private @NotNull int noArg(CommandContext context) throws CommandSyntaxException { 26 | CommandSource source = (CommandSource) context.getSource(); 27 | Player player = source.getSender(); 28 | 29 | for (String line : Essentials.info.get(1)) player.sendMessage(line); 30 | 31 | return 1; 32 | } 33 | 34 | private @NotNull int pageArg(CommandContext context) throws CommandSyntaxException { 35 | CommandSource source = (CommandSource) context.getSource(); 36 | Player player = source.getSender(); 37 | int page = context.getArgument("page", Integer.class); 38 | 39 | for (String line : Essentials.info.get(page)) player.sendMessage(line); 40 | 41 | return 1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/BlockTNTMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.core.block.Block; 6 | import net.minecraft.core.block.BlockLogic; 7 | import net.minecraft.core.block.BlockLogicTNT; 8 | import net.minecraft.core.block.material.Material; 9 | import net.minecraft.core.entity.player.Player; 10 | import net.minecraft.core.net.command.TextFormatting; 11 | import net.minecraft.core.world.World; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.injection.At; 14 | import org.spongepowered.asm.mixin.injection.Inject; 15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 16 | import wyspr.BTE.Essentials; 17 | 18 | @Environment(EnvType.SERVER) @Mixin(value = BlockLogicTNT.class, remap = false) public class BlockTNTMixin extends BlockLogic { 19 | public BlockTNTMixin(Block block, Material material) { 20 | super(block, material); 21 | } 22 | 23 | @Inject( 24 | method = "ignite(Lnet/minecraft/core/world/World;IIILnet/minecraft/core/entity/player/Player;Z)V", at = @At("HEAD"), cancellable = true 25 | ) 26 | public void disableAbove(World world, int x, int y, int z, Player player, boolean sound, CallbackInfo ci) 27 | { 28 | String msg = TextFormatting.YELLOW + "TNT is disabled above y: " + TextFormatting.LIME; 29 | if (world.dimension.id == 0 && Essentials.DisableTNTOverworld <= y) { 30 | player.sendMessage(msg + Essentials.DisableTNTOverworld); 31 | ci.cancel(); 32 | } 33 | if (world.dimension.id == 1 && Essentials.DisableTNTNether <= y) { 34 | player.sendMessage(msg + Essentials.DisableTNTNether); 35 | ci.cancel(); 36 | } 37 | if (world.dimension.id == 2 && Essentials.DisableTNTSky <= y) { 38 | player.sendMessage(msg + Essentials.DisableTNTSky); 39 | ci.cancel(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/FireballCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.context.CommandContext; 6 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.entity.projectile.ProjectileFireball; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.world.World; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | @SuppressWarnings("ALL") public class FireballCommand implements CommandManager.CommandRegistry { 15 | @Override 16 | public void register(CommandDispatcher dispatcher) { 17 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 18 | .literal("fireball") 19 | .requires(source -> ((CommandSource) source).hasAdmin()) 20 | .executes(this::exec)); 21 | } 22 | 23 | private @NotNull int exec(CommandContext context) throws CommandSyntaxException { 24 | CommandSource source = (CommandSource) context.getSource(); 25 | Player player = source.getSender(); 26 | 27 | World world = player.world; 28 | 29 | double x = player.x; 30 | double y = player.y + 1; 31 | double z = player.z; 32 | 33 | double pitchRad = Math.toRadians(player.xRot); 34 | double yawRad = Math.toRadians(player.yRot); 35 | 36 | double vX = -Math.sin(yawRad) * Math.cos(pitchRad); 37 | double vZ = Math.cos(yawRad) * Math.cos(pitchRad); 38 | double vY = -Math.sin(pitchRad); 39 | 40 | world.playSoundAtEntity(null, player, "mob.ghast.fireball", 1, 1); 41 | ProjectileFireball fireball = new ProjectileFireball(world, x, y, z, vX, vY, vZ); 42 | world.entityJoinedWorld(fireball); 43 | 44 | return 1; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/warp/DelWarpCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.warp; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.net.command.CommandManager; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.net.command.TextFormatting; 11 | import wyspr.BTE.commands.arguments.ArgumentTypeWarp; 12 | import wyspr.BTE.utils.Warps; 13 | 14 | @SuppressWarnings("ALL") public class DelWarpCommand implements CommandManager.CommandRegistry { 15 | @Override 16 | public void register(CommandDispatcher commandDispatcher) { 17 | String[] literals = {"delwarp", "rmwarp"}; 18 | for (String literal : literals) { 19 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 20 | .literal(literal) 21 | .requires(source -> ((CommandSource) source).hasAdmin()) 22 | .then(ArgumentBuilderRequired 23 | .argument("target", ArgumentTypeWarp.warp()) 24 | .executes(this::exec))); 25 | 26 | } 27 | } 28 | 29 | private int exec(CommandContext context) { 30 | CommandSource source = (CommandSource) context.getSource(); 31 | Player player = source.getSender(); 32 | String target = context.getArgument("target", String.class); 33 | 34 | if (Warps.removeWarp(target)) { 35 | player.sendMessage(TextFormatting.ORANGE + "Removed warp: " + TextFormatting.YELLOW + target); 36 | } else { 37 | player.sendMessage(TextFormatting.ORANGE + "There is no warp named: " + TextFormatting.YELLOW + target); 38 | player.sendMessage(TextFormatting.ORANGE + "Set a warp with: §3/setwarp [name]"); 39 | } 40 | 41 | return 1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/MuteCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import net.minecraft.core.entity.player.Player; 7 | import net.minecraft.core.net.command.CommandManager; 8 | import net.minecraft.core.net.command.CommandSource; 9 | import net.minecraft.core.net.command.TextFormatting; 10 | import net.minecraft.server.entity.player.PlayerServer; 11 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 12 | import wyspr.BTE.utils.PlayerData; 13 | 14 | @SuppressWarnings("ALL") public class MuteCommand implements CommandManager.CommandRegistry { 15 | 16 | @Override 17 | public void register(CommandDispatcher commandDispatcher) { 18 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 19 | .literal("mute") 20 | .requires(source -> ((CommandSource) source).hasAdmin()) 21 | .then(ArgumentBuilderRequired 22 | .argument("player", ArgumentTypeUser.user()) 23 | .executes(context -> { 24 | CommandSource source = (CommandSource) context.getSource(); 25 | Player player = source.getSender(); 26 | PlayerServer target = context.getArgument("player", PlayerServer.class); 27 | PlayerData targetData = PlayerData.get(target); 28 | 29 | boolean isAlreadyMuted = targetData.muted; 30 | targetData.mute(); 31 | 32 | if (isAlreadyMuted) { 33 | player.sendMessage(TextFormatting.LIGHT_BLUE + target.username + TextFormatting.YELLOW + " is already muted."); 34 | } else { 35 | player.sendMessage(TextFormatting.YELLOW + "You have muted " + TextFormatting.LIGHT_BLUE + target.username); 36 | target.sendMessage(TextFormatting.RED + "You have been muted."); 37 | } 38 | return 1; 39 | }))); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/warp/SetWarpCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.warp; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeString; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import com.mojang.brigadier.context.CommandContext; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import wyspr.BTE.utils.Warps; 13 | import wyspr.BTE.utils.WorldPosition; 14 | 15 | @SuppressWarnings("ALL") public class SetWarpCommand implements CommandManager.CommandRegistry { 16 | @Override 17 | public void register(CommandDispatcher commandDispatcher) { 18 | String[] literals = {"setwarp", "addwarp"}; 19 | for (String literal : literals) { 20 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 21 | .literal(literal) 22 | .requires(source -> ((CommandSource) source).hasAdmin()) 23 | .then(ArgumentBuilderRequired 24 | .argument("target", ArgumentTypeString.string()) 25 | .executes(this::exec))); 26 | } 27 | } 28 | 29 | private int exec(CommandContext context) { 30 | CommandSource source = (CommandSource) context.getSource(); 31 | Player player = source.getSender(); 32 | String target = context.getArgument("target", String.class); 33 | 34 | if (Warps.addWarp( 35 | target, 36 | new WorldPosition(player.x, player.y, player.z, player.dimension) 37 | )) { 38 | player.sendMessage(TextFormatting.ORANGE + "Created warp: " + TextFormatting.YELLOW + target); 39 | } else { 40 | player.sendMessage(TextFormatting.YELLOW + "" + target + TextFormatting.ORANGE + " already exists"); 41 | } 42 | 43 | return 1; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/UnmuteCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import net.minecraft.core.entity.player.Player; 7 | import net.minecraft.core.net.command.CommandManager; 8 | import net.minecraft.core.net.command.CommandSource; 9 | import net.minecraft.core.net.command.TextFormatting; 10 | import net.minecraft.server.entity.player.PlayerServer; 11 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 12 | import wyspr.BTE.utils.PlayerData; 13 | 14 | @SuppressWarnings("ALL") public class UnmuteCommand implements CommandManager.CommandRegistry { 15 | 16 | @Override 17 | public void register(CommandDispatcher commandDispatcher) { 18 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 19 | .literal("unmute") 20 | .requires(source -> ((CommandSource) source).hasAdmin()) 21 | .then(ArgumentBuilderRequired 22 | .argument("player", ArgumentTypeUser.user()) 23 | .executes(context -> { 24 | CommandSource source = (CommandSource) context.getSource(); 25 | Player player = source.getSender(); 26 | PlayerServer target = context.getArgument("player", PlayerServer.class); 27 | PlayerData targetData = PlayerData.get(target); 28 | 29 | boolean isAlreadyUnmuted = !targetData.muted; 30 | targetData.unmute(); 31 | 32 | if (isAlreadyUnmuted) { 33 | player.sendMessage( 34 | TextFormatting.LIGHT_BLUE + target.username + 35 | TextFormatting.YELLOW + " is already unmuted." 36 | ); 37 | } else { 38 | player.sendMessage( 39 | TextFormatting.YELLOW + "You have unmuted " + 40 | TextFormatting.LIGHT_BLUE + target.username 41 | ); 42 | target.sendMessage(TextFormatting.ORANGE + "You have been unmuted."); 43 | } 44 | return 1; 45 | }))); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/ColorsCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import net.minecraft.core.net.command.CommandManager; 6 | import net.minecraft.core.net.command.CommandSource; 7 | 8 | @SuppressWarnings("ALL") public class ColorsCommand implements CommandManager.CommandRegistry { 9 | @Override 10 | public void register(CommandDispatcher commandDispatcher) { 11 | 12 | String[] literals = {"colorcodes", "colourcodes"}; 13 | for (String literal : literals) { 14 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 15 | .literal(literal) 16 | .executes(context -> { 17 | CommandSource source = (CommandSource) context.getSource(); 18 | source.sendMessage("§§00 = §0White"); 19 | source.sendMessage("§§01 = §1Orange"); 20 | source.sendMessage("§§02 = §2Magenta"); 21 | source.sendMessage("§§03 = §3Light blue / Aqua"); 22 | source.sendMessage("§§04 = §4Yellow"); 23 | source.sendMessage("§§05 = §5Lime"); 24 | source.sendMessage("§§06 = §6Pink"); 25 | source.sendMessage("§§07 = §7Grey"); 26 | source.sendMessage("§§08 = §8Light Grey / Silver"); 27 | source.sendMessage("§§09 = §9Cyan / Turquoise"); 28 | source.sendMessage("§§0a = §aPurple"); 29 | source.sendMessage("§§0b = §bBlue"); 30 | source.sendMessage("§§0c = §cBrown"); 31 | source.sendMessage("§§0d = §dGreen"); 32 | source.sendMessage("§§0e = §eRed"); 33 | source.sendMessage("§§0f = §fBlack"); 34 | source.sendMessage("§§0k = (Obfuscated, §e§lOperator§r only.) §kObfuscated §r"); 35 | source.sendMessage("§§0l = §lBold"); 36 | source.sendMessage("§§0m = §mStrikethrough"); 37 | source.sendMessage("§§0n = §nUnderline"); 38 | source.sendMessage("§§0o = §oItalic"); 39 | source.sendMessage("§§0r = §rnormal!"); 40 | return 1; 41 | })); 42 | 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/OPChatCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeString; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.net.command.CommandManager; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.net.command.TextFormatting; 11 | import net.minecraft.server.MinecraftServer; 12 | import net.minecraft.server.net.PlayerList; 13 | 14 | @SuppressWarnings("ALL") public class OPChatCommand implements CommandManager.CommandRegistry { 15 | @Override 16 | public void register(CommandDispatcher commandDispatcher) { 17 | String[] literals = {"chatop", "opc", "opchat"}; 18 | for (String literal : literals) { 19 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 20 | .literal(literal) 21 | .requires(CommandSource::hasAdmin) 22 | .then(ArgumentBuilderRequired 23 | .argument("message", ArgumentTypeString.greedyString()) 24 | .executes(context -> { 25 | CommandSource source = (CommandSource) context.getSource(); 26 | Player player = source.getSender(); 27 | String message = context.getArgument("message", String.class); 28 | String opChat = opChat(player, message); 29 | PlayerList playerList = MinecraftServer.getInstance().playerList; 30 | playerList.sendChatMessageToPlayer("_wyspr", opChat); 31 | playerList.sendChatMessageToAllOps(opChat); 32 | return 1; 33 | }))); 34 | } 35 | } 36 | 37 | public String opChat(Player player, String message) { 38 | return "[" + TextFormatting.RED + TextFormatting.BOLD + "OP CHAT" + TextFormatting.RESET + "] <" + player.username + TextFormatting.RESET + "> " + message.replace("$$", "§"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/arguments/ArgumentTypeUser.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.arguments; 2 | 3 | import com.mojang.brigadier.StringReader; 4 | import com.mojang.brigadier.arguments.ArgumentType; 5 | import com.mojang.brigadier.context.CommandContext; 6 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 7 | import com.mojang.brigadier.suggestion.Suggestions; 8 | import com.mojang.brigadier.suggestion.SuggestionsBuilder; 9 | import net.minecraft.server.MinecraftServer; 10 | import net.minecraft.server.entity.player.PlayerServer; 11 | import net.minecraft.server.net.command.ServerCommandSource; 12 | 13 | import java.util.List; 14 | import java.util.concurrent.CompletableFuture; 15 | 16 | public class ArgumentTypeUser implements ArgumentType { 17 | public ArgumentTypeUser() {} 18 | 19 | public static ArgumentType user() { 20 | return new ArgumentTypeUser(); 21 | } 22 | 23 | public PlayerServer parse(StringReader reader) throws CommandSyntaxException { 24 | final String string = reader.readString(); 25 | List players = MinecraftServer.getInstance().playerList.playerEntities; 26 | 27 | for (PlayerServer player : players) { 28 | if (player.username.equalsIgnoreCase(string)) { 29 | return player; 30 | } 31 | } 32 | throw new CommandSyntaxException( 33 | CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), 34 | () -> "Failed to find User: " + string 35 | ); 36 | } 37 | 38 | public CompletableFuture listSuggestions( 39 | CommandContext context, 40 | SuggestionsBuilder builder 41 | ) 42 | { 43 | MinecraftServer server = ((ServerCommandSource) context.getSource()).getServer(); 44 | List players = server.playerList.playerEntities; 45 | 46 | for (PlayerServer player : players) { 47 | String username = player.username; 48 | if (username.startsWith(builder.getRemaining())) { 49 | builder.suggest(username); 50 | } 51 | } 52 | 53 | return builder.buildFuture(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/arguments/ArgumentTypeWarp.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.arguments; 2 | 3 | import com.mojang.brigadier.StringReader; 4 | import com.mojang.brigadier.arguments.ArgumentType; 5 | import com.mojang.brigadier.context.CommandContext; 6 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 7 | import com.mojang.brigadier.suggestion.Suggestions; 8 | import com.mojang.brigadier.suggestion.SuggestionsBuilder; 9 | import wyspr.BTE.utils.Warps; 10 | 11 | import java.util.Arrays; 12 | import java.util.Collection; 13 | import java.util.List; 14 | import java.util.concurrent.CompletableFuture; 15 | 16 | // Adapted from 17 | // https://github.com/MelonModding/MelonUtilities/blob/main/src/main/java/MelonUtilities/command/arguments/ArgumentTypeWarp.java 18 | 19 | public class ArgumentTypeWarp implements ArgumentType { 20 | private static final List EXAMPLES = Arrays.asList("market", "arena", "parkour"); 21 | 22 | public ArgumentTypeWarp() {} 23 | 24 | public static ArgumentType warp() { 25 | return new ArgumentTypeWarp(); 26 | } 27 | 28 | public String parse(StringReader reader) throws CommandSyntaxException { 29 | final String string = reader.readString(); 30 | 31 | List warps = Warps.getWarps(); 32 | for (String warp : warps) { 33 | if (warp.equalsIgnoreCase(string)) { 34 | return warp; 35 | } 36 | } 37 | throw new CommandSyntaxException( 38 | CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), 39 | () -> "Failed to find Warp: " + string + " (Warp Doesn't Exist)" 40 | ); 41 | } 42 | 43 | public CompletableFuture listSuggestions( 44 | CommandContext context, 45 | SuggestionsBuilder builder 46 | ) 47 | { 48 | List warps = Warps.getWarps(); 49 | for (String warp : warps) { 50 | if (warp.startsWith(builder.getRemaining())) { 51 | builder.suggest(warp); 52 | } 53 | } 54 | 55 | return builder.buildFuture(); 56 | } 57 | 58 | public Collection getExamples() { 59 | return EXAMPLES; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/arguments/ArgumentTypeCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.arguments; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.StringReader; 5 | import com.mojang.brigadier.arguments.ArgumentType; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.suggestion.Suggestions; 8 | import com.mojang.brigadier.suggestion.SuggestionsBuilder; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.server.MinecraftServer; 11 | import net.minecraft.server.entity.player.PlayerServer; 12 | import net.minecraft.server.net.command.ServerCommandSource; 13 | 14 | import java.util.Objects; 15 | import java.util.concurrent.CompletableFuture; 16 | 17 | public class ArgumentTypeCommand implements ArgumentType { 18 | public ArgumentTypeCommand() { 19 | } 20 | 21 | public static ArgumentType commands() { 22 | return new ArgumentTypeCommand(); 23 | } 24 | 25 | @Override 26 | public String parse(StringReader reader) { 27 | String text = reader.getRemaining(); 28 | reader.setCursor(reader.getTotalLength()); 29 | return text; 30 | } 31 | 32 | @Override 33 | public CompletableFuture listSuggestions( 34 | CommandContext context, 35 | SuggestionsBuilder builder 36 | ) 37 | { 38 | PlayerServer target = context.getArgument("player", PlayerServer.class); 39 | ServerCommandSource playerCommandSource = new ServerCommandSource( 40 | MinecraftServer.getInstance(), 41 | target 42 | ); 43 | CommandDispatcher dispatcher = MinecraftServer 44 | .getInstance() 45 | .getDimensionWorld(target.dimension) 46 | .getCommandManager() 47 | .getDispatcher(); 48 | 49 | String[] commands = dispatcher.getAllUsage(dispatcher.getRoot(), playerCommandSource, true); 50 | for (String command : commands) { 51 | String cmd = command.split(" ")[0]; 52 | if (Objects.equals(cmd, "")) continue; 53 | if (cmd.startsWith(builder.getRemainingLowerCase())) { 54 | builder.suggest(cmd); 55 | } 56 | } 57 | 58 | return builder.buildFuture(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/TPA/TPAAllCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.TPA; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import net.minecraft.core.entity.player.Player; 6 | import net.minecraft.core.net.command.CommandManager; 7 | import net.minecraft.core.net.command.CommandSource; 8 | import net.minecraft.core.net.command.TextFormatting; 9 | import net.minecraft.server.MinecraftServer; 10 | import net.minecraft.server.entity.player.PlayerServer; 11 | import wyspr.BTE.utils.PlayerData; 12 | import wyspr.BTE.utils.TPARequestType; 13 | 14 | import java.util.List; 15 | 16 | @SuppressWarnings("ALL") public class TPAAllCommand implements CommandManager.CommandRegistry { 17 | @Override 18 | public void register(CommandDispatcher commandDispatcher) { 19 | String[] literals = {"tpall", "tpaall"}; 20 | for (String literal : literals) { 21 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 22 | .literal(literal) 23 | .requires(source -> ((CommandSource) source).hasAdmin()) 24 | .executes(context -> { 25 | CommandSource source = (CommandSource) context.getSource(); 26 | Player player = source.getSender(); 27 | PlayerData playerData = PlayerData.get(player); 28 | 29 | List players 30 | = MinecraftServer.getInstance().playerList.playerEntities; 31 | 32 | for (PlayerServer targetPlayer : players) { 33 | PlayerData targetData = PlayerData.get(targetPlayer); 34 | targetData.tpManager.sendTPARequest(player.username, TPARequestType.TPAHERE); 35 | targetPlayer.world.playSoundAtEntity(null, targetPlayer, "note.celesta", 1, 2); 36 | targetPlayer.sendMessage(TextFormatting.YELLOW + player.username + TextFormatting.ORANGE + " has sent you a request to teleport to them."); 37 | targetPlayer.sendMessage(TextFormatting.LIME + "/tpyes " + TextFormatting.ORANGE + "to accept, " + TextFormatting.RED + "/tpno " + TextFormatting.ORANGE + "to deny."); 38 | } 39 | 40 | player.sendMessage(TextFormatting.YELLOW + "Sent a request to all players."); 41 | 42 | return 1; 43 | })); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/ContainerInvsee.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | import net.minecraft.core.entity.player.Player; 4 | import net.minecraft.core.item.ItemStack; 5 | import net.minecraft.core.player.inventory.container.Container; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | public class ContainerInvsee implements Container { 9 | private final Player player; 10 | 11 | public ContainerInvsee(Player player) { 12 | this.player = player; 13 | } 14 | 15 | @Override 16 | public int getContainerSize() { 17 | return 36; 18 | } 19 | 20 | private int shiftIndex(int index) { 21 | if (index >= 27 && index < 36) { 22 | return index - 27; 23 | } else { 24 | return index + 9; 25 | } 26 | } 27 | 28 | @Override 29 | public @Nullable ItemStack getItem(int index) { 30 | int i = shiftIndex(index); 31 | return this.player.inventory.mainInventory[i]; 32 | } 33 | 34 | @Override 35 | public @Nullable ItemStack removeItem(int index, int takeAmount) { 36 | ItemStack item = this.getItem(index); 37 | if (item != null) { 38 | if (item.stackSize <= takeAmount) { 39 | this.setItem(index, null); 40 | this.setChanged(); 41 | return item; 42 | } else { 43 | ItemStack itemStack1 = item.splitStack(takeAmount); 44 | if (item.stackSize <= 0) { 45 | this.setItem(index, null); 46 | } 47 | 48 | this.setChanged(); 49 | return itemStack1; 50 | } 51 | } else { 52 | return null; 53 | } 54 | } 55 | 56 | @Override 57 | public void setItem(int index, @Nullable ItemStack itemStack) { 58 | if (itemStack != null && itemStack.stackSize > this.getMaxStackSize()) { 59 | itemStack.stackSize = this.getMaxStackSize(); 60 | } 61 | int i = shiftIndex(index); 62 | this.player.inventory.mainInventory[i] = itemStack; 63 | 64 | this.setChanged(); 65 | } 66 | 67 | @Override 68 | public String getNameTranslationKey() { 69 | return this.player.username; 70 | } 71 | 72 | @Override 73 | public int getMaxStackSize() { 74 | return 64; 75 | } 76 | 77 | @Override 78 | public void setChanged() {} 79 | 80 | @Override 81 | public boolean stillValid(Player player) { 82 | return true; 83 | } 84 | 85 | @Override 86 | public void sortContainer() {} 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/PayCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeInteger; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.net.command.CommandManager; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.net.command.TextFormatting; 11 | import net.minecraft.server.entity.player.PlayerServer; 12 | import wyspr.BTE.Essentials; 13 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 14 | 15 | @SuppressWarnings("ALL") public class PayCommand implements CommandManager.CommandRegistry { 16 | @Override 17 | public void register(CommandDispatcher commandDispatcher) { 18 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 19 | .literal("pay") 20 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.PayCommand) 21 | .then(ArgumentBuilderRequired 22 | .argument("player", ArgumentTypeUser.user()) 23 | .then(ArgumentBuilderRequired 24 | .argument("amount", ArgumentTypeInteger.integer(1)) 25 | .executes(context -> { 26 | CommandSource source = (CommandSource) context.getSource(); 27 | Player sender = source.getSender(); 28 | boolean senderIsAdmin = source.hasAdmin(); 29 | int amount = context.getArgument("amount", Integer.class); 30 | PlayerServer reciever = context.getArgument("player", PlayerServer.class); 31 | 32 | if (sender.score < amount && !senderIsAdmin) { 33 | sender.sendMessage(TextFormatting.RED + (TextFormatting.BOLD + "Insufficient funds!")); 34 | return 1; 35 | } 36 | 37 | sender.score -= amount; 38 | reciever.score += amount; 39 | sender.sendMessage( 40 | TextFormatting.ORANGE + "Paid " + 41 | TextFormatting.YELLOW + reciever.username + " " + 42 | TextFormatting.LIGHT_BLUE + amount + 43 | TextFormatting.ORANGE + " points." 44 | ); 45 | reciever.sendMessage( 46 | TextFormatting.YELLOW + sender.username + 47 | TextFormatting.ORANGE + " has paid you " + 48 | TextFormatting.LIGHT_BLUE + amount + 49 | TextFormatting.ORANGE + " points." 50 | ); 51 | 52 | return 1; 53 | })))); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/BackCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.context.CommandContext; 6 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.net.command.CommandManager; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.net.command.TextFormatting; 11 | import wyspr.BTE.Essentials; 12 | import wyspr.BTE.utils.PlayerData; 13 | import wyspr.BTE.utils.PlayerData.TPManager; 14 | import wyspr.BTE.utils.Teleport; 15 | import wyspr.BTE.utils.WorldPosition; 16 | 17 | @SuppressWarnings("ALL") public class BackCommand implements CommandManager.CommandRegistry { 18 | @Override 19 | public void register(CommandDispatcher commandDispatcher) { 20 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 21 | .literal("back") 22 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.BackCommand) 23 | .executes(this::command)); 24 | } 25 | 26 | private int command(CommandContext context) throws CommandSyntaxException { 27 | CommandSource source = (CommandSource) context.getSource(); 28 | boolean isAdmin = source.hasAdmin(); 29 | Player player = source.getSender(); 30 | TPManager playerData = PlayerData.get(player).tpManager; 31 | 32 | int cost = Essentials.BackCost; 33 | if (player.score < cost && !isAdmin) { 34 | player.sendMessage(TextFormatting.YELLOW + "You do not have enough points to use this command!"); 35 | player.sendMessage(TextFormatting.YELLOW + "You need " + TextFormatting.ORANGE + (cost - player.score) + TextFormatting.YELLOW + " more points!"); 36 | return 1; 37 | } 38 | 39 | if (playerData.canTP() || isAdmin) { 40 | if (playerData.atNewPos()) { 41 | WorldPosition lastPos = playerData.getLastPos(); 42 | 43 | playerData.updateBackPos(); 44 | 45 | if (Teleport.teleport(player, lastPos)) { 46 | player.sendMessage(TextFormatting.YELLOW + "Went back."); 47 | } 48 | } else { 49 | player.sendMessage(TextFormatting.YELLOW + "You have not moved!"); 50 | } 51 | 52 | } else { 53 | int cooldown = playerData.TPCooldown(); 54 | player.sendMessage(TextFormatting.YELLOW + "Teleport available in " + TextFormatting.ORANGE + cooldown + TextFormatting.YELLOW + " seconds."); 55 | } 56 | 57 | return 1; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/Warps.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | import com.google.common.reflect.TypeToken; 4 | import com.google.gson.Gson; 5 | import com.google.gson.GsonBuilder; 6 | import wyspr.BTE.Essentials; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.nio.charset.StandardCharsets; 11 | import java.nio.file.Files; 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Optional; 16 | import java.util.stream.Collectors; 17 | 18 | 19 | public class Warps { 20 | private static final File warpFile = Essentials.DATA_DIR.resolve("warps.json").toFile(); 21 | 22 | private static HashMap warps; 23 | 24 | static { 25 | if (!warpFile.exists()) { 26 | warps = new HashMap<>(); 27 | try { 28 | warpFile.createNewFile(); 29 | } catch (IOException e) { 30 | throw new RuntimeException(e); 31 | } 32 | } else { 33 | load(); 34 | } 35 | } 36 | 37 | public static void load() { 38 | Gson gson = new Gson(); 39 | try { 40 | String json = new String(Files.readAllBytes(warpFile.toPath()), StandardCharsets.UTF_8); 41 | warps = gson.fromJson(json, new TypeToken>() {}.getType()); 42 | if (warps == null) { 43 | warps = new HashMap<>(); 44 | } 45 | } catch (IOException e) { 46 | System.err.println("Error reading file: " + e.getMessage()); 47 | } 48 | } 49 | 50 | public static void importWarps(HashMap newWarps) { 51 | warps = newWarps; 52 | save(); 53 | } 54 | 55 | public static void save() { 56 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 57 | String json = gson.toJson(warps); 58 | try { 59 | Files.write(warpFile.toPath(), json.getBytes(StandardCharsets.UTF_8)); 60 | } catch (IOException e) { 61 | System.err.println("Error writing file: " + e.getMessage()); 62 | } 63 | } 64 | 65 | public static boolean addWarp(String name, WorldPosition position) { 66 | if (warps.containsKey(name)) { 67 | return false; 68 | } 69 | warps.put(name, position); 70 | return true; 71 | } 72 | 73 | public static boolean removeWarp(String name) { 74 | if (!warps.containsKey(name)) { 75 | return false; 76 | } 77 | warps.remove(name); 78 | return true; 79 | } 80 | 81 | public static Optional getWarp(String name) { 82 | return Optional.ofNullable(warps.get(name)); 83 | } 84 | 85 | public static List getWarps() { 86 | if (warps.isEmpty()) { 87 | return new ArrayList<>(); 88 | } 89 | 90 | return warps.keySet().stream().sorted().collect(Collectors.toList()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/gamemode/CreativeCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.gamemode; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import net.minecraft.core.player.gamemode.Gamemode; 13 | import net.minecraft.server.entity.player.PlayerServer; 14 | import wyspr.BTE.Essentials; 15 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 16 | 17 | import java.text.MessageFormat; 18 | 19 | @SuppressWarnings("ALL") public class CreativeCommand implements CommandManager.CommandRegistry { 20 | @Override 21 | public void register(CommandDispatcher commandDispatcher) { 22 | String[] literals = {"creative", "gmc"}; 23 | for (String literal : literals) { 24 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 25 | .literal(literal) 26 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.GamemodeCommand) 27 | .executes(this::noArg) 28 | .then(ArgumentBuilderRequired 29 | .argument("user", ArgumentTypeUser.user()) 30 | .requires(source -> ((CommandSource) source).hasAdmin()) 31 | .executes(this::playerArg))); 32 | } 33 | } 34 | 35 | private int noArg(CommandContext context) throws CommandSyntaxException { 36 | CommandSource source = (CommandSource) context.getSource(); 37 | Player player = source.getSender(); 38 | player.setGamemode(Gamemode.creative); 39 | player.sendMessage(TextFormatting.YELLOW + "Set own gamemode to " + TextFormatting.CYAN + "Creative"); 40 | return 0; 41 | } 42 | 43 | private int playerArg(CommandContext context) throws CommandSyntaxException { 44 | CommandSource source = (CommandSource) context.getSource(); 45 | Player player = source.getSender(); 46 | PlayerServer user = context.getArgument("user", PlayerServer.class); 47 | user.setGamemode(Gamemode.creative); 48 | player.sendMessage(MessageFormat.format( 49 | "{0}Set gamemode to {1}Creative{0} for " + TextFormatting.RESET + user.getDisplayName(), 50 | TextFormatting.YELLOW, 51 | TextFormatting.CYAN 52 | )); 53 | user.sendMessage(TextFormatting.YELLOW + "Your gamemode was set to " + TextFormatting.CYAN + "Creative"); 54 | return 0; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/gamemode/SurvivalCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.gamemode; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import net.minecraft.core.player.gamemode.Gamemode; 13 | import net.minecraft.server.entity.player.PlayerServer; 14 | import wyspr.BTE.Essentials; 15 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 16 | 17 | import java.text.MessageFormat; 18 | 19 | @SuppressWarnings("ALL") public class SurvivalCommand implements CommandManager.CommandRegistry { 20 | @Override 21 | public void register(CommandDispatcher commandDispatcher) { 22 | String[] literals = {"survival", "gms"}; 23 | for (String literal : literals) { 24 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 25 | .literal(literal) 26 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.GamemodeCommand) 27 | .executes(this::noArg) 28 | .then(ArgumentBuilderRequired 29 | .argument("user", ArgumentTypeUser.user()) 30 | .requires(source -> ((CommandSource) source).hasAdmin()) 31 | .executes(this::playerArg))); 32 | } 33 | } 34 | 35 | private int noArg(CommandContext context) throws CommandSyntaxException { 36 | CommandSource source = (CommandSource) context.getSource(); 37 | Player player = source.getSender(); 38 | player.setGamemode(Gamemode.survival); 39 | player.sendMessage(TextFormatting.YELLOW + "Set own gamemode to " + TextFormatting.CYAN + "Survival"); 40 | return 0; 41 | } 42 | 43 | private int playerArg(CommandContext context) throws CommandSyntaxException { 44 | CommandSource source = (CommandSource) context.getSource(); 45 | Player player = source.getSender(); 46 | PlayerServer user = context.getArgument("user", PlayerServer.class); 47 | user.setGamemode(Gamemode.survival); 48 | player.sendMessage(MessageFormat.format( 49 | "{0}Set gamemode to {1}Survival{0} for " + TextFormatting.RESET + user.getDisplayName(), 50 | TextFormatting.YELLOW, 51 | TextFormatting.CYAN 52 | )); 53 | user.sendMessage(TextFormatting.YELLOW + "Your gamemode was set to " + TextFormatting.CYAN + "Survival"); 54 | return 0; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/gamemode/SpectatorCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.gamemode; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import net.minecraft.core.player.gamemode.Gamemode; 13 | import net.minecraft.server.entity.player.PlayerServer; 14 | import wyspr.BTE.Essentials; 15 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 16 | 17 | import java.text.MessageFormat; 18 | 19 | @SuppressWarnings("ALL") public class SpectatorCommand implements CommandManager.CommandRegistry { 20 | @Override 21 | public void register(CommandDispatcher commandDispatcher) { 22 | String[] literals = {"spectator", "gmsp", "spec"}; 23 | for (String literal : literals) { 24 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 25 | .literal(literal) 26 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.GamemodeCommand) 27 | .executes(this::noArg) 28 | .then(ArgumentBuilderRequired 29 | .argument("user", ArgumentTypeUser.user()) 30 | .requires(source -> ((CommandSource) source).hasAdmin()) 31 | .executes(this::playerArg))); 32 | } 33 | } 34 | 35 | private int noArg(CommandContext context) throws CommandSyntaxException { 36 | CommandSource source = (CommandSource) context.getSource(); 37 | Player player = source.getSender(); 38 | player.setGamemode(Gamemode.spectator); 39 | player.sendMessage(TextFormatting.YELLOW + "Set own gamemode to " + TextFormatting.CYAN + "Spectator"); 40 | return 0; 41 | } 42 | 43 | private int playerArg(CommandContext context) throws CommandSyntaxException { 44 | CommandSource source = (CommandSource) context.getSource(); 45 | Player player = source.getSender(); 46 | PlayerServer user = context.getArgument("user", PlayerServer.class); 47 | user.setGamemode(Gamemode.spectator); 48 | player.sendMessage(MessageFormat.format( 49 | "{0}Set gamemode to {1}Spectator{0} for " + TextFormatting.RESET + user.getDisplayName(), 50 | TextFormatting.YELLOW, 51 | TextFormatting.CYAN 52 | )); 53 | user.sendMessage(TextFormatting.YELLOW + "Your gamemode was set to " + TextFormatting.CYAN + "Spectator"); 54 | return 0; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/SpawnCommandMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import net.minecraft.core.entity.player.Player; 6 | import net.minecraft.core.net.command.CommandSource; 7 | import net.minecraft.core.net.command.commands.CommandSpawn; 8 | import net.minecraft.core.net.command.exceptions.CommandExceptions; 9 | import net.minecraft.core.world.World; 10 | import net.minecraft.core.world.chunk.ChunkCoordinates; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Inject; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | import wyspr.BTE.Essentials; 16 | import wyspr.BTE.utils.PlayerData; 17 | 18 | @SuppressWarnings("ALL") 19 | @Mixin(value = CommandSpawn.class, remap = false) public class SpawnCommandMixin { 20 | 21 | /** 22 | * @author ipiepiepie 23 | * @reason override default spawn command, which accessible only for admins. 24 | *
25 | * source 26 | */ 27 | @Inject( 28 | method = "register", at = @At("HEAD"), cancellable = true 29 | ) 30 | private void setSpawn(CommandDispatcher dispatcher, CallbackInfo ci) { 31 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral.literal("spawn") 32 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.SpawnCommand) 33 | .executes(context -> { 34 | CommandSource source = (CommandSource) context.getSource(); 35 | Player sender = source.getSender(); 36 | World world = source.getWorld(0); 37 | ChunkCoordinates spawnCoordinates = world.getSpawnPoint(); 38 | if (sender == null) { 39 | throw CommandExceptions 40 | .notInWorld().create(); 41 | } else { 42 | if (sender.dimension != 0) { 43 | source.movePlayerToDimension(sender, 0); 44 | } 45 | 46 | PlayerData 47 | .get(sender).tpManager.updateBackPos(); 48 | 49 | source.teleportPlayerToPos( 50 | sender, 51 | (double) spawnCoordinates.x + (double) 0.5F, 52 | (double) ((float) world.findTopSolidBlock( 53 | spawnCoordinates.x, 54 | spawnCoordinates.z 55 | ) + sender.heightOffset), 56 | (double) spawnCoordinates.z + (double) 0.5F 57 | ); 58 | source.sendTranslatableMessage("command.commands.spawn.success", new Object[0]); 59 | return 1; 60 | } 61 | }) 62 | ); 63 | 64 | ci.cancel(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/PlayerServerMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.minecraft.core.entity.Entity; 4 | import net.minecraft.core.entity.player.Player; 5 | import net.minecraft.core.player.gamemode.Gamemode; 6 | import net.minecraft.core.util.helper.DamageType; 7 | import net.minecraft.core.world.World; 8 | import net.minecraft.server.entity.player.PlayerServer; 9 | import net.minecraft.server.player.PlayerListBox; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | import wyspr.BTE.Essentials; 15 | import wyspr.BTE.utils.PlayerData; 16 | 17 | @Mixin(value = PlayerServer.class, remap = false) public abstract class PlayerServerMixin extends Player { 18 | public PlayerServerMixin(World world) { 19 | super(world); 20 | PlayerData.set(this); 21 | } 22 | 23 | @Override 24 | public boolean isInLava() { 25 | if (PlayerData.get(this).godMode) return false; 26 | return super.isInLava(); 27 | } 28 | 29 | @Override 30 | public boolean isOnFire() { 31 | if (PlayerData.get(this).godMode) return false; 32 | return super.isOnFire(); 33 | } 34 | 35 | @Override 36 | public void onLivingUpdate() { 37 | super.onLivingUpdate(); 38 | PlayerData playerData = PlayerData.get(this); 39 | this.speed = playerData.speed; 40 | this.flySpeed = playerData.flySpeed; 41 | } 42 | 43 | @Override 44 | public void onDeath(Entity entityKilledBy) { 45 | if (Essentials.BackOnDeath) { 46 | PlayerData.get(this).tpManager.updateBackPos(); 47 | } 48 | super.onDeath(entityKilledBy); 49 | } 50 | 51 | @Override 52 | public boolean hurt(Entity attacker, int damage, DamageType type) { 53 | if (PlayerData.get(this).godMode) return false; 54 | return super.hurt(attacker, damage, type); 55 | } 56 | 57 | @Override 58 | public void lavaHurt() { 59 | if (PlayerData.get(this).godMode) return; 60 | super.lavaHurt(); 61 | } 62 | 63 | @Override 64 | public void fireHurt() { 65 | if (PlayerData.get(this).godMode) return; 66 | super.fireHurt(); 67 | } 68 | 69 | @Override 70 | public double getRidingHeight() { 71 | if (Essentials.HeadSit) { 72 | return super.getRidingHeight() + 0.5; 73 | } else { 74 | return super.getRidingHeight(); 75 | } 76 | } 77 | 78 | @Inject( 79 | method = "setGamemode", at = @At("HEAD") 80 | ) 81 | public void updateListOnGamemode(Gamemode newGamemode, CallbackInfo ci) { 82 | PlayerData playerData = PlayerData.get(this); 83 | if (playerData.vanished) { 84 | if (this.gamemode == Gamemode.spectator && newGamemode != Gamemode.spectator) { 85 | playerData.removeVanish(); 86 | PlayerListBox.updateList(); 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/FixCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import net.minecraft.core.entity.player.Player; 7 | import net.minecraft.core.item.ItemStack; 8 | import net.minecraft.core.net.command.CommandManager; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.net.command.TextFormatting; 11 | import net.minecraft.server.entity.player.PlayerServer; 12 | import wyspr.BTE.Essentials; 13 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 14 | 15 | @SuppressWarnings("ALL") public class FixCommand implements CommandManager.CommandRegistry { 16 | @Override 17 | public void register(CommandDispatcher commandDispatcher) { 18 | String[] literals = {"fix", "repair"}; 19 | for (String literal : literals) { 20 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 21 | .literal(literal) 22 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.FixCommand) 23 | .executes(context -> { 24 | CommandSource source = (CommandSource) context.getSource(); 25 | Player player = source.getSender(); 26 | ItemStack held = player.getHeldItem(); 27 | if (held.isItemStackDamageable()) { 28 | held.setMetadata(0); 29 | player.sendMessage(TextFormatting.LIGHT_BLUE + held.getDisplayName() + TextFormatting.YELLOW + " has been repaired."); 30 | } else { 31 | player.sendMessage(TextFormatting.LIGHT_BLUE + held.getDisplayName() + TextFormatting.YELLOW + " is not repairable."); 32 | } 33 | 34 | return 1; 35 | }) 36 | .then(ArgumentBuilderRequired 37 | .argument("player", ArgumentTypeUser.user()) 38 | .requires(source -> ((CommandSource) source).hasAdmin()) 39 | .executes(context -> { 40 | CommandSource source = (CommandSource) context.getSource(); 41 | Player player = source.getSender(); 42 | PlayerServer target = context.getArgument("player", PlayerServer.class); 43 | ItemStack held = target.getHeldItem(); 44 | if (held.isItemStackDamageable()) { 45 | held.setMetadata(0); 46 | player.sendMessage(TextFormatting.LIGHT_BLUE + held.getDisplayName() + TextFormatting.YELLOW + " has been repaired for " + TextFormatting.RESET + target.getDisplayName() + TextFormatting.YELLOW + "."); 47 | target.sendMessage(TextFormatting.LIGHT_BLUE + held.getDisplayName() + TextFormatting.YELLOW + " has been repaired."); 48 | } else { 49 | player.sendMessage(TextFormatting.LIGHT_BLUE + held.getDisplayName() + TextFormatting.YELLOW + " is not repairable."); 50 | } 51 | 52 | return 1; 53 | }))); 54 | 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/TPA/TPACommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.TPA; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.net.command.CommandManager; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.net.command.TextFormatting; 11 | import net.minecraft.server.entity.player.PlayerServer; 12 | import wyspr.BTE.Essentials; 13 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 14 | import wyspr.BTE.utils.PlayerData; 15 | import wyspr.BTE.utils.TPARequestType; 16 | 17 | @SuppressWarnings("ALL") public class TPACommand implements CommandManager.CommandRegistry { 18 | @Override 19 | public void register(CommandDispatcher commandDispatcher) { 20 | 21 | String[] literals = {"tpa", "tpask"}; 22 | for (String literal : literals) { 23 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 24 | .literal(literal) 25 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.TPACommand) 26 | .then(ArgumentBuilderRequired 27 | .argument("target", ArgumentTypeUser.user()) 28 | .executes(this::exec))); 29 | } 30 | } 31 | 32 | private int exec(CommandContext context) { 33 | CommandSource source = (CommandSource) context.getSource(); 34 | boolean isAdmin = source.hasAdmin(); 35 | PlayerServer target = context.getArgument("target", PlayerServer.class); 36 | Player player = source.getSender(); 37 | PlayerData targetData = PlayerData.get(target); 38 | PlayerData playerData = PlayerData.get(player); 39 | 40 | int cost = Essentials.TPACost; 41 | if (player.score < cost && !isAdmin) { 42 | player.sendMessage(TextFormatting.YELLOW + "You do not have enough points to use this command!"); 43 | player.sendMessage(TextFormatting.YELLOW + "You need " + TextFormatting.ORANGE + (cost - player.score) + TextFormatting.YELLOW + " more points!"); 44 | return 1; 45 | } 46 | 47 | boolean isOnlyRequest = targetData.tpManager.sendTPARequest( 48 | player.username, 49 | TPARequestType.TPA 50 | ); 51 | 52 | if (isOnlyRequest) { 53 | player.sendMessage(TextFormatting.YELLOW + "Sent a request to " + target.username); 54 | target.world.playSoundAtEntity(null, target, "note.celesta", 1, 2); 55 | target.sendMessage(TextFormatting.YELLOW + "" + player.username + TextFormatting.ORANGE + " has sent you a TP request."); 56 | target.sendMessage(TextFormatting.LIME + "/tpyes " + TextFormatting.ORANGE + "to accept, " + TextFormatting.RED + "/tpno " + TextFormatting.ORANGE + "to deny."); 57 | } else { 58 | player.sendMessage(TextFormatting.YELLOW + "You already have a pending request for " + target.username); 59 | } 60 | 61 | return 1; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.JsonParser; 5 | import net.minecraft.core.util.phys.HitResult; 6 | import net.minecraft.server.entity.player.PlayerServer; 7 | import wyspr.BTE.Essentials; 8 | 9 | import javax.annotation.Nullable; 10 | import java.io.BufferedReader; 11 | import java.io.InputStreamReader; 12 | import java.net.HttpURLConnection; 13 | import java.net.URL; 14 | import java.util.UUID; 15 | 16 | public class Utils { 17 | /** 18 | * Gets the UUID of a Minecraft user from their username using the Mojang API. 19 | * 20 | * @param username the Minecraft username 21 | * @return the UUID as a String, or null if not found or error 22 | */ 23 | public static String getUUIDFromName(String username) { 24 | try { 25 | URL url = new URL("https://api.mojang.com/users/profiles/minecraft/" + username); 26 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 27 | conn.setRequestMethod("GET"); 28 | 29 | // If the username doesn't exist, Mojang returns HTTP 204 30 | if (conn.getResponseCode() == HttpURLConnection.HTTP_NO_CONTENT) { 31 | return null; 32 | } 33 | 34 | BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); 35 | StringBuilder response = new StringBuilder(); 36 | String line; 37 | 38 | while ((line = reader.readLine()) != null) { 39 | response.append(line); 40 | } 41 | 42 | reader.close(); 43 | 44 | JsonObject json = JsonParser.parseString(response.toString()).getAsJsonObject(); 45 | return json.get("id").getAsString().replaceFirst( 46 | "(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{12})", 47 | "$1-$2-$3-$4-$5" 48 | ); 49 | } catch (Exception e) { 50 | Essentials.LOGGER.error("Failed to contact Mojang API", e); 51 | return null; 52 | } 53 | } 54 | 55 | public static @Nullable String getNameFromUUID(UUID uuid) { 56 | try { 57 | URL url = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid); 58 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 59 | conn.setRequestMethod("GET"); 60 | 61 | BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); 62 | StringBuilder response = new StringBuilder(); 63 | String line; 64 | 65 | while ((line = reader.readLine()) != null) { 66 | response.append(line); 67 | } 68 | 69 | reader.close(); 70 | 71 | JsonObject json = JsonParser.parseString(response.toString()).getAsJsonObject(); 72 | return json.get("name").getAsString(); 73 | 74 | } catch (Exception e) { 75 | Essentials.LOGGER.error("Failed to contact Mojang API", e); 76 | return null; 77 | } 78 | } 79 | 80 | public static HitResult rayCastFromPlayer(PlayerServer player, int distance) { 81 | return player.rayTrace(distance, 1, true, true); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/GodCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.net.command.CommandManager; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.net.command.TextFormatting; 11 | import net.minecraft.server.entity.player.PlayerServer; 12 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 13 | import wyspr.BTE.utils.PlayerData; 14 | 15 | @SuppressWarnings("ALL") public class GodCommand implements CommandManager.CommandRegistry { 16 | 17 | @Override 18 | public void register(CommandDispatcher dispatcher) { 19 | String[] literals = {"god", "godmode"}; 20 | for (String literal : literals) { 21 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 22 | .literal(literal) 23 | .requires(source -> ((CommandSource) source).hasAdmin()) 24 | .executes(this::noArg) 25 | .then(ArgumentBuilderRequired 26 | .argument("player", ArgumentTypeUser.user()) 27 | .executes(this::userArg))); 28 | } 29 | } 30 | 31 | private int noArg(CommandContext context) { 32 | CommandSource source = (CommandSource) context.getSource(); 33 | Player player = source.getSender(); 34 | boolean isGodMode = PlayerData 35 | .get(player) 36 | .toggleGodMode(); 37 | 38 | if (isGodMode) { 39 | player.sendMessage( 40 | TextFormatting.YELLOW + "God mode " + 41 | TextFormatting.LIME + "on" 42 | ); 43 | } else { 44 | player.sendMessage( 45 | TextFormatting.YELLOW + "God mode " + 46 | TextFormatting.RED + "off" 47 | ); 48 | } 49 | 50 | return 1; 51 | } 52 | 53 | private int userArg(CommandContext context) { 54 | CommandSource source = (CommandSource) context.getSource(); 55 | Player player = source.getSender(); 56 | PlayerServer target = context.getArgument("player", PlayerServer.class); 57 | boolean isGodMode = PlayerData 58 | .get(target) 59 | .toggleGodMode(); 60 | 61 | if (isGodMode) { 62 | player.sendMessage( 63 | TextFormatting.YELLOW + "God mode " + 64 | TextFormatting.LIME + "on " + 65 | TextFormatting.YELLOW + "for " + 66 | TextFormatting.RESET + target.getDisplayName() 67 | ); 68 | target.sendMessage( 69 | TextFormatting.YELLOW + "God mode " + 70 | TextFormatting.LIME + "on" 71 | ); 72 | } else { 73 | player.sendMessage( 74 | TextFormatting.YELLOW + "God mode " + 75 | TextFormatting.RED + "off " + 76 | TextFormatting.YELLOW + "for " + 77 | TextFormatting.RESET + target.getDisplayName() 78 | ); 79 | target.sendMessage( 80 | TextFormatting.YELLOW + "God mode " + 81 | TextFormatting.RED + "off" 82 | ); 83 | } 84 | 85 | return 1; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/warp/WarpCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.warp; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import wyspr.BTE.Essentials; 13 | import wyspr.BTE.commands.arguments.ArgumentTypeWarp; 14 | import wyspr.BTE.utils.PlayerData; 15 | import wyspr.BTE.utils.PlayerData.TPManager; 16 | import wyspr.BTE.utils.Teleport; 17 | import wyspr.BTE.utils.Warps; 18 | import wyspr.BTE.utils.WorldPosition; 19 | 20 | import java.util.Optional; 21 | 22 | @SuppressWarnings("ALL") public class WarpCommand implements CommandManager.CommandRegistry { 23 | @Override 24 | public void register(CommandDispatcher commandDispatcher) { 25 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 26 | .literal("warp") 27 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.WarpCommand) 28 | .then(ArgumentBuilderRequired 29 | .argument("target", ArgumentTypeWarp.warp()) 30 | .executes(this::exec))); 31 | } 32 | 33 | private int exec(CommandContext context) throws CommandSyntaxException { 34 | CommandSource source = (CommandSource) context.getSource(); 35 | Player player = source.getSender(); 36 | TPManager playerTPM = PlayerData.get(player).tpManager; 37 | boolean isAdmin = source.hasAdmin(); 38 | String target = context.getArgument("target", String.class); 39 | 40 | Optional warp = Warps.getWarp(target); 41 | 42 | if (!warp.isPresent()) { 43 | player.sendMessage(TextFormatting.ORANGE + "There is no warp named: " + TextFormatting.YELLOW + target); 44 | return 1; 45 | } 46 | 47 | int cost = Essentials.WarpCost; 48 | if (player.score < cost && !isAdmin) { 49 | player.sendMessage(TextFormatting.YELLOW + "You do not have enough points to use this command!"); 50 | player.sendMessage(TextFormatting.YELLOW + "You need " + TextFormatting.ORANGE + (cost - player.score) + TextFormatting.YELLOW + " more points!"); 51 | return 1; 52 | } 53 | 54 | if (playerTPM.canTP() || isAdmin) { 55 | playerTPM.updateBackPos(); 56 | WorldPosition warpPos = warp.get(); 57 | if (Teleport.teleport(player, warpPos)) { 58 | player.sendMessage(TextFormatting.YELLOW + "Teleported to " + TextFormatting.ORANGE + target); 59 | } 60 | } else { 61 | int waitTime = playerTPM.TPCooldown(); 62 | player.sendMessage(TextFormatting.YELLOW + "Teleport available in " + TextFormatting.ORANGE + waitTime + TextFormatting.YELLOW + " seconds."); 63 | } 64 | 65 | return 1; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/home/HomesCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.home; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import net.minecraft.server.entity.player.PlayerServer; 13 | import wyspr.BTE.Essentials; 14 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 15 | import wyspr.BTE.utils.PlayerData; 16 | 17 | import java.util.List; 18 | 19 | @SuppressWarnings("ALL") public class HomesCommand implements CommandManager.CommandRegistry { 20 | @Override 21 | public void register(CommandDispatcher commandDispatcher) { 22 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 23 | .literal("homes") 24 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.HomeCommand) 25 | .executes(this::noArg) 26 | .then(ArgumentBuilderRequired 27 | .argument("player", ArgumentTypeUser.user()) 28 | .requires(source -> ((CommandSource) source).hasAdmin()) 29 | .executes(this::playerArg))); 30 | } 31 | 32 | private int noArg(CommandContext context) throws CommandSyntaxException { 33 | CommandSource source = (CommandSource) context.getSource(); 34 | boolean isAdmin = source.hasAdmin(); 35 | Player player = source.getSender(); 36 | PlayerData playerData = PlayerData.get(player); 37 | List homes = playerData.homes.getHomesList(); 38 | 39 | if (homes.isEmpty()) { 40 | player.sendMessage(TextFormatting.ORANGE + "You do not have any homes!"); 41 | player.sendMessage(TextFormatting.ORANGE + "Set a home with: §3/sethome [name]"); 42 | return 1; 43 | } 44 | 45 | String homesString = String.join(", ", homes); 46 | player.sendMessage(TextFormatting.ORANGE + "Homes: " + TextFormatting.YELLOW + homesString); 47 | 48 | return 1; 49 | } 50 | 51 | private int playerArg(CommandContext context) throws CommandSyntaxException { 52 | CommandSource source = (CommandSource) context.getSource(); 53 | Player player = source.getSender(); 54 | Player target = context.getArgument("player", PlayerServer.class); 55 | PlayerData playerData = PlayerData.get(target); 56 | List homes = playerData.homes.getHomesList(); 57 | 58 | if (homes.isEmpty()) { 59 | player.sendMessage(TextFormatting.ORANGE + "" + target.nickname + " does not have any homes!"); 60 | return 1; 61 | } 62 | 63 | String homesString = String.join(", ", homes); 64 | player.sendMessage(TextFormatting.ORANGE + "Homes: " + TextFormatting.YELLOW + homesString); 65 | 66 | return 1; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/RTPCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | 4 | import com.mojang.brigadier.CommandDispatcher; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import net.minecraft.core.entity.player.Player; 7 | import net.minecraft.core.net.command.CommandManager; 8 | import net.minecraft.core.net.command.CommandSource; 9 | import net.minecraft.core.net.command.TextFormatting; 10 | import wyspr.BTE.Essentials; 11 | import wyspr.BTE.utils.PlayerData; 12 | import wyspr.BTE.utils.PlayerData.TPManager; 13 | import wyspr.BTE.utils.Teleport; 14 | 15 | import java.util.Random; 16 | 17 | @SuppressWarnings("ALL") public class RTPCommand implements CommandManager.CommandRegistry { 18 | Random r = new Random(); 19 | 20 | @Override 21 | public void register(CommandDispatcher commandDispatcher) { 22 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 23 | .literal("rtp") 24 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.RTPCommand) 25 | .executes(context -> { 26 | CommandSource source = (CommandSource) context.getSource(); 27 | boolean isAdmin = source.hasAdmin(); 28 | Player player = source.getSender(); 29 | TPManager playerTPM = PlayerData.get(player).tpManager; 30 | 31 | int cost = Essentials.RTPCost; 32 | if (player.score < cost && !isAdmin) { 33 | player.sendMessage(TextFormatting.YELLOW + "You do not have enough points to use this command!"); 34 | player.sendMessage( 35 | TextFormatting.YELLOW + "You need " + 36 | TextFormatting.ORANGE + (cost - player.score) + 37 | TextFormatting.YELLOW + " more points!" 38 | ); 39 | return 1; 40 | } 41 | if (player.dimension != 0) { 42 | player.sendMessage(TextFormatting.YELLOW + "You may only use this in the overworld!"); 43 | return 1; 44 | } 45 | if (!playerTPM.canTP() && !isAdmin) { 46 | int waitTime = playerTPM.TPCooldown(); 47 | player.sendMessage( 48 | TextFormatting.YELLOW + "Teleport available in " + 49 | TextFormatting.ORANGE + waitTime + 50 | TextFormatting.YELLOW + " seconds." 51 | ); 52 | return 1; 53 | } 54 | 55 | int min = Essentials.RTPMin; 56 | int max = Essentials.RTPMax; 57 | int randX = (int) (r.nextDouble() * (max - min) + min); 58 | int randZ = (int) (r.nextDouble() * (max - min) + min); 59 | 60 | playerTPM.updateBackPos(); 61 | 62 | if (Teleport.teleport(player, randX, 256, randZ, player.dimension)) { 63 | player.sendMessage( 64 | TextFormatting.YELLOW + "Teleported! " + 65 | TextFormatting.BOLD + "Should you get stuck, rejoin." 66 | ); 67 | 68 | player.score -= Essentials.RTPCost; 69 | 70 | player.fireImmuneTicks = 200; 71 | player.onGround = false; 72 | player.maxHurtTime = 200; 73 | player.hurtTime = 200; 74 | player.airSupply = 1000; 75 | player.fallDistance = -1000; 76 | } 77 | 78 | return 1; 79 | })); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/TPA/TPAHereCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.TPA; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import net.minecraft.server.entity.player.PlayerServer; 13 | import wyspr.BTE.Essentials; 14 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 15 | import wyspr.BTE.utils.PlayerData; 16 | import wyspr.BTE.utils.TPARequestType; 17 | 18 | @SuppressWarnings("ALL") public class TPAHereCommand implements CommandManager.CommandRegistry { 19 | @Override 20 | public void register(CommandDispatcher commandDispatcher) { 21 | String[] literals = {"tphere", "tph", "tpahere"}; 22 | for (String literal : literals) { 23 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 24 | .literal(literal) 25 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.TPACommand) 26 | .then(ArgumentBuilderRequired 27 | .argument("player", ArgumentTypeUser.user()) 28 | .executes(this::exec))); 29 | } 30 | } 31 | 32 | private int exec(CommandContext context) throws CommandSyntaxException { 33 | CommandSource source = (CommandSource) context.getSource(); 34 | boolean isAdmin = source.hasAdmin(); 35 | PlayerServer target = context.getArgument("player", PlayerServer.class); 36 | Player player = source.getSender(); 37 | PlayerData targetData = PlayerData.get(target); 38 | PlayerData playerData = PlayerData.get(player); 39 | 40 | int cost = Essentials.TPACost; 41 | if (player.score < cost && !isAdmin) { 42 | player.sendMessage(TextFormatting.YELLOW + "You do not have enough points to use this command!"); 43 | player.sendMessage(TextFormatting.YELLOW + "You need " + TextFormatting.ORANGE + (cost - player.score) + TextFormatting.YELLOW + " more points!"); 44 | return 1; 45 | } 46 | 47 | boolean isOnlyRequest = targetData.tpManager.sendTPARequest( 48 | player.username, 49 | TPARequestType.TPAHERE 50 | ); 51 | 52 | if (isOnlyRequest) { 53 | player.sendMessage(TextFormatting.YELLOW + "Sent a request to " + target.getDisplayName()); 54 | target.world.playSoundAtEntity(null, target, "note.celesta", 1, 2); 55 | target.sendMessage(TextFormatting.YELLOW + "" + player.username + TextFormatting.ORANGE + " has sent you a request to teleport to them."); 56 | target.sendMessage(TextFormatting.LIME + "/tpyes " + TextFormatting.ORANGE + "to accept, " + TextFormatting.RED + "/tpno " + TextFormatting.ORANGE + "to deny."); 57 | } else { 58 | player.sendMessage(TextFormatting.YELLOW + "You already have a pending request for " + target); 59 | } 60 | 61 | return 1; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/arguments/ArgumentTypeHome.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.arguments; 2 | 3 | import com.mojang.brigadier.StringReader; 4 | import com.mojang.brigadier.arguments.ArgumentType; 5 | import com.mojang.brigadier.context.CommandContext; 6 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 7 | import com.mojang.brigadier.suggestion.Suggestions; 8 | import com.mojang.brigadier.suggestion.SuggestionsBuilder; 9 | import net.minecraft.core.entity.player.Player; 10 | import net.minecraft.server.entity.player.PlayerServer; 11 | import net.minecraft.server.net.command.ServerCommandSource; 12 | import wyspr.BTE.utils.PlayerData; 13 | 14 | import java.util.Arrays; 15 | import java.util.Collection; 16 | import java.util.List; 17 | import java.util.concurrent.CompletableFuture; 18 | 19 | public class ArgumentTypeHome implements ArgumentType { 20 | private static final List EXAMPLES = Arrays.asList("home", "base", "mobspawner"); 21 | private final HomesType type; 22 | 23 | private ArgumentTypeHome(HomesType type) { 24 | this.type = type; 25 | } 26 | 27 | public static ArgumentType ownHomes() { 28 | return new ArgumentTypeHome(HomesType.OWN); 29 | } 30 | 31 | public static ArgumentType othersHomes() { 32 | return new ArgumentTypeHome(HomesType.OTHERS); 33 | } 34 | 35 | public String parse(StringReader reader) throws CommandSyntaxException { 36 | return reader.readString(); 37 | } 38 | 39 | public String parse(StringReader reader, S source) throws CommandSyntaxException { 40 | final String input = reader.readString(); 41 | List homes; 42 | if (type== HomesType.OWN) { 43 | Player sender = ((ServerCommandSource) source).getSender(); 44 | PlayerData playerData = PlayerData.get(sender); 45 | homes = playerData.homes.getHomesList(); 46 | } else { 47 | return input; 48 | } 49 | 50 | for (String home : homes) { 51 | if (home.equalsIgnoreCase(input)) { 52 | return input; 53 | } 54 | } 55 | throw new CommandSyntaxException( 56 | CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), 57 | () -> "Failed to find Home: " + input 58 | ); 59 | } 60 | 61 | public CompletableFuture listSuggestions( 62 | CommandContext context, 63 | SuggestionsBuilder builder 64 | ) 65 | { 66 | Player sender = ((ServerCommandSource) context.getSource()).getSender(); 67 | PlayerData playerData; 68 | 69 | if (type == HomesType.OTHERS) { 70 | Player target = context.getArgument("player", PlayerServer.class); 71 | playerData = PlayerData.get(target); 72 | } else { 73 | playerData = PlayerData.get(sender); 74 | } 75 | 76 | List homes = playerData.homes.getHomesList(); 77 | 78 | for (String home : homes) { 79 | if (home.startsWith(builder.getRemaining()) || builder.getRemaining().isEmpty()) { 80 | builder.suggest(home); 81 | } 82 | } 83 | 84 | return builder.buildFuture(); 85 | } 86 | 87 | public Collection getExamples() { 88 | return EXAMPLES; 89 | } 90 | 91 | private enum HomesType { 92 | OWN, OTHERS 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/SmiteCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.EntityLightning; 9 | import net.minecraft.core.entity.player.Player; 10 | import net.minecraft.core.net.command.CommandManager; 11 | import net.minecraft.core.net.command.CommandSource; 12 | import net.minecraft.core.net.command.TextFormatting; 13 | import net.minecraft.core.util.phys.HitResult; 14 | import net.minecraft.server.entity.player.PlayerServer; 15 | import org.jetbrains.annotations.NotNull; 16 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 17 | import wyspr.BTE.utils.Utils; 18 | 19 | @SuppressWarnings("ALL") public class SmiteCommand implements CommandManager.CommandRegistry { 20 | @Override 21 | public void register(CommandDispatcher dispatcher) { 22 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 23 | .literal("smite") 24 | .requires(source -> ((CommandSource) source).hasAdmin()) 25 | .executes(this::noArg) 26 | .then(ArgumentBuilderRequired 27 | .argument("player", ArgumentTypeUser.user()) 28 | .executes(this::userArg))); 29 | } 30 | 31 | private @NotNull int noArg(CommandContext context) throws CommandSyntaxException { 32 | CommandSource source = (CommandSource) context.getSource(); 33 | Player player = source.getSender(); 34 | HitResult hitresult = Utils.rayCastFromPlayer((PlayerServer) player, 100); 35 | 36 | if (hitresult == null) { 37 | player.sendMessage(TextFormatting.ORANGE + "No block in sight"); 38 | } else { 39 | player.world.addWeatherEffect(new EntityLightning( 40 | player.world, 41 | hitresult.x, 42 | hitresult.y, 43 | hitresult.z 44 | )); 45 | player.sendMessage(TextFormatting.YELLOW + "Struck at: " + 46 | TextFormatting.LIGHT_BLUE + String.format( 47 | "%d, %d, %d", 48 | hitresult.x, 49 | hitresult.y, 50 | hitresult.z 51 | )); 52 | } 53 | 54 | return 1; 55 | } 56 | 57 | private @NotNull int userArg(CommandContext context) throws CommandSyntaxException { 58 | CommandSource source = (CommandSource) context.getSource(); 59 | Player player = source.getSender(); 60 | PlayerServer target = context.getArgument("player", PlayerServer.class); 61 | 62 | target.world.addWeatherEffect(new EntityLightning( 63 | target.world, 64 | target.x, 65 | target.y, 66 | target.z 67 | )); 68 | player.sendMessage(TextFormatting.YELLOW + "Struck " + 69 | TextFormatting.RESET + target.getDisplayName() + 70 | TextFormatting.YELLOW + " at: " + 71 | TextFormatting.LIGHT_BLUE + String.format( 72 | "%d, %d, %d", 73 | (int)target.x, 74 | (int)target.y, 75 | (int)target.z 76 | ) + 77 | TextFormatting.YELLOW + " in " + 78 | TextFormatting.LIGHT_BLUE + target.world.dimension.getTranslatedName() 79 | ); 80 | 81 | return 1; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/home/SethomeCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.home; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeString; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import com.mojang.brigadier.context.CommandContext; 8 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 9 | import net.minecraft.core.entity.player.Player; 10 | import net.minecraft.core.net.command.CommandManager; 11 | import net.minecraft.core.net.command.CommandSource; 12 | import net.minecraft.core.net.command.TextFormatting; 13 | import wyspr.BTE.Essentials; 14 | import wyspr.BTE.utils.PlayerData; 15 | 16 | @SuppressWarnings("ALL") public class SethomeCommand implements CommandManager.CommandRegistry { 17 | @Override 18 | public void register(CommandDispatcher commandDispatcher) { 19 | String[] literals = {"addhome", "sethome"}; 20 | for (String literal : literals) { 21 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 22 | .literal(literal) 23 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.HomeCommand) 24 | .executes(this::noArg) 25 | .then(ArgumentBuilderRequired 26 | .argument("homeName", ArgumentTypeString.string()) 27 | .executes(this::homeArg))); 28 | } 29 | } 30 | 31 | private int noArg(CommandContext context) throws CommandSyntaxException { 32 | CommandSource source = (CommandSource) context.getSource(); 33 | boolean isAdmin = source.hasAdmin(); 34 | Player player = source.getSender(); 35 | PlayerData playerData = PlayerData.get(player); 36 | int homesAmount = playerData.homes.getHomesAmount(); 37 | 38 | return setHome(homesAmount, player, playerData, "home"); 39 | } 40 | 41 | private int homeArg(CommandContext context) throws CommandSyntaxException { 42 | CommandSource source = (CommandSource) context.getSource(); 43 | boolean isAdmin = source.hasAdmin(); 44 | Player player = source.getSender(); 45 | PlayerData playerData = PlayerData.get(player); 46 | int homesAmount = playerData.homes.getHomesAmount(); 47 | String homeName = context.getArgument("homeName", String.class); 48 | 49 | if (homeName.equals("bed")) { 50 | player.sendMessage(TextFormatting.YELLOW + "This home is reserved for your bed."); 51 | return 1; 52 | } 53 | 54 | return setHome(homesAmount, player, playerData, homeName); 55 | } 56 | 57 | private static Integer setHome( 58 | int homesAmount, Player player, PlayerData playerData, String 59 | homeName 60 | ) 61 | { 62 | if (homesAmount == Essentials.MaxHomes) { 63 | player.sendMessage(TextFormatting.YELLOW + "You've reached the max amount of homes!"); 64 | return 1; 65 | } 66 | 67 | if (playerData.homes.setHome(player, homeName)) { 68 | player.sendMessage(TextFormatting.YELLOW + "Created home: " + TextFormatting.ORANGE + homeName); 69 | } else { 70 | player.sendMessage(TextFormatting.YELLOW + "You already have a home named: " + TextFormatting.ORANGE + homeName); 71 | player.sendMessage(TextFormatting.YELLOW + "Use: " + TextFormatting.LIGHT_BLUE + "/delhome " + homeName + TextFormatting.YELLOW + " to remove"); 72 | } 73 | return 1; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/TntCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeInteger; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import com.mojang.brigadier.context.CommandContext; 8 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 9 | import net.minecraft.core.entity.Entity; 10 | import net.minecraft.core.entity.EntityPrimedTNT; 11 | import net.minecraft.core.entity.player.Player; 12 | import net.minecraft.core.net.command.CommandManager; 13 | import net.minecraft.core.net.command.CommandSource; 14 | import net.minecraft.core.world.World; 15 | import org.jetbrains.annotations.NotNull; 16 | 17 | @SuppressWarnings("ALL") public class TntCommand implements CommandManager.CommandRegistry { 18 | @Override 19 | public void register(CommandDispatcher dispatcher) { 20 | String[] literals = {"tnt", "grenade"}; 21 | for (String literal : literals) { 22 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 23 | .literal(literal) 24 | .requires(source -> ((CommandSource) source).hasAdmin()) 25 | .executes(this::noArg) 26 | .then(ArgumentBuilderRequired 27 | .argument("velocity", ArgumentTypeInteger.integer(0)) 28 | .executes(this::velArg))); 29 | } 30 | } 31 | 32 | private @NotNull int noArg(CommandContext context) throws CommandSyntaxException { 33 | CommandSource source = (CommandSource) context.getSource(); 34 | Player player = source.getSender(); 35 | 36 | DirectionalTNT tnt = new DirectionalTNT( 37 | player.world, 38 | player.x, 39 | player.y + 1, 40 | player.z, 41 | player.xRot, 42 | player.yRot, 43 | 2 44 | ); 45 | 46 | player.world.entityJoinedWorld(tnt); 47 | player.world.playSoundAtEntity((Entity) null, tnt, "tile.tnt.fuse", 1.0F, 1.0F); 48 | 49 | return 1; 50 | } 51 | 52 | private @NotNull int velArg(CommandContext context) throws CommandSyntaxException { 53 | CommandSource source = (CommandSource) context.getSource(); 54 | Player player = source.getSender(); 55 | int velocity = context.getArgument("velocity", Integer.class); 56 | 57 | DirectionalTNT tnt = new DirectionalTNT( 58 | player.world, 59 | player.x, 60 | player.y + 1, 61 | player.z, 62 | player.xRot, 63 | player.yRot, 64 | velocity 65 | ); 66 | 67 | player.world.entityJoinedWorld(tnt); 68 | player.world.playSoundAtEntity((Entity) null, tnt, "tile.tnt.fuse", 1.0F, 1.0F); 69 | 70 | return 1; 71 | } 72 | 73 | private class DirectionalTNT extends EntityPrimedTNT { 74 | public DirectionalTNT( 75 | World world, 76 | double x, 77 | double y, 78 | double z, 79 | float pitch, 80 | float yaw, 81 | float force 82 | ) 83 | { 84 | super(world); 85 | this.setPos(x, y, z); 86 | 87 | float pitchRad = (float) Math.toRadians(pitch); 88 | float yawRad = (float) Math.toRadians(yaw); 89 | 90 | this.xd = -Math.sin(yawRad) * Math.cos(pitchRad) * force; 91 | this.zd = Math.cos(yawRad) * Math.cos(pitchRad) * force; 92 | this.yd = -Math.sin(pitchRad) * force + 0.3; 93 | 94 | this.fuse = 80; 95 | 96 | this.xo = x; 97 | this.yo = y; 98 | this.zo = z; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/SudoCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | 4 | import com.mojang.brigadier.CommandDispatcher; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import com.mojang.brigadier.context.CommandContext; 8 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 9 | import net.minecraft.core.entity.player.Player; 10 | import net.minecraft.core.net.command.CommandManager; 11 | import net.minecraft.core.net.command.CommandSource; 12 | import net.minecraft.core.net.command.TextFormatting; 13 | import net.minecraft.core.net.packet.PacketChat; 14 | import net.minecraft.server.MinecraftServer; 15 | import net.minecraft.server.entity.player.PlayerServer; 16 | import net.minecraft.server.net.command.ServerCommandSource; 17 | import wyspr.BTE.commands.arguments.ArgumentTypeCommand; 18 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 19 | 20 | @SuppressWarnings("ALL") public class SudoCommand implements CommandManager.CommandRegistry { 21 | @Override 22 | public void register(CommandDispatcher commandDispatcher) { 23 | String[] literals = {"sudo", "doas"}; 24 | for (String literal : literals) { 25 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 26 | .literal(literal) 27 | .requires(source -> ((CommandSource) source).hasAdmin()) 28 | .then(ArgumentBuilderRequired 29 | .argument("player", ArgumentTypeUser.user()) 30 | .then(ArgumentBuilderRequired 31 | .argument("command", ArgumentTypeCommand.commands()) 32 | .executes(this::exec)))); 33 | } 34 | } 35 | 36 | private int exec(CommandContext context) { 37 | CommandSource source = (CommandSource) context.getSource(); 38 | Player sender = source.getSender(); 39 | PlayerServer player = context.getArgument("player", PlayerServer.class); 40 | String command = context.getArgument("command", String.class); 41 | 42 | if (!command.startsWith("/")) { 43 | player.playerNetServerHandler.handleChat(new PacketChat(command)); 44 | sender.sendMessage(( 45 | TextFormatting.YELLOW + "Sent \"" + 46 | TextFormatting.LIGHT_BLUE + command + 47 | TextFormatting.YELLOW + "\" as " + 48 | TextFormatting.RESET + player.getDisplayName() 49 | )); 50 | return 1; 51 | } 52 | 53 | MinecraftServer mcServer = MinecraftServer.getInstance(); 54 | ServerCommandSource playerCommandSource = new ServerCommandSource(mcServer, player); 55 | CommandDispatcher dispatcher = mcServer 56 | .getDimensionWorld(player.dimension) 57 | .getCommandManager() 58 | .getDispatcher(); 59 | 60 | try { 61 | command = command.substring(1); 62 | dispatcher.execute(command, playerCommandSource); 63 | sender.sendMessage(( 64 | TextFormatting.YELLOW + "Ran " + 65 | TextFormatting.LIGHT_BLUE + "/" + command + 66 | TextFormatting.YELLOW + " as " + 67 | TextFormatting.RESET + player.getDisplayName() 68 | )); 69 | } catch (CommandSyntaxException e) { 70 | sender.sendMessage(( 71 | TextFormatting.ORANGE + "Failed to run " + 72 | TextFormatting.LIGHT_BLUE + "/" + command + 73 | TextFormatting.ORANGE + " as " + 74 | TextFormatting.RESET + player.getDisplayName() 75 | )); 76 | sender.sendMessage(( 77 | TextFormatting.RED + "Error: " + 78 | TextFormatting.WHITE + e.getMessage() 79 | )); 80 | } 81 | 82 | return 1; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/TPA/TPDenyCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.TPA; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import com.mojang.brigadier.tree.CommandNode; 9 | import net.minecraft.core.entity.player.Player; 10 | import net.minecraft.core.net.command.CommandManager; 11 | import net.minecraft.core.net.command.CommandSource; 12 | import net.minecraft.core.net.command.TextFormatting; 13 | import net.minecraft.server.entity.player.PlayerServer; 14 | import org.apache.commons.lang3.tuple.Pair; 15 | import wyspr.BTE.Essentials; 16 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 17 | import wyspr.BTE.utils.PlayerData; 18 | import wyspr.BTE.utils.PlayerData.TPManager; 19 | import wyspr.BTE.utils.TPARequestType; 20 | 21 | @SuppressWarnings("ALL") public class TPDenyCommand implements CommandManager.CommandRegistry { 22 | @Override 23 | public void register(CommandDispatcher commandDispatcher) { 24 | String[] literals = {"tpno", "tn", "tpdeny"}; 25 | for (String literal : literals) { 26 | CommandNode command 27 | = commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 28 | .literal(literal) 29 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.TPACommand) 30 | .executes(this::noArg) 31 | .then(ArgumentBuilderRequired 32 | .argument("target", ArgumentTypeUser.user()) 33 | .executes(this::playerArg))); 34 | } 35 | } 36 | 37 | private int noArg(CommandContext context) throws CommandSyntaxException { 38 | CommandSource source = (CommandSource) context.getSource(); 39 | boolean isAdmin = source.hasAdmin(); 40 | Player player = source.getSender(); 41 | TPManager playerTPM = PlayerData.get(player).tpManager; 42 | 43 | if (playerTPM.hasNoRequests()) { 44 | player.sendMessage(TextFormatting.YELLOW + "You don't have any requests."); 45 | return 1; 46 | } 47 | 48 | Pair requestPair = playerTPM.getNewestRequest(); 49 | String targetUsername = requestPair.getKey(); 50 | 51 | playerTPM.removeRequest(targetUsername); 52 | 53 | player.sendMessage(TextFormatting.ORANGE + "Denied TP request from " + TextFormatting.YELLOW + targetUsername); 54 | 55 | return 1; 56 | } 57 | 58 | private int playerArg(CommandContext context) throws CommandSyntaxException { 59 | CommandSource source = (CommandSource) context.getSource(); 60 | boolean isAdmin = source.hasAdmin(); 61 | PlayerServer target = context.getArgument("target", PlayerServer.class); 62 | Player player = source.getSender(); 63 | PlayerData targetData = PlayerData.get(target); 64 | TPManager playerTPM = PlayerData.get(player).tpManager; 65 | boolean targetNotAdmin = !((PlayerServer) target).isOperator(); 66 | 67 | if (playerTPM.hasNoRequests()) { 68 | player.sendMessage(TextFormatting.YELLOW + "You don't have any requests."); 69 | return 1; 70 | } 71 | 72 | if (!playerTPM.hasRequestFrom(target.username)) { 73 | player.sendMessage(TextFormatting.ORANGE + "You don't have a request from " + TextFormatting.YELLOW + target); 74 | return 1; 75 | } 76 | 77 | playerTPM.removeRequest(target.username); 78 | 79 | player.sendMessage(TextFormatting.ORANGE + "Denied TP request from " + TextFormatting.YELLOW + target.username); 80 | 81 | return 1; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/home/DelhomeCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.home; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import net.minecraft.server.entity.player.PlayerServer; 13 | import wyspr.BTE.Essentials; 14 | import wyspr.BTE.commands.arguments.ArgumentTypeHome; 15 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 16 | import wyspr.BTE.utils.PlayerData; 17 | 18 | @SuppressWarnings("ALL") public class DelhomeCommand implements CommandManager.CommandRegistry { 19 | @Override 20 | public void register(CommandDispatcher commandDispatcher) { 21 | String[] literals = {"delhome", "rmhome"}; 22 | for (String literal : literals) { 23 | commandDispatcher.register((ArgumentBuilderLiteral) (ArgumentBuilderLiteral.literal(literal)) 24 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.HomeCommand) 25 | .then(ArgumentBuilderRequired 26 | .argument("home", ArgumentTypeHome.ownHomes()) 27 | .executes(this::homeArg)) 28 | .then(ArgumentBuilderRequired 29 | .argument("player", ArgumentTypeUser.user()) 30 | .requires(source -> ((CommandSource) source).hasAdmin()) 31 | .then(ArgumentBuilderRequired 32 | .argument("home", ArgumentTypeHome.othersHomes()) 33 | .executes(this::playerHomeArg))) 34 | ); 35 | } 36 | } 37 | 38 | 39 | private int homeArg(CommandContext context) throws CommandSyntaxException { 40 | CommandSource source = (CommandSource) context.getSource(); 41 | boolean isAdmin = source.hasAdmin(); 42 | Player player = source.getSender(); 43 | PlayerData playerData = PlayerData.get(player); 44 | int homes = playerData.homes.getHomesAmount(); 45 | String homeName = context.getArgument("home", String.class); 46 | 47 | if (homes == 0) { 48 | player.sendMessage(TextFormatting.ORANGE + "You do not have any homes!"); 49 | player.sendMessage(TextFormatting.ORANGE + "Set a home with: " + TextFormatting.LIGHT_BLUE + "/sethome [name]"); 50 | return 1; 51 | } 52 | 53 | if (homeName.equals("bed")) { 54 | player.sendMessage(TextFormatting.YELLOW + "This home is reserved for your bed."); 55 | return 1; 56 | } 57 | 58 | if (playerData.homes.delHome(homeName)) { 59 | player.sendMessage(TextFormatting.YELLOW + "Removed home: " + TextFormatting.ORANGE + homeName); 60 | } else { 61 | player.sendMessage(TextFormatting.YELLOW + "You don't have a home named: " + TextFormatting.ORANGE + homeName); 62 | player.sendMessage(TextFormatting.YELLOW + "Use: " + TextFormatting.LIGHT_BLUE + "/sethome " + homeName + TextFormatting.YELLOW + " to create"); 63 | } 64 | 65 | return 1; 66 | } 67 | 68 | private int playerHomeArg(CommandContext context) throws CommandSyntaxException { 69 | CommandSource source = (CommandSource) context.getSource(); 70 | Player player = source.getSender(); 71 | PlayerServer target = context.getArgument("player", PlayerServer.class); 72 | String homeName = context.getArgument("home", String.class); 73 | PlayerData playerData = PlayerData.get(target); 74 | 75 | if (playerData.homes.delHome(homeName)) { 76 | player.sendMessage(TextFormatting.YELLOW + "You have removed " + TextFormatting.RESET + target.getDisplayName() + TextFormatting.RESET + TextFormatting.YELLOW + "'s home: " + TextFormatting.LIGHT_BLUE + homeName); 77 | } else { 78 | player.sendMessage(target.getDisplayName() + TextFormatting.RESET + TextFormatting.YELLOW + " does not have a home named: " + TextFormatting.LIGHT_BLUE + homeName); 79 | } 80 | 81 | return 1; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/Teleport.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | import net.minecraft.core.entity.player.Player; 4 | import net.minecraft.core.net.command.TextFormatting; 5 | import net.minecraft.core.net.packet.PacketAddEntity; 6 | import net.minecraft.core.net.packet.PacketRespawn; 7 | import net.minecraft.core.util.helper.DyeColor; 8 | import net.minecraft.server.MinecraftServer; 9 | import net.minecraft.server.entity.player.PlayerServer; 10 | import net.minecraft.server.net.PlayerList; 11 | import net.minecraft.server.world.WorldServer; 12 | 13 | public class Teleport { 14 | public static boolean teleport(Player player, double x, double y, double z, int dimID) { 15 | return teleport(player, new WorldPosition(x, y, z, dimID)); 16 | } 17 | 18 | public static boolean teleport(Player player, WorldPosition destination) { 19 | if (player.isPassenger()) { 20 | player.sendMessage(TextFormatting.YELLOW + "You can't teleport while you're a passenger."); 21 | return false; 22 | } 23 | 24 | PlayerList playerList = MinecraftServer.getInstance().playerList; 25 | if (player.dimension != destination.dimID) { 26 | playerList.sendPlayerToOtherDimension( 27 | (PlayerServer) player, 28 | destination.dimID, 29 | DyeColor.MAGENTA, 30 | false 31 | ); 32 | playerList.sendPacketToPlayer( 33 | player.username, new PacketRespawn( 34 | (byte) destination.dimID, 35 | (byte) 0 36 | ) 37 | ); 38 | } 39 | 40 | MinecraftServer server = MinecraftServer.getInstance(); 41 | WorldServer world = server.getDimensionWorld(destination.dimID); 42 | int chunkCordX = (int) destination.x >> 4; 43 | int chunkCordZ = (int) destination.z >> 4; 44 | 45 | world 46 | .getChunkProvider() 47 | .prepareChunk(chunkCordX, chunkCordZ); 48 | 49 | 50 | ((PlayerServer) player).teleport( 51 | destination.x, 52 | destination.y, 53 | destination.z, 54 | player.yRot, 55 | player.xRot 56 | ); 57 | player.moveTo(destination.x, destination.y, destination.z, player.yRot, player.xRot); 58 | player.world.playSoundAtEntity(null, player, "random.explode", 2, 2); 59 | player.world.spawnParticle("smoke", destination.x + 0.5, destination.y, destination.z + 0.5, 0, 0, 0, 0); 60 | // Show the teleported player instantly 61 | // instead of waiting on the server to send the packet 62 | playerList.sendPacketToPlayersAroundPoint( 63 | destination.x, 64 | destination.y, 65 | destination.z, 66 | 64, 67 | destination.dimID, 68 | new PacketAddEntity(player) 69 | ); 70 | 71 | return true; 72 | } 73 | 74 | public static boolean teleport(Player movingPlayer, Player stationaryPlayer) { 75 | if (movingPlayer.isPassenger() || stationaryPlayer.isPassenger()) { 76 | movingPlayer.sendMessage(TextFormatting.YELLOW + "You cannot teleport as, or to, a passenger!"); 77 | stationaryPlayer.sendMessage(TextFormatting.YELLOW + "You cannot teleport as, or to, a passenger!"); 78 | return false; 79 | } 80 | double x = stationaryPlayer.x; 81 | double y = stationaryPlayer.y; 82 | double z = stationaryPlayer.z; 83 | float xr = stationaryPlayer.xRot; 84 | float yr = stationaryPlayer.yRot; 85 | PlayerList playerList = MinecraftServer.getInstance().playerList; 86 | if (movingPlayer.dimension != stationaryPlayer.dimension) { 87 | playerList.sendPlayerToOtherDimension( 88 | (PlayerServer) movingPlayer, 89 | stationaryPlayer.dimension, 90 | null, 91 | false 92 | ); 93 | playerList.sendPacketToPlayer( 94 | movingPlayer.username, new PacketRespawn( 95 | (byte) stationaryPlayer.dimension, 96 | (byte) 0 97 | ) 98 | ); 99 | } 100 | ((PlayerServer) movingPlayer).teleport(x, y, z, yr, xr); 101 | movingPlayer.moveTo(x, y, z, yr, xr); 102 | movingPlayer.world.playSoundAtEntity(null, movingPlayer, "random.explode", 2, 2); 103 | movingPlayer.world.spawnParticle("smoke", x + 0.5, y, z + 0.5, 0, 0, 0, 0); 104 | // Show the teleported player to the accepting player instantly 105 | // instead of waiting on the server to send the packet 106 | playerList.sendPacketToPlayersAroundPoint( 107 | x, 108 | y, 109 | z, 110 | 64, 111 | stationaryPlayer.dimension, 112 | new PacketAddEntity(movingPlayer) 113 | ); 114 | return true; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/CommandGameModeMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import net.minecraft.core.entity.Entity; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.lang.I18n; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.net.command.arguments.ArgumentTypeEntity; 11 | import net.minecraft.core.net.command.arguments.ArgumentTypeGameMode; 12 | import net.minecraft.core.net.command.commands.CommandGameMode; 13 | import net.minecraft.core.net.command.exceptions.CommandExceptions; 14 | import net.minecraft.core.net.command.helpers.EntitySelector; 15 | import net.minecraft.core.net.command.util.CommandHelper; 16 | import net.minecraft.core.player.gamemode.Gamemode; 17 | import org.spongepowered.asm.mixin.Mixin; 18 | import org.spongepowered.asm.mixin.injection.At; 19 | import org.spongepowered.asm.mixin.injection.Inject; 20 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 21 | import wyspr.BTE.Essentials; 22 | 23 | import java.util.List; 24 | 25 | @SuppressWarnings("ALL") 26 | @Mixin(value = CommandGameMode.class, remap = false) public class CommandGameModeMixin { 27 | @Inject( 28 | method = "register", at = @At("HEAD"), cancellable = true 29 | ) 30 | public void register(CommandDispatcher dispatcher, CallbackInfo ci) { 31 | String[] literals = {"gm", "gamemode"}; 32 | for (String literal : literals) { 33 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 34 | .literal(literal) 35 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.GamemodeCommand) 36 | .then( 37 | ArgumentBuilderRequired 38 | .argument("gamemode", ArgumentTypeGameMode.gameMode()) 39 | .executes(context -> { 40 | CommandSource source = (CommandSource) context.getSource(); 41 | Gamemode gameMode = (Gamemode) context.getArgument( 42 | "gamemode", 43 | Gamemode.class 44 | ); 45 | if (source.getSender() == null) { 46 | throw CommandExceptions 47 | .notInWorld() 48 | .create(); 49 | } else { 50 | source 51 | .getSender() 52 | .setGamemode(gameMode); 53 | source.sendTranslatableMessage( 54 | "command.commands.gamemode.success_self", 55 | new Object[]{I18n.getInstance().translateKey(gameMode.getLanguageKey() + ".name")} 56 | ); 57 | return 1; 58 | } 59 | }) 60 | ) 61 | .then(ArgumentBuilderRequired 62 | .argument("targets", ArgumentTypeEntity.usernames()) 63 | .requires(source -> ((CommandSource) source).hasAdmin()) 64 | .executes((c) -> { 65 | CommandSource source = (CommandSource) c.getSource(); 66 | Gamemode gameMode = (Gamemode) c.getArgument( 67 | "gamemode", 68 | Gamemode.class 69 | ); 70 | EntitySelector entitySelector = (EntitySelector) c.getArgument( 71 | "targets", 72 | EntitySelector.class 73 | ); 74 | List entities 75 | = entitySelector.get((CommandSource) c.getSource()); 76 | 77 | for (Entity entity : entities) { 78 | ((Player) entity).setGamemode(gameMode); 79 | if (entity != source.getSender()) { 80 | source.sendTranslatableMessage( 81 | (Player) entity, 82 | "command.commands.gamemode.success_receiver", 83 | new Object[0] 84 | ); 85 | } 86 | } 87 | 88 | if (entities.size() == 1) { 89 | if (entities.get(0) == source.getSender()) { 90 | source.sendTranslatableMessage( 91 | "command.commands.gamemode.success_self", 92 | new Object[]{I18n.getInstance().translateKey(gameMode.getLanguageKey() + ".name")} 93 | ); 94 | } else { 95 | source.sendTranslatableMessage( 96 | "command.commands.gamemode.success_other", 97 | new Object[]{ 98 | CommandHelper.getEntityName((Entity) entities.get(0)), 99 | I18n.getInstance().translateKey(gameMode.getLanguageKey() + ".name") 100 | } 101 | ); 102 | } 103 | } 104 | 105 | return 1; 106 | })) 107 | 108 | ); 109 | } 110 | 111 | ci.cancel(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/PacketHandlerServerMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.minecraft.core.entity.Entity; 4 | import net.minecraft.core.entity.player.Player; 5 | import net.minecraft.core.item.ItemStack; 6 | import net.minecraft.core.item.Items; 7 | import net.minecraft.core.net.command.TextFormatting; 8 | import net.minecraft.core.net.packet.PacketChat; 9 | import net.minecraft.core.net.packet.PacketRespawn; 10 | import net.minecraft.core.net.packet.PacketUpdatePlayerState; 11 | import net.minecraft.server.MinecraftServer; 12 | import net.minecraft.server.entity.player.PlayerServer; 13 | import net.minecraft.server.net.handler.PacketHandlerServer; 14 | import org.slf4j.Logger; 15 | import org.spongepowered.asm.mixin.Mixin; 16 | import org.spongepowered.asm.mixin.Shadow; 17 | import org.spongepowered.asm.mixin.Unique; 18 | import org.spongepowered.asm.mixin.injection.At; 19 | import org.spongepowered.asm.mixin.injection.Inject; 20 | import org.spongepowered.asm.mixin.injection.Redirect; 21 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 22 | import wyspr.BTE.Essentials; 23 | import wyspr.BTE.utils.PlayerData; 24 | 25 | import java.util.Objects; 26 | 27 | @Mixin(value = PacketHandlerServer.class, remap = false) public class PacketHandlerServerMixin { 28 | @Shadow 29 | private PlayerServer playerEntity; 30 | 31 | @Redirect( 32 | method = "handleChat", at = @At( 33 | value = "INVOKE", target = "Ljava/lang/String;trim()Ljava/lang/String;" 34 | 35 | ) 36 | ) 37 | public String redirectChat(String message) { 38 | if (Essentials.GreenText && message.startsWith("> ")) { 39 | message = TextFormatting.GREEN + message; 40 | } else if (Essentials.ColorChat) { 41 | message = message.replace("$$", "§"); 42 | } 43 | 44 | return message; 45 | } 46 | 47 | @Redirect( 48 | method = "handleChat", at = @At( 49 | value = "INVOKE", target = "Lorg/slf4j/Logger;info(Ljava/lang/String;)V" 50 | ) 51 | ) 52 | public void redirectMutePlayer(Logger logger, String message) { 53 | if (PlayerData.get(this.playerEntity).muted) { 54 | MinecraftServer.getInstance().playerList.sendChatMessageToAllOps(TextFormatting.RED + "" + TextFormatting.BOLD + "[MUTED] " + TextFormatting.RESET + message); 55 | } else { 56 | logger.info(message); 57 | } 58 | } 59 | 60 | @Inject( 61 | method = "handleChat", cancellable = true, at = @At( 62 | value = "INVOKE", target = "Lnet/minecraft/server/net/PlayerList;sendEncryptedChatToAllPlayers(Ljava/lang/String;)V" 63 | ) 64 | ) 65 | public void mutePlayer(PacketChat packet, CallbackInfo ci) { 66 | if (PlayerData.get(this.playerEntity).muted) { 67 | this.playerEntity.sendMessage(TextFormatting.RED + "You have been muted."); 68 | ci.cancel(); 69 | } 70 | } 71 | 72 | @Redirect( 73 | method = "handleUseEntity", at = @At( 74 | value = "INVOKE", target = "Lnet/minecraft/server/entity/player/PlayerServer;useCurrentItemOnEntity(Lnet/minecraft/core/entity/Entity;)Z" 75 | ) 76 | ) 77 | public boolean ridePlayer(PlayerServer player, Entity targetEntity) { 78 | if (Essentials.HeadSit) { 79 | if (targetEntity instanceof Player) { 80 | if (player.getCurrentEquippedItem() != null) { 81 | return player.useCurrentItemOnEntity(targetEntity); 82 | } 83 | 84 | Player targetPlayer = (Player) targetEntity; 85 | if (Essentials.HeadSitSaddle) { 86 | ItemStack headSlot = targetPlayer.inventory.armorInventory[3]; 87 | if (Objects.nonNull(headSlot)) { 88 | if (Objects.equals(headSlot.getItem(), Items.SADDLE)) { 89 | return mountPlayer(player, targetEntity); 90 | } 91 | } 92 | } else { 93 | return mountPlayer(player, targetEntity); 94 | } 95 | 96 | } 97 | } 98 | 99 | return player.useCurrentItemOnEntity(targetEntity); 100 | } 101 | 102 | @Unique 103 | private static boolean mountPlayer(PlayerServer player, Entity targetEntity) { 104 | player.startRiding(targetEntity); 105 | 106 | player.collision = false; 107 | player.noPhysics = true; 108 | return true; 109 | } 110 | 111 | @Inject( 112 | method = "handlePlayerState", at = @At( 113 | value = "INVOKE", target = "Lnet/minecraft/core/world/IVehicle;ejectRider()Lnet/minecraft/core/entity/Entity;", shift = At.Shift.AFTER 114 | ) 115 | ) 116 | public void playerRideEject(PacketUpdatePlayerState updatePlayerStatePacket, CallbackInfo ci) { 117 | if (this.playerEntity.vehicle instanceof Player) { 118 | this.playerEntity.collision = true; 119 | this.playerEntity.noPhysics = false; 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/TrollCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.Entity; 9 | import net.minecraft.core.entity.EntityPrimedTNT; 10 | import net.minecraft.core.entity.player.Player; 11 | import net.minecraft.core.net.command.CommandManager; 12 | import net.minecraft.core.net.command.CommandSource; 13 | import net.minecraft.core.world.World; 14 | import net.minecraft.server.entity.player.PlayerServer; 15 | import org.jetbrains.annotations.NotNull; 16 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 17 | 18 | import java.util.Random; 19 | 20 | @SuppressWarnings("ALL") public class TrollCommand implements CommandManager.CommandRegistry { 21 | @Override 22 | public void register(CommandDispatcher dispatcher) { 23 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 24 | .literal("troll") 25 | .requires(source -> ((CommandSource) source).hasAdmin()) 26 | .executes(this::noArg) 27 | .then(ArgumentBuilderRequired 28 | .argument("player", ArgumentTypeUser.user()) 29 | .executes(this::userArg))); 30 | } 31 | 32 | private @NotNull int noArg(CommandContext context) throws CommandSyntaxException { 33 | CommandSource source = (CommandSource) context.getSource(); 34 | Player player = source.getSender(); 35 | 36 | TrollTNT tnt = new TrollTNT( 37 | player.world, 38 | player.x, 39 | player.y + 1, 40 | player.z, 41 | player.xRot, 42 | player.yRot, 43 | 1.5F 44 | ); 45 | 46 | player.world.entityJoinedWorld(tnt); 47 | player.world.playSoundAtEntity((Entity) null, tnt, "tile.tnt.fuse", 1.0F, 1.0F); 48 | 49 | return 1; 50 | } 51 | 52 | private @NotNull int userArg(CommandContext context) throws CommandSyntaxException { 53 | CommandSource source = (CommandSource) context.getSource(); 54 | Player player = source.getSender(); 55 | PlayerServer target = context.getArgument("player", PlayerServer.class); 56 | 57 | TrollTNT tnt = new TrollTNT( 58 | target.world, 59 | target.x, 60 | target.y + 1, 61 | target.z, 62 | target.xRot, 63 | target.yRot, 64 | 1.5F 65 | ); 66 | 67 | target.world.entityJoinedWorld(tnt); 68 | target.world.playSoundAtEntity((Entity) null, tnt, "tile.tnt.fuse", 1.0F, 1.0F); 69 | 70 | return 1; 71 | } 72 | 73 | private class TrollTNT extends EntityPrimedTNT { 74 | private Random random = new Random(); 75 | 76 | public TrollTNT( 77 | World world, 78 | double x, 79 | double y, 80 | double z, 81 | float pitch, 82 | float yaw, 83 | float force 84 | ) 85 | { 86 | super(world); 87 | this.setPos(x, y, z); 88 | 89 | float pitchRad = (float) Math.toRadians(pitch); 90 | float yawRad = (float) Math.toRadians(yaw); 91 | 92 | this.xd = -Math.sin(yawRad) * Math.cos(pitchRad) * force; 93 | this.zd = Math.cos(yawRad) * Math.cos(pitchRad) * force; 94 | this.yd = 0.2 + -Math.sin(pitchRad) * force; 95 | 96 | this.fuse = 100; 97 | 98 | this.xo = x; 99 | this.yo = y; 100 | this.zo = z; 101 | } 102 | 103 | 104 | @Override 105 | public void tick() { 106 | this.checkOnWater(true); 107 | this.checkOnWater(true); 108 | this.pushTime *= 0.98F; 109 | if (this.pushTime < 0.05F || (double) this.pushTime < (double) 0.25F && this.onGround) { 110 | this.pushTime = 0.0F; 111 | } 112 | 113 | this.xo = this.x; 114 | this.yo = this.y; 115 | this.zo = this.z; 116 | this.yd -= 0.04; 117 | this.move(this.xd, this.yd, this.zd); 118 | this.xd *= 0.98; 119 | this.yd *= 0.98; 120 | this.zd *= 0.98; 121 | if (this.onGround) { 122 | this.xd *= 0.7; 123 | this.zd *= 0.7; 124 | this.yd *= -0.5; 125 | } 126 | 127 | if (this.fuse <= 40) { 128 | this.world.spawnParticle( 129 | "smoke", 130 | this.x, 131 | this.y + 0.5, 132 | this.z, 133 | 0.0, 134 | 0.0, 135 | 0.0, 136 | 0 137 | ); 138 | } 139 | 140 | switch (this.fuse) { 141 | case 45: 142 | this.world.playSoundAtEntity(null, this, "mob.ghast.scream", 2, 1); 143 | break; 144 | case 40: 145 | this.world.playSoundAtEntity(null, this, "random.explode", 0.5F, 0); 146 | break; 147 | case 35: 148 | this.world.playSoundAtEntity(null, this, "mob.cowhurt", 2, 1.5F); 149 | break; 150 | case 30: 151 | this.world.playSoundAtEntity(null, this, "random.explode", 1, 0.25F); 152 | break; 153 | case 25: 154 | this.world.playSoundAtEntity(null, this, "mob.wolf.hurt", 2, 1.5F); 155 | break; 156 | case 20: 157 | this.world.playSoundAtEntity(null, this, "random.explode", 1.5F, 0.75F); 158 | break; 159 | case 15: 160 | this.world.playSoundAtEntity(null, this, "mob.pigdeath", 2, 0.75F); 161 | break; 162 | case 10: 163 | this.world.playSoundAtEntity(null, this, "random.explode", 2, 1); 164 | break; 165 | case 05: 166 | this.world.playSoundAtEntity(null, this, "mob.chickenhurt", 2, 0.75F); 167 | break; 168 | case 00: 169 | this.world.playSoundAtEntity(null, this, "random.glass", 2, 0.75F); 170 | this.world.playSoundAtEntity(null, this, "mob.ghast.scream", 2, 0.75F); 171 | this.remove(); 172 | break; 173 | } 174 | 175 | --this.fuse; 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/ConfigBuilder.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | import net.minecraft.core.net.command.TextFormatting; 4 | import wyspr.BTE.Essentials; 5 | 6 | import java.io.IOException; 7 | import java.nio.charset.StandardCharsets; 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | import java.util.*; 11 | 12 | public class ConfigBuilder { 13 | private static final Map colorMap = new HashMap<>(33); 14 | 15 | static { 16 | colorMap.put("white", TextFormatting.WHITE.toString()); 17 | colorMap.put("orange", TextFormatting.ORANGE.toString()); 18 | colorMap.put("magenta", TextFormatting.MAGENTA.toString()); 19 | colorMap.put("aqua", TextFormatting.LIGHT_BLUE.toString()); 20 | colorMap.put("light_blue", TextFormatting.LIGHT_BLUE.toString()); 21 | colorMap.put("yellow", TextFormatting.YELLOW.toString()); 22 | colorMap.put("lime", TextFormatting.LIME.toString()); 23 | colorMap.put("pink", TextFormatting.PINK.toString()); 24 | colorMap.put("grey", TextFormatting.GRAY.toString()); 25 | colorMap.put("gray", TextFormatting.GRAY.toString()); 26 | colorMap.put("silver", TextFormatting.LIGHT_GRAY.toString()); 27 | colorMap.put("light_gray", TextFormatting.LIGHT_GRAY.toString()); 28 | colorMap.put("light_grey", TextFormatting.LIGHT_GRAY.toString()); 29 | colorMap.put("cyan", TextFormatting.CYAN.toString()); 30 | colorMap.put("purple", TextFormatting.PURPLE.toString()); 31 | colorMap.put("blue", TextFormatting.BLUE.toString()); 32 | colorMap.put("brown", TextFormatting.BROWN.toString()); 33 | colorMap.put("green", TextFormatting.GREEN.toString()); 34 | colorMap.put("red", TextFormatting.RED.toString()); 35 | colorMap.put("black", TextFormatting.BLACK.toString()); 36 | colorMap.put("o", TextFormatting.OBFUSCATED.toString()); 37 | colorMap.put("obf", TextFormatting.OBFUSCATED.toString()); 38 | colorMap.put("obfuscated", TextFormatting.OBFUSCATED.toString()); 39 | colorMap.put("b", TextFormatting.BOLD.toString()); 40 | colorMap.put("bold", TextFormatting.BOLD.toString()); 41 | colorMap.put("s", TextFormatting.STRIKETHROUGH.toString()); 42 | colorMap.put("strike", TextFormatting.STRIKETHROUGH.toString()); 43 | colorMap.put("strikethrough", TextFormatting.STRIKETHROUGH.toString()); 44 | colorMap.put("u", TextFormatting.UNDERLINE.toString()); 45 | colorMap.put("underline", TextFormatting.UNDERLINE.toString()); 46 | colorMap.put("i", TextFormatting.ITALIC.toString()); 47 | colorMap.put("italic", TextFormatting.ITALIC.toString()); 48 | colorMap.put("r", TextFormatting.RESET.toString()); 49 | colorMap.put("reset", TextFormatting.RESET.toString()); 50 | } 51 | 52 | private final Path cfgPath; 53 | private final String fileName; 54 | private final List defaultContent; 55 | private final boolean syntaxEnabled; 56 | 57 | public ConfigBuilder(String fileName, List defaultContent, boolean syntaxEnabled) { 58 | this.fileName = fileName; 59 | this.defaultContent = defaultContent; 60 | this.syntaxEnabled = syntaxEnabled; 61 | this.cfgPath = Essentials.DATA_DIR.resolve(fileName.toLowerCase()); 62 | if (!Files.exists(this.cfgPath)) { 63 | try { 64 | Files.createDirectory(this.cfgPath); 65 | Essentials.LOGGER.info("Created {}", this.cfgPath); 66 | } catch (IOException e) { 67 | Essentials.LOGGER.error("Could not create: {}", this.cfgPath, new RuntimeException(e)); 68 | throw new RuntimeException(e); // Exit if the directory cannot be created 69 | } 70 | } 71 | createBase(); 72 | } 73 | 74 | private void createBase() { 75 | Path baseFile = cfgPath.resolve(fileName + ".txt"); 76 | if (!Files.exists(baseFile)) { 77 | try { 78 | Essentials.LOGGER.info("{} does not exist. Creating it for you...", baseFile); 79 | Files.write(baseFile, defaultContent, StandardCharsets.UTF_8); 80 | Essentials.LOGGER.info("Done! Check your config folder for {}", baseFile); 81 | } catch (IOException e) { 82 | Essentials.LOGGER.error("Error creating file: {}", e.getMessage()); 83 | } 84 | } 85 | } 86 | 87 | public List get(int pageNumber) { 88 | if (pageNumber <= 1) { 89 | return readFile(cfgPath.resolve(fileName + ".txt")); 90 | } 91 | return readFile(cfgPath.resolve(fileName + pageNumber + ".txt")); 92 | } 93 | 94 | private List readFile(Path path) { 95 | try { 96 | List lines = Files.readAllLines(path, StandardCharsets.UTF_8); 97 | if (syntaxEnabled) { 98 | return parseSyntax(lines); 99 | } else { 100 | return lines; 101 | } 102 | } catch (IOException e) { 103 | List errorMsg = Collections.singletonList(parseTags("Page not found.")); 104 | return parseSyntax(errorMsg); 105 | } 106 | } 107 | 108 | private List parseSyntax(List content) { 109 | List parsedLines = new ArrayList<>(); 110 | 111 | for (String line : content) { 112 | if (line.startsWith("///")) continue; // Skip comments 113 | line = parseTags(line); 114 | parsedLines.add(line); 115 | } 116 | 117 | return parsedLines; 118 | } 119 | 120 | private String parseTags(String line) { 121 | // Handle escaping 122 | line = line 123 | .replaceAll("\\\\<", "ESCAPED_LT") 124 | .replaceAll("\\\\>", "ESCAPED_GT"); 125 | // Process color tags 126 | for (Map.Entry entry : colorMap.entrySet()) { 127 | line = line.replaceAll("<" + entry.getKey() + ">", entry.getValue()); 128 | } 129 | // Revert escaped characters 130 | return line 131 | .replaceAll("ESCAPED_LT", "<") 132 | .replaceAll("ESCAPED_GT", ">"); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/CommandGiveMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeInteger; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import com.mojang.brigadier.context.CommandContext; 8 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 9 | import net.fabricmc.api.EnvType; 10 | import net.fabricmc.api.Environment; 11 | import net.minecraft.core.entity.Entity; 12 | import net.minecraft.core.entity.player.Player; 13 | import net.minecraft.core.item.ItemStack; 14 | import net.minecraft.core.net.command.CommandManager; 15 | import net.minecraft.core.net.command.CommandSource; 16 | import net.minecraft.core.net.command.arguments.ArgumentTypeEntity; 17 | import net.minecraft.core.net.command.arguments.ArgumentTypeItemStack; 18 | import net.minecraft.core.net.command.commands.CommandGive; 19 | import net.minecraft.core.net.command.helpers.EntitySelector; 20 | import net.minecraft.core.net.command.util.CommandHelper; 21 | import org.spongepowered.asm.mixin.Mixin; 22 | import wyspr.BTE.Essentials; 23 | 24 | import java.util.List; 25 | 26 | 27 | @Environment(EnvType.SERVER) @SuppressWarnings("ALL") @Mixin( 28 | value = CommandGive.class 29 | ) public class CommandGiveMixin implements CommandManager.CommandRegistry { 30 | public void register(CommandDispatcher dispatcher) { 31 | String[] literals = {"i", "give"}; 32 | for (String literal : literals) { 33 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 34 | .literal(literal) 35 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.GiveCommand) 36 | .then(ArgumentBuilderRequired.argument("item", ArgumentTypeItemStack.itemStack()) 37 | .executes(this::fullStackToSelf)) 38 | .then(ArgumentBuilderRequired.argument("target", ArgumentTypeEntity.usernames()) 39 | .then(ArgumentBuilderRequired.argument("item", ArgumentTypeItemStack.itemStack()) 40 | .executes(this::fullStack) 41 | .then(ArgumentBuilderRequired.argument("amount", ArgumentTypeInteger.integer(1, 6400)) 42 | .executes(this::amountArg))))); 43 | } 44 | } 45 | 46 | private int fullStackToSelf(CommandContext c) throws CommandSyntaxException { 47 | CommandSource source = (CommandSource) c.getSource(); 48 | Player player = source.getSender(); 49 | ItemStack itemStack = (ItemStack) c.getArgument("item", ItemStack.class); 50 | int amount = itemStack.getMaxStackSize(); 51 | 52 | player.inventory.insertItem(itemStack, true); 53 | if (itemStack.stackSize > 0) { 54 | player.dropPlayerItem(itemStack); 55 | } 56 | 57 | source.sendTranslatableMessage( 58 | "command.commands.give.success_single_entity", new Object[]{ 59 | CommandHelper.getEntityName(player), amount, itemStack.getDisplayName() 60 | } 61 | ); 62 | 63 | return 1; 64 | } 65 | 66 | private int fullStack(CommandContext c) throws CommandSyntaxException { 67 | CommandSource source = (CommandSource) c.getSource(); 68 | ItemStack itemStack = (ItemStack) c.getArgument("item", ItemStack.class); 69 | int amount = itemStack.stackSize; 70 | EntitySelector entitySelector = (EntitySelector) c.getArgument( 71 | "target", 72 | EntitySelector.class 73 | ); 74 | List entities = entitySelector.get(source); 75 | 76 | for (Entity player : entities) { 77 | ((Player) player).inventory.insertItem(itemStack, true); 78 | if (itemStack.stackSize > 0) { 79 | ((Player) player).dropPlayerItem(itemStack); 80 | } 81 | } 82 | 83 | if (entities.size() == 1) { 84 | source.sendTranslatableMessage( 85 | "command.commands.give.success_single_entity", new Object[]{ 86 | CommandHelper.getEntityName((Entity) entities.get(0)), amount, itemStack.getDisplayName() 87 | } 88 | ); 89 | } else { 90 | source.sendTranslatableMessage( 91 | "command.commands.give.success_single_entity", 92 | new Object[]{entities.size(), amount, itemStack.getDisplayName()} 93 | ); 94 | } 95 | 96 | return 1; 97 | } 98 | 99 | private int amountArg(CommandContext c) throws CommandSyntaxException { 100 | CommandSource source = (CommandSource) c.getSource(); 101 | ItemStack itemStack = (ItemStack) c.getArgument("item", ItemStack.class); 102 | EntitySelector entitySelector = (EntitySelector) c.getArgument( 103 | "target", 104 | EntitySelector.class 105 | ); 106 | List entities = entitySelector.get(source); 107 | int amount = (Integer) c.getArgument("amount", Integer.class); 108 | 109 | for (Entity player : entities) { 110 | int incompleteStack = amount % 64; 111 | 112 | for (int i = 0; i < (amount - incompleteStack) / 64; ++i) { 113 | ItemStack itemStack1 = ItemStack.copyItemStack(itemStack); 114 | itemStack1.stackSize = 64; 115 | ((Player) player).inventory.insertItem(itemStack1, true); 116 | if (itemStack1.stackSize > 0) { 117 | ((Player) player).dropPlayerItem(itemStack1); 118 | } 119 | } 120 | 121 | if (incompleteStack > 0) { 122 | ItemStack itemStack1 = ItemStack.copyItemStack(itemStack); 123 | itemStack1.stackSize = incompleteStack; 124 | ((Player) player).inventory.insertItem(itemStack1, true); 125 | if (itemStack1.stackSize > 0) { 126 | ((Player) player).dropPlayerItem(itemStack1); 127 | } 128 | } 129 | } 130 | 131 | if (entities.size() == 1) { 132 | source.sendTranslatableMessage( 133 | "command.commands.give.success_single_entity", new Object[]{ 134 | CommandHelper.getEntityName((Entity) entities.get(0)), amount, itemStack.getDisplayName() 135 | } 136 | ); 137 | } else { 138 | source.sendTranslatableMessage( 139 | "command.commands.give.success_single_entity", 140 | new Object[]{entities.size(), amount, itemStack.getDisplayName()} 141 | ); 142 | } 143 | 144 | return 1; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MSYS* | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/TPA/TPConfirmCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.TPA; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import net.minecraft.server.MinecraftServer; 13 | import net.minecraft.server.entity.player.PlayerServer; 14 | import org.apache.commons.lang3.tuple.Pair; 15 | import wyspr.BTE.Essentials; 16 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 17 | import wyspr.BTE.utils.PlayerData; 18 | import wyspr.BTE.utils.PlayerData.TPManager; 19 | import wyspr.BTE.utils.TPARequestType; 20 | import wyspr.BTE.utils.Teleport; 21 | 22 | @SuppressWarnings("ALL") public class TPConfirmCommand implements CommandManager.CommandRegistry { 23 | @Override 24 | public void register(CommandDispatcher commandDispatcher) { 25 | 26 | String[] literals = {"tpyes", "ty", "tpconfirm"}; 27 | for (String literal : literals) { 28 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 29 | .literal(literal) 30 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.TPACommand) 31 | .executes(this::noArg) 32 | .then(ArgumentBuilderRequired 33 | .argument("target", ArgumentTypeUser.user()) 34 | .executes(this::playerArg))); 35 | } 36 | 37 | } 38 | 39 | private int noArg(CommandContext context) throws CommandSyntaxException { 40 | CommandSource source = (CommandSource) context.getSource(); 41 | boolean isAdmin = source.hasAdmin(); 42 | Player player = source.getSender(); 43 | TPManager playerTPM = PlayerData.get(player).tpManager; 44 | 45 | if (playerTPM.hasNoRequests()) { 46 | player.sendMessage(TextFormatting.YELLOW + "You don't have any requests."); 47 | return 1; 48 | } 49 | 50 | Pair requestPair = playerTPM.getNewestRequest(); 51 | String targetUsername = requestPair.getKey(); 52 | TPARequestType request = requestPair.getValue(); 53 | 54 | Player target = (Player) MinecraftServer.getInstance().playerList.getPlayerEntity(targetUsername); 55 | if (target == null) { 56 | player.sendMessage(TextFormatting.LIGHT_BLUE + targetUsername + TextFormatting.ORANGE + " is offline."); 57 | return 1; 58 | } 59 | 60 | PlayerData targetData = PlayerData.get(target); 61 | boolean targetNotAdmin = !((PlayerServer) target).isOperator(); 62 | 63 | int cost = Essentials.TPACost; 64 | if (target.score < cost && targetNotAdmin) { 65 | target.sendMessage(TextFormatting.YELLOW + "You do not have enough points to use TPA!"); 66 | target.sendMessage(TextFormatting.YELLOW + "You need " + TextFormatting.ORANGE + (cost - target.score) + TextFormatting.YELLOW + " more points!"); 67 | player.sendMessage(TextFormatting.YELLOW + "" + targetUsername + " does not have enough points to use TPA"); 68 | return 1; 69 | } 70 | 71 | boolean didTeleport = false; 72 | 73 | if (request == TPARequestType.TPA) { 74 | targetData.tpManager.updateBackPos(); 75 | didTeleport = Teleport.teleport(target, player); 76 | if (didTeleport) { 77 | target.sendMessage(TextFormatting.ORANGE + "Teleported to " + player.getDisplayName()); 78 | } 79 | } else if (request == TPARequestType.TPAHERE) { 80 | playerTPM.updateBackPos(); 81 | didTeleport = Teleport.teleport(player, target); 82 | if (didTeleport) { 83 | target.sendMessage(TextFormatting.ORANGE + "Teleported " + player.getDisplayName() + " to you"); 84 | player.sendMessage(TextFormatting.ORANGE + "Teleported to " + target.getDisplayName()); 85 | } 86 | } 87 | 88 | if (didTeleport) { 89 | playerTPM.removeRequest(target.username); 90 | if (targetNotAdmin) { 91 | target.score -= Essentials.TPACost; 92 | } 93 | } 94 | 95 | return 1; 96 | } 97 | 98 | private int playerArg(CommandContext context) throws CommandSyntaxException { 99 | CommandSource source = (CommandSource) context.getSource(); 100 | boolean isAdmin = source.hasAdmin(); 101 | Player player = source.getSender(); 102 | PlayerServer target = context.getArgument("target", PlayerServer.class); 103 | PlayerData targetData = PlayerData.get(target); 104 | TPManager playerTPM = PlayerData.get(player).tpManager; 105 | boolean targetNotAdmin = !target.isOperator(); 106 | 107 | if (playerTPM.hasNoRequests()) { 108 | player.sendMessage(TextFormatting.YELLOW + "You don't have any requests."); 109 | return 1; 110 | } 111 | 112 | if (!playerTPM.hasRequestFrom(target.username)) { 113 | player.sendMessage(TextFormatting.ORANGE + "You don't have a request from " + TextFormatting.YELLOW + target); 114 | return 1; 115 | } 116 | 117 | TPARequestType request = playerTPM.getRequest(target.username); 118 | 119 | int cost = Essentials.TPACost; 120 | if (target.score < cost && targetNotAdmin) { 121 | target.sendMessage(TextFormatting.YELLOW + "You do not have enough points to use TPA!"); 122 | target.sendMessage(TextFormatting.YELLOW + "You need " + TextFormatting.ORANGE + (cost - target.score) + TextFormatting.YELLOW + " more points!"); 123 | player.sendMessage(TextFormatting.YELLOW + "" + target.username + " does not have enough points to use TPA"); 124 | return 1; 125 | } 126 | 127 | boolean didTeleport = false; 128 | 129 | if (request == TPARequestType.TPA) { 130 | targetData.tpManager.updateBackPos(); 131 | didTeleport = Teleport.teleport(target, player); 132 | if (didTeleport) { 133 | target.sendMessage(TextFormatting.ORANGE + "Teleported to " + player.getDisplayName()); 134 | } 135 | } else if (request == TPARequestType.TPAHERE) { 136 | playerTPM.updateBackPos(); 137 | didTeleport = Teleport.teleport(player, target); 138 | if (didTeleport) { 139 | target.sendMessage(TextFormatting.ORANGE + "Teleported " + player.getDisplayName() + " to you"); 140 | player.sendMessage(TextFormatting.ORANGE + "Teleported to " + target.getDisplayName()); 141 | } 142 | } 143 | 144 | if (didTeleport) { 145 | playerTPM.removeRequest(target.username); 146 | if (targetNotAdmin) { 147 | target.score -= Essentials.TPACost; 148 | } 149 | } 150 | 151 | return 1; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/ImportMelonUtilsCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands; 2 | 3 | import com.google.common.reflect.TypeToken; 4 | import com.google.gson.*; 5 | import com.mojang.brigadier.CommandDispatcher; 6 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 7 | import net.minecraft.core.entity.player.Player; 8 | import net.minecraft.core.net.command.CommandManager; 9 | import net.minecraft.core.net.command.CommandSource; 10 | import net.minecraft.core.world.chunk.ChunkCoordinates; 11 | import wyspr.BTE.Essentials; 12 | import wyspr.BTE.utils.InstantTypeAdapter; 13 | import wyspr.BTE.utils.Warps; 14 | import wyspr.BTE.utils.WorldPosition; 15 | 16 | import java.io.File; 17 | import java.io.FileNotFoundException; 18 | import java.io.FileReader; 19 | import java.io.Serializable; 20 | import java.nio.charset.StandardCharsets; 21 | import java.nio.file.Files; 22 | import java.nio.file.Path; 23 | import java.time.Duration; 24 | import java.time.Instant; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | 28 | @SuppressWarnings("ALL") public class ImportMelonUtilsCommand implements CommandManager.CommandRegistry { 29 | @Override 30 | public void register(CommandDispatcher commandDispatcher) { 31 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 32 | .literal("importmelonutils") 33 | .requires(source -> ((CommandSource) source).hasAdmin()) 34 | .executes(context -> { 35 | CommandSource source = (CommandSource) context.getSource(); 36 | Player player = source.getSender(); 37 | 38 | Path melonutilsDir = Essentials.CFG_DIR.resolve("melonutilities"); 39 | 40 | if (!melonutilsDir.toFile().exists()) { 41 | player.sendMessage("melonutilities direcory not found"); 42 | return 1; 43 | } 44 | 45 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 46 | 47 | File melonutilsConfig = new File(melonutilsDir.toFile(), "config.json"); 48 | // Load full JSON document 49 | JsonObject root = null; 50 | try { 51 | root = JsonParser.parseReader(new FileReader(melonutilsConfig)).getAsJsonObject(); 52 | } catch (FileNotFoundException e) { 53 | Essentials.LOGGER.error( 54 | "Failed to load file: {}", 55 | melonutilsConfig, 56 | new RuntimeException(e) 57 | ); 58 | player.sendMessage("Failed to load config.json"); 59 | return 1; 60 | } 61 | 62 | JsonObject mainConfig = root.getAsJsonObject("Main Config"); 63 | 64 | if (mainConfig == null) { 65 | player.sendMessage("Main Config section not found in config.json"); 66 | return 1; 67 | } 68 | 69 | // Apply the changes 70 | mainConfig.addProperty("enableTPA", false); 71 | mainConfig.addProperty("enableHomes", false); 72 | mainConfig.addProperty("enableWarps", false); 73 | mainConfig.addProperty("enableRules", false); 74 | 75 | // Save the config 76 | try { 77 | Files.write( 78 | melonutilsConfig.toPath(), 79 | gson.toJson(root).getBytes(StandardCharsets.UTF_8) 80 | ); 81 | player.sendMessage("Config updated successfully."); 82 | } catch (Exception e) { 83 | Essentials.LOGGER.error("Failed to save modified config.json", e); 84 | player.sendMessage("Failed to save config.json"); 85 | } 86 | 87 | // Locate the "Warp Data" → "warps" array 88 | JsonArray warpsArray = root.getAsJsonObject("Warp Data").getAsJsonArray("warps"); 89 | 90 | // Convert JSON array to List 91 | List warpList = gson.fromJson( 92 | warpsArray, 93 | new TypeToken>() {}.getType() 94 | ); 95 | 96 | // Fill the hashmap 97 | HashMap warpMap = new HashMap<>(); 98 | 99 | for (MelonPosition w : warpList) { 100 | warpMap.put(w.name, new WorldPosition(w.x, w.y, w.z, w.dimID)); 101 | } 102 | 103 | Warps.importWarps(warpMap); 104 | 105 | File melonutilsPlayerDir = melonutilsDir.resolve("users").toFile(); 106 | File[] playersDirList = melonutilsPlayerDir.listFiles(); 107 | 108 | if (playersDirList != null) { 109 | ChunkCoordinates spawnCC = source.getWorld().getSpawnPoint(); 110 | WorldPosition spawn = new WorldPosition(spawnCC.x, spawnCC.y, spawnCC.z, 0); 111 | 112 | for (File melonUserfile : playersDirList) { 113 | try { 114 | loadPlayerFile(melonUserfile, spawn); 115 | } catch (Exception e) { 116 | Essentials.LOGGER.error( 117 | "Failed to load userfile: {}", 118 | melonUserfile, 119 | new RuntimeException(e) 120 | ); 121 | } 122 | } 123 | } else { 124 | player.sendMessage("melonutilities/users direcory not found"); 125 | } 126 | 127 | return 1; 128 | })); 129 | } 130 | 131 | private void loadPlayerFile(File melonUserFile, WorldPosition spawn) throws Exception { 132 | JsonObject melonPlayerJson = JsonParser.parseReader(new FileReader(melonUserFile)).getAsJsonObject(); 133 | Gson gson = new GsonBuilder() 134 | .setPrettyPrinting() 135 | .registerTypeAdapter(Instant.class, new InstantTypeAdapter()) 136 | .create(); 137 | String uuid = melonPlayerJson 138 | .getAsJsonObject("User Data") 139 | .getAsJsonPrimitive("userUUID") 140 | .getAsString(); 141 | 142 | JsonArray homesArray = melonPlayerJson.getAsJsonObject("Home Data").getAsJsonArray("homes"); 143 | 144 | List homesList = gson.fromJson( 145 | homesArray, 146 | new TypeToken>() {}.getType() 147 | ); 148 | 149 | HashMap homesMap = new HashMap<>(); 150 | 151 | if (homesList != null) { 152 | for (MelonPosition home : homesList) { 153 | homesMap.put(home.name, new WorldPosition(home.x, home.y, home.z, home.dimID)); 154 | } 155 | } 156 | 157 | MockPlayerData playerData = new MockPlayerData(); 158 | playerData.lastTPTime = Instant.now().minus(Duration.ofSeconds(Essentials.TPTimeout)); 159 | playerData.backPos = spawn; 160 | playerData.homes = homesMap; 161 | 162 | String json = gson.toJson(playerData); 163 | File saveFile = new File(Essentials.PLAYER_DIR.toFile(), uuid + ".json"); 164 | 165 | Files.write(saveFile.toPath(), json.getBytes(StandardCharsets.UTF_8)); 166 | 167 | } 168 | 169 | private static class MockPlayerData implements Serializable { 170 | public Instant lastTPTime; 171 | public WorldPosition backPos; 172 | public HashMap homes; 173 | } 174 | 175 | private static class MelonPosition { 176 | public String name; 177 | public double x; 178 | public double y; 179 | public double z; 180 | public int dimID; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/commands/home/HomeCommand.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.commands.home; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 5 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 6 | import com.mojang.brigadier.context.CommandContext; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.core.entity.player.Player; 9 | import net.minecraft.core.net.command.CommandManager; 10 | import net.minecraft.core.net.command.CommandSource; 11 | import net.minecraft.core.net.command.TextFormatting; 12 | import net.minecraft.core.world.chunk.ChunkCoordinates; 13 | import net.minecraft.server.entity.player.PlayerServer; 14 | import wyspr.BTE.Essentials; 15 | import wyspr.BTE.commands.arguments.ArgumentTypeHome; 16 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 17 | import wyspr.BTE.utils.PlayerData; 18 | import wyspr.BTE.utils.PlayerData.TPManager; 19 | import wyspr.BTE.utils.Teleport; 20 | import wyspr.BTE.utils.WorldPosition; 21 | 22 | import java.util.Optional; 23 | 24 | @SuppressWarnings("ALL") public class HomeCommand implements CommandManager.CommandRegistry { 25 | @Override 26 | public void register(CommandDispatcher commandDispatcher) { 27 | commandDispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 28 | .literal("home") 29 | .requires(source -> ((CommandSource) source).hasAdmin() || Essentials.HomeCommand) 30 | .executes(this::noArg) 31 | .then(ArgumentBuilderRequired 32 | .argument("home", ArgumentTypeHome.ownHomes()) 33 | .executes(this::homeArg)) 34 | .then(ArgumentBuilderRequired 35 | .argument("player", ArgumentTypeUser.user()) 36 | .requires(source -> ((CommandSource) source).hasAdmin()) 37 | .then(ArgumentBuilderRequired 38 | .argument("home", ArgumentTypeHome.othersHomes()) 39 | .executes(this::playerHomeArg)))); 40 | } 41 | 42 | private int noArg(CommandContext context) throws CommandSyntaxException { 43 | CommandSource source = (CommandSource) context.getSource(); 44 | boolean isAdmin = source.hasAdmin(); 45 | Player player = source.getSender(); 46 | PlayerData playerData = PlayerData.get(player); 47 | String homeName = "home"; 48 | Optional homePos = playerData.homes.getHomePos(homeName); 49 | 50 | return goHome(homePos, player, homeName, playerData, isAdmin); 51 | } 52 | 53 | private int homeArg(CommandContext context) throws CommandSyntaxException { 54 | CommandSource source = (CommandSource) context.getSource(); 55 | boolean isAdmin = source.hasAdmin(); 56 | Player player = source.getSender(); 57 | PlayerData playerData = PlayerData.get(player); 58 | String homeName = context.getArgument("home", String.class); 59 | 60 | Optional homePos; 61 | 62 | if (homeName.equals("bed")) { 63 | ChunkCoordinates bed = player.getPlayerSpawnCoordinate(); 64 | if (bed == null) { 65 | player.sendMessage(TextFormatting.ORANGE + "You do not have a bed! You should work on that!"); 66 | return 1; 67 | } 68 | homePos = Optional.of(new WorldPosition(bed.x, bed.y + 1.0, bed.z, 0)); 69 | } else { 70 | homePos = playerData.homes.getHomePos(homeName); 71 | } 72 | 73 | return goHome(homePos, player, homeName, playerData, isAdmin); 74 | } 75 | 76 | private int playerHomeArg(CommandContext context) { 77 | CommandSource source = (CommandSource) context.getSource(); 78 | boolean isAdmin = source.hasAdmin(); 79 | Player player = source.getSender(); 80 | TPManager playerTP = PlayerData.get(player).tpManager; 81 | String homeName = context.getArgument("home", String.class); 82 | PlayerServer targetPlayer = context.getArgument("player", PlayerServer.class); 83 | PlayerData targetData = PlayerData.get(targetPlayer); 84 | 85 | int homes = targetData.homes.getHomesAmount(); 86 | if (homes == 0) { 87 | player.sendMessage(targetPlayer.getDisplayName() + TextFormatting.ORANGE + " does not have any homes!"); 88 | return 1; 89 | } 90 | 91 | Optional homePos = targetData.homes.getHomePos(homeName); 92 | 93 | boolean homeNotFound = !homePos.isPresent(); 94 | if (homeNotFound) { 95 | player.sendMessage(targetPlayer.getDisplayName() + TextFormatting.ORANGE + " does not have a home named: " + TextFormatting.YELLOW + homeName); 96 | player.sendMessage(TextFormatting.ORANGE + "View homes with: " + TextFormatting.LIGHT_BLUE + "/homes " + targetPlayer.username); 97 | return 1; 98 | } 99 | 100 | playerTP.updateBackPos(); 101 | WorldPosition home = homePos.get(); 102 | if (Teleport.teleport(player, home)) { 103 | player.sendMessage(TextFormatting.YELLOW + "Teleported to " + TextFormatting.RESET + targetPlayer.getDisplayName() + TextFormatting.YELLOW + "'s home: " + TextFormatting.ORANGE + homeName); 104 | } 105 | 106 | return 1; 107 | } 108 | 109 | 110 | private static Integer goHome( 111 | Optional homePos, 112 | Player player, 113 | String homeName, 114 | PlayerData playerData, 115 | boolean isAdmin 116 | ) 117 | { 118 | int cost = Essentials.HomeCost; 119 | if (player.score < cost && !isAdmin) { 120 | player.sendMessage(TextFormatting.YELLOW + "You do not have enough points to use this command!"); 121 | player.sendMessage(TextFormatting.YELLOW + "You need " + TextFormatting.ORANGE + (cost - player.score) + TextFormatting.YELLOW + " more points!"); 122 | return 1; 123 | } 124 | 125 | int homes = playerData.homes.getHomesAmount(); 126 | if (homes == 0) { 127 | player.sendMessage(TextFormatting.ORANGE + "You do not have any homes!"); 128 | player.sendMessage(TextFormatting.ORANGE + "Set a home with: §3/sethome [name]"); 129 | return 1; 130 | } 131 | 132 | boolean homeNotFound = !homePos.isPresent(); 133 | if (homeNotFound) { 134 | player.sendMessage(TextFormatting.ORANGE + "You do not have a home named: " + TextFormatting.YELLOW + homeName); 135 | player.sendMessage(TextFormatting.ORANGE + "View your homes with: §3/homes"); 136 | return 1; 137 | } 138 | 139 | if (playerData.tpManager.canTP() || isAdmin) { 140 | playerData.tpManager.updateBackPos(); 141 | WorldPosition home = homePos.get(); 142 | if (Teleport.teleport(player, home)) { 143 | player.sendMessage(TextFormatting.YELLOW + "Teleported to " + TextFormatting.ORANGE + homeName); 144 | } 145 | } else { 146 | int waitTime = playerData.tpManager.TPCooldown(); 147 | player.sendMessage(TextFormatting.YELLOW + "Teleport available in " + TextFormatting.ORANGE + waitTime + TextFormatting.YELLOW + " seconds."); 148 | } 149 | return 1; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/CommandNicknameMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.arguments.ArgumentTypeString; 5 | import com.mojang.brigadier.builder.ArgumentBuilderLiteral; 6 | import com.mojang.brigadier.builder.ArgumentBuilderRequired; 7 | import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; 8 | import com.mojang.brigadier.tree.CommandNode; 9 | import net.fabricmc.api.EnvType; 10 | import net.fabricmc.api.Environment; 11 | import net.minecraft.core.net.command.CommandManager; 12 | import net.minecraft.core.net.command.CommandSource; 13 | import net.minecraft.core.net.command.exceptions.CommandExceptions; 14 | import net.minecraft.server.entity.player.PlayerServer; 15 | import net.minecraft.server.net.command.commands.CommandNickname; 16 | import org.spongepowered.asm.mixin.Mixin; 17 | import org.spongepowered.asm.mixin.Overwrite; 18 | import org.spongepowered.asm.mixin.Shadow; 19 | import wyspr.BTE.Essentials; 20 | import wyspr.BTE.commands.arguments.ArgumentTypeUser; 21 | 22 | @Environment(EnvType.SERVER) @SuppressWarnings("ALL") @Mixin( 23 | value = CommandNickname.class, remap = false 24 | ) public class CommandNicknameMixin implements CommandManager.CommandRegistry { 25 | 26 | @Shadow 27 | private static SimpleCommandExceptionType NICKNAME_TOO_LARGE; 28 | @Shadow 29 | private static SimpleCommandExceptionType NICKNAME_TOO_SMALL; 30 | 31 | /** 32 | * @author wyspr 33 | * @reason Override max nick length 34 | */ 35 | @Overwrite 36 | public void register(CommandDispatcher dispatcher) { 37 | CommandNode command 38 | = dispatcher.register((ArgumentBuilderLiteral) ((ArgumentBuilderLiteral) ((ArgumentBuilderLiteral) ArgumentBuilderLiteral 39 | .literal("nickname") 40 | .then(((ArgumentBuilderLiteral) ArgumentBuilderLiteral 41 | .literal("set") 42 | .then(((ArgumentBuilderRequired) ArgumentBuilderRequired 43 | .argument("target", ArgumentTypeUser.user()) 44 | .requires(source -> ((CommandSource) source).hasAdmin())).then(ArgumentBuilderRequired 45 | .argument("nickname", ArgumentTypeString.string()) 46 | .executes((c) -> { 47 | CommandSource source = (CommandSource) c.getSource(); 48 | String nickname = (String) c.getArgument("nickname", String.class); 49 | if (nickname.length() > Essentials.NickLength) { 50 | throw NICKNAME_TOO_LARGE.create(); 51 | } else if (nickname.isEmpty()) { 52 | throw NICKNAME_TOO_SMALL.create(); 53 | } else { 54 | PlayerServer player = c.getArgument("target", PlayerServer.class); 55 | player.nickname = nickname; 56 | player.hadNicknameSet = true; 57 | player.mcServer.playerList.updatePlayerProfile( 58 | player.username, 59 | player.nickname, 60 | player.uuid, 61 | player.score, 62 | player.chatColor, 63 | true, 64 | player.isOperator() 65 | ); 66 | if (source.getSender() == player) { 67 | source.sendTranslatableMessage( 68 | "command.commands.nickname.set.success", 69 | new Object[]{nickname} 70 | ); 71 | } else { 72 | source.sendTranslatableMessage( 73 | "command.commands.nickname.set.success_other", 74 | new Object[]{player.username, nickname} 75 | ); 76 | source.sendTranslatableMessage( 77 | player, 78 | "command.commands.nickname.set.success_receiver", 79 | new Object[]{nickname} 80 | ); 81 | } 82 | 83 | return 1; 84 | } 85 | })))).then(ArgumentBuilderRequired 86 | .argument("nickname", ArgumentTypeString.string()) 87 | .executes((c) -> { 88 | CommandSource source = (CommandSource) c.getSource(); 89 | String nickname = (String) c.getArgument("nickname", String.class); 90 | if (nickname.length() > Essentials.NickLength) { 91 | throw NICKNAME_TOO_LARGE.create(); 92 | } else if (nickname.isEmpty()) { 93 | throw NICKNAME_TOO_SMALL.create(); 94 | } else { 95 | PlayerServer player = (PlayerServer) source.getSender(); 96 | if (player == null) { 97 | throw CommandExceptions.notInWorld().create(); 98 | } else { 99 | player.nickname = nickname; 100 | player.hadNicknameSet = true; 101 | player.mcServer.playerList.updatePlayerProfile( 102 | player.username, 103 | player.nickname, 104 | player.uuid, 105 | player.score, 106 | player.chatColor, 107 | true, 108 | player.isOperator() 109 | ); 110 | source.sendTranslatableMessage( 111 | "command.commands.nickname.set.success", 112 | new Object[]{nickname} 113 | ); 114 | return 1; 115 | } 116 | } 117 | })))).then(ArgumentBuilderLiteral 118 | .literal("get") 119 | .then(ArgumentBuilderRequired.argument("target", ArgumentTypeUser.user()).executes((c) -> { 120 | CommandSource source = (CommandSource) c.getSource(); 121 | PlayerServer player = c.getArgument("target", PlayerServer.class); 122 | source.sendTranslatableMessage( 123 | "command.commands.nickname.get.success", 124 | new Object[]{player.username, player.nickname} 125 | ); 126 | return 1; 127 | })))).then(((ArgumentBuilderLiteral) ArgumentBuilderLiteral 128 | .literal("reset") 129 | .then(((ArgumentBuilderRequired) ArgumentBuilderRequired 130 | .argument("target", ArgumentTypeUser.user()) 131 | .requires(source -> ((CommandSource) source).hasAdmin())).executes(c -> { 132 | CommandSource source = (CommandSource) c.getSource(); 133 | PlayerServer player = (PlayerServer) c.getArgument("target", PlayerServer.class); 134 | player.nickname = ""; 135 | player.hadNicknameSet = false; 136 | player.mcServer.playerList.updatePlayerProfile( 137 | player.username, 138 | player.nickname, 139 | player.uuid, 140 | player.score, 141 | player.chatColor, 142 | true, 143 | player.isOperator() 144 | ); 145 | if (source.getSender() == player) { 146 | source.sendTranslatableMessage("command.commands.nickname.reset.success", new Object[0]); 147 | } else { 148 | source.sendTranslatableMessage( 149 | "command.commands.nickname.reset.success_other", 150 | new Object[]{player.username} 151 | ); 152 | source.sendTranslatableMessage( 153 | player, 154 | "command.commands.nickname.reset.success_receiver", 155 | new Object[0] 156 | ); 157 | } 158 | 159 | return 1; 160 | }))).executes((c) -> { 161 | CommandSource source = (CommandSource) c.getSource(); 162 | PlayerServer player = (PlayerServer) source.getSender(); 163 | if (player == null) { 164 | throw CommandExceptions.notInWorld().create(); 165 | } else { 166 | player.nickname = ""; 167 | player.hadNicknameSet = false; 168 | player.mcServer.playerList.updatePlayerProfile( 169 | player.username, 170 | player.nickname, 171 | player.uuid, 172 | player.score, 173 | player.chatColor, 174 | true, 175 | player.isOperator() 176 | ); 177 | source.sendTranslatableMessage( 178 | "command.commands.nickname.reset.success", 179 | new Object[]{player.username} 180 | ); 181 | return 1; 182 | } 183 | }))); 184 | dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral 185 | .literal("nick") 186 | .redirect(command)); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/utils/PlayerData.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.utils; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import net.minecraft.core.entity.player.Player; 6 | import net.minecraft.core.net.command.TextFormatting; 7 | import net.minecraft.core.player.gamemode.Gamemode; 8 | import net.minecraft.server.MinecraftServer; 9 | import org.apache.commons.lang3.tuple.Pair; 10 | import wyspr.BTE.Essentials; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.io.Serializable; 15 | import java.nio.charset.StandardCharsets; 16 | import java.nio.file.Files; 17 | import java.time.Duration; 18 | import java.time.Instant; 19 | import java.util.*; 20 | 21 | public class PlayerData { 22 | private final File saveFile; 23 | private final Player player; 24 | public TPManager tpManager; 25 | public Homes homes; 26 | public boolean craftCommandOpen = false; 27 | public boolean godMode = false; 28 | public boolean muted; 29 | public boolean vanished; 30 | public Gamemode vanishedGamemode; 31 | public float speed; 32 | public float flySpeed; 33 | 34 | public PlayerData(Player player) { 35 | this.player = player; 36 | this.saveFile = new File(Essentials.PLAYER_DIR.toFile(), player.uuid + ".json"); 37 | this.tpManager = new TPManager(); 38 | this.homes = new Homes(); 39 | 40 | if (!saveFile.exists()) { 41 | this.save(); 42 | } 43 | this.load(); 44 | } 45 | 46 | private void save() { 47 | Gson gson = new GsonBuilder() 48 | .setPrettyPrinting() 49 | .registerTypeAdapter(Instant.class, new InstantTypeAdapter()) 50 | .create(); 51 | PlayerDataFile dataFile = new PlayerDataFile(); 52 | dataFile.backPos = this.tpManager.backPos; 53 | dataFile.lastTPTime = this.tpManager.lastTPTime; 54 | dataFile.homes = this.homes; 55 | dataFile.vanished = this.vanished; 56 | dataFile.vanishedGamemode = this.vanishedGamemode; 57 | dataFile.muted = this.muted; 58 | String json = gson.toJson(dataFile); 59 | try { 60 | Files.write(saveFile.toPath(), json.getBytes(StandardCharsets.UTF_8)); 61 | } catch (IOException e) { 62 | Essentials.LOGGER.error("Error writing file: {}", e.getMessage()); 63 | } 64 | } 65 | 66 | private void load() { 67 | Gson gson = new GsonBuilder() 68 | .registerTypeAdapter(Instant.class, new InstantTypeAdapter()) 69 | .create(); 70 | try { 71 | String json = new String( 72 | Files.readAllBytes(saveFile.toPath()), 73 | StandardCharsets.UTF_8 74 | ); 75 | PlayerDataFile loadedInfo = gson.fromJson(json, PlayerDataFile.class); 76 | 77 | tpManager.lastTPTime = loadedInfo.lastTPTime; 78 | tpManager.backPos = loadedInfo.backPos; 79 | homes = new Homes().from(loadedInfo.homes); 80 | muted = loadedInfo.muted; 81 | vanished = loadedInfo.vanished; 82 | } catch (IOException e) { 83 | Essentials.LOGGER.error("Error reading file: {}", e.getMessage()); 84 | } 85 | } 86 | 87 | public static PlayerData get(Player player) { 88 | return ((Interface) player).betterThanEssentials$getPlayerData(player); 89 | } 90 | 91 | public static void set(Player player) { 92 | ((Interface) player).betterThanEssentials$setPlayerData(player); 93 | } 94 | 95 | public boolean toggleVanished() { 96 | if (vanished) { 97 | vanished = false; 98 | player.setGamemode(vanishedGamemode); 99 | MinecraftServer.getInstance().playerList.sendEncryptedChatToAllPlayers(player.getDisplayName() + TextFormatting.YELLOW + " joined the game."); 100 | } else { 101 | vanishedGamemode = player.gamemode; 102 | vanished = true; 103 | MinecraftServer.getInstance().playerList.sendEncryptedChatToAllPlayers(player.getDisplayName() + TextFormatting.YELLOW + " left the game."); 104 | player.setGamemode(Gamemode.spectator); 105 | } 106 | this.save(); 107 | return vanished; 108 | } 109 | 110 | public void removeVanish() { 111 | vanished = false; 112 | MinecraftServer.getInstance().playerList.sendEncryptedChatToAllPlayers(player.getDisplayName() + TextFormatting.YELLOW + " joined the game."); 113 | save(); 114 | } 115 | 116 | public void mute() { 117 | muted = true; 118 | save(); 119 | } 120 | 121 | public void unmute() { 122 | muted = false; 123 | save(); 124 | } 125 | 126 | public boolean toggleGodMode() { 127 | godMode = !godMode; 128 | return godMode; 129 | } 130 | 131 | public interface Interface { 132 | PlayerData betterThanEssentials$getPlayerData(Player player); 133 | 134 | void betterThanEssentials$setPlayerData(Player player); 135 | } 136 | 137 | private static class PlayerDataFile implements Serializable { 138 | private static final long serialVersionUID = 1L; 139 | // Ensures version compatibility during deserialization 140 | public Instant lastTPTime; 141 | public WorldPosition backPos; 142 | public HashMap homes; 143 | public boolean muted; 144 | public boolean vanished; 145 | public Gamemode vanishedGamemode; 146 | } 147 | 148 | public class TPManager { 149 | private final ArrayList TPARequestsOrder = new ArrayList<>(); 150 | private final HashMap TPARequests = new HashMap<>(); 151 | private Instant lastTPTime; 152 | private WorldPosition backPos; 153 | 154 | public TPManager() { 155 | this.lastTPTime = Instant 156 | .now() 157 | .minus(Duration.ofSeconds(Essentials.TPTimeout)); 158 | this.backPos = new WorldPosition(player.x, player.y, player.z, player.dimension); 159 | } 160 | 161 | public boolean canTP() { 162 | return TPCooldown() == 0; 163 | } 164 | 165 | /// Returns 0 if tp is available 166 | public int TPCooldown() { 167 | Instant now = Instant.now(); 168 | Instant TPAvailable = lastTPTime.plus(Duration.ofSeconds(Essentials.TPTimeout)); 169 | 170 | if (now.isAfter(TPAvailable)) { 171 | return 0; 172 | } 173 | 174 | return Math.toIntExact(Duration 175 | .between(now, TPAvailable) 176 | .getSeconds()); 177 | } 178 | 179 | public WorldPosition getLastPos() { 180 | return backPos; 181 | } 182 | 183 | public void updateBackPos() { 184 | lastTPTime = Instant.now(); 185 | backPos = new WorldPosition(player.x, player.y, player.z, player.dimension); 186 | save(); 187 | } 188 | 189 | public boolean atNewPos() { 190 | WorldPosition newPos = new WorldPosition(player.x, player.y, player.z, player.dimension); 191 | return !(newPos.equals(backPos)); 192 | } 193 | 194 | /** 195 | * Send a teleport request from a user. 196 | *
197 | * If a user with a pending request sends a new request of a different type (TPA vs TPAHERE) 198 | * the old request is removed and the new one is moved to the front of the list. 199 | * 200 | * @param username String 201 | * @param type TPARequestType 202 | * @return true if request was sent, false if that user has a pending request or is offline 203 | */ 204 | public boolean sendTPARequest(String username, TPARequestType type) { 205 | if (TPARequests.get(username) == type) { 206 | return false; 207 | } 208 | TPARequestsOrder.remove(username); 209 | TPARequestsOrder.add(username); 210 | TPARequests.put(username, type); 211 | return true; 212 | } 213 | 214 | public Pair getNewestRequest() { 215 | // Get the index of the newest request 216 | int lastIndex = TPARequests.size() - 1; 217 | 218 | // Check if there are any requests 219 | if (lastIndex >= 0) { 220 | String lastRequestName = TPARequestsOrder.get(lastIndex); 221 | TPARequestType req = TPARequests.get(lastRequestName); 222 | 223 | return Pair.of(lastRequestName, req); 224 | } else { 225 | return null; 226 | } 227 | } 228 | 229 | public List getAllRequests() { 230 | if (hasNoRequests()) { 231 | return Collections.singletonList(TextFormatting.YELLOW + "You don't have any requests."); 232 | } 233 | ArrayList out = new ArrayList<>(); 234 | 235 | for (String username : TPARequestsOrder) { 236 | TPARequestType type = TPARequests.get(username); 237 | 238 | out.add(TextFormatting.ORANGE + "[ " + TextFormatting.LIGHT_BLUE + username + " " + TextFormatting.ORANGE + "| " + TextFormatting.YELLOW + type.toString() + TextFormatting.ORANGE + " ]" + TextFormatting.RESET); 239 | } 240 | 241 | return out; 242 | } 243 | 244 | public boolean hasNoRequests() { 245 | return TPARequests.isEmpty(); 246 | } 247 | 248 | public boolean hasRequestFrom(String username) { 249 | return TPARequests.containsKey(username); 250 | } 251 | 252 | public TPARequestType getRequest(String username) { 253 | return TPARequests.get(username); 254 | } 255 | 256 | public void removeRequest(String username) { 257 | TPARequestsOrder.remove(username); 258 | TPARequests.remove(username); 259 | } 260 | } 261 | 262 | public class Homes extends HashMap { 263 | public Homes from(HashMap map) { 264 | for (String key : map.keySet()) { 265 | this.put(key, map.get(key)); 266 | } 267 | return this; 268 | } 269 | 270 | public int getHomesAmount() { 271 | return this.size(); 272 | } 273 | 274 | /** 275 | * @return true if the home was added, false if the home exists. 276 | */ 277 | public boolean setHome(Player p, String homeName) { 278 | if (this.containsKey(homeName)) { 279 | return false; 280 | } 281 | 282 | this.put(homeName, new WorldPosition(p.x, p.y, p.z, p.dimension)); 283 | 284 | save(); 285 | return true; 286 | } 287 | 288 | /** 289 | * @return true if the home was removed, false if the home does not exist. 290 | */ 291 | public boolean delHome(String homeName) { 292 | if (!this.containsKey(homeName)) { 293 | return false; 294 | } 295 | 296 | this.remove(homeName); 297 | save(); 298 | return true; 299 | } 300 | 301 | /** 302 | * @return An Optional containing the HomePosition for the player, or an empty Optional if it does not exist. 303 | */ 304 | public Optional getHomePos(String homeName) { 305 | return Optional.ofNullable(this.get(homeName)); 306 | } 307 | 308 | /** 309 | * @return An ArrayList of home names for the player, 310 | * or an empty ArrayList if the player has no homes. 311 | */ 312 | public List getHomesList() { 313 | return new ArrayList<>(this.keySet()); 314 | } 315 | 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /src/main/java/wyspr/BTE/mixins/EntityFishingBobberMixin.java: -------------------------------------------------------------------------------- 1 | package wyspr.BTE.mixins; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.core.block.Blocks; 6 | import net.minecraft.core.block.material.Material; 7 | import net.minecraft.core.entity.Entity; 8 | import net.minecraft.core.entity.EntityFishingBobber; 9 | import net.minecraft.core.entity.MobPathfinder; 10 | import net.minecraft.core.entity.player.Player; 11 | import net.minecraft.core.item.ItemStack; 12 | import net.minecraft.core.item.Items; 13 | import net.minecraft.core.util.helper.DamageType; 14 | import net.minecraft.core.util.helper.MathHelper; 15 | import net.minecraft.core.util.phys.AABB; 16 | import net.minecraft.core.util.phys.HitResult; 17 | import net.minecraft.core.util.phys.Vec3; 18 | import net.minecraft.core.world.World; 19 | import org.jetbrains.annotations.Nullable; 20 | import org.spongepowered.asm.mixin.Mixin; 21 | import org.spongepowered.asm.mixin.Overwrite; 22 | import org.spongepowered.asm.mixin.Shadow; 23 | import wyspr.BTE.Essentials; 24 | 25 | import java.util.List; 26 | 27 | @Environment(EnvType.SERVER) @Mixin(value = EntityFishingBobber.class, remap = false) public abstract class EntityFishingBobberMixin extends Entity { 28 | @Shadow 29 | public Player owner; 30 | @Shadow 31 | public Entity hookedEntity; 32 | @Shadow 33 | private int xTile; 34 | @Shadow 35 | private int yTile; 36 | @Shadow 37 | private int zTile; 38 | @Shadow 39 | private int ticksInAir; 40 | @Shadow 41 | private int ticksCatchable; 42 | @Shadow 43 | private int lerpSteps; 44 | @Shadow 45 | private double lerpX; 46 | @Shadow 47 | private double lerpY; 48 | @Shadow 49 | private double lerpZ; 50 | @Shadow 51 | private double lerpYRot; 52 | @Shadow 53 | private double lerpXRot; 54 | 55 | public EntityFishingBobberMixin(@Nullable World world) { 56 | super(world); 57 | } 58 | 59 | /** 60 | * @author wyspr 61 | * @reason Allow modification of catch timer 62 | */ 63 | @Overwrite 64 | public void tick() { 65 | super.tick(); 66 | if (this.lerpSteps > 0) { 67 | double d = this.x + (this.lerpX - this.x) / (double) this.lerpSteps; 68 | double d1 = this.y + (this.lerpY - this.y) / (double) this.lerpSteps; 69 | double d2 = this.z + (this.lerpZ - this.z) / (double) this.lerpSteps; 70 | 71 | double d4; 72 | for (d4 = this.lerpYRot - (double) this.yRot; d4 < (double) -180.0F; d4 += 360.0F) { 73 | } 74 | 75 | while (d4 >= (double) 180.0F) { 76 | d4 -= 360.0F; 77 | } 78 | 79 | this.yRot = (float) ((double) this.yRot + d4 / (double) this.lerpSteps); 80 | this.xRot 81 | = (float) ((double) this.xRot + (this.lerpXRot - (double) this.xRot) / (double) this.lerpSteps); 82 | --this.lerpSteps; 83 | this.setPos(d, d1, d2); 84 | this.setRot(this.yRot, this.xRot); 85 | } else { 86 | if (!this.world.isClientSide) { 87 | ItemStack heldPlayerItem = this.owner.getCurrentEquippedItem(); 88 | if (this.owner.removed || !this.owner.isAlive() || heldPlayerItem == null || heldPlayerItem.getItem() != Items.TOOL_FISHINGROD || this.distanceToSqr( 89 | this.owner) > (double) 1024.0F) { 90 | this.remove(); 91 | this.owner.bobberEntity = null; 92 | return; 93 | } 94 | 95 | if (this.hookedEntity != null) { 96 | if (!this.hookedEntity.removed) { 97 | this.x = this.hookedEntity.x; 98 | this.y = this.hookedEntity.bb.minY + (double) this.hookedEntity.bbHeight * 0.8; 99 | this.z = this.hookedEntity.z; 100 | if (this.hookedEntity instanceof MobPathfinder) { 101 | ((MobPathfinder) this.hookedEntity).setTarget(this.owner); 102 | } 103 | 104 | double dx = this.owner.x - this.x; 105 | double dy = this.owner.y - this.y; 106 | double dz = this.owner.z - this.z; 107 | double distance = MathHelper.sqrt(dx * dx + dy * dy + dz * dz); 108 | if (distance > (double) 10.0F) { 109 | double scale = 0.01; 110 | Entity var10000 = this.hookedEntity; 111 | var10000.xd += dx * scale; 112 | var10000 = this.hookedEntity; 113 | var10000.yd += dy * scale; 114 | var10000 = this.hookedEntity; 115 | var10000.zd += dz * scale; 116 | } 117 | 118 | return; 119 | } 120 | 121 | this.hookedEntity = null; 122 | } 123 | } 124 | 125 | if (this.isInGround()) { 126 | if (this.world.getBlockId(this.xTile, this.yTile, this.zTile) == Blocks.ROPE.id()) { 127 | this.x = (double) this.xTile + (double) 0.5F; 128 | this.y = (double) this.yTile + (double) 0.5F; 129 | this.z = (double) this.zTile + (double) 0.5F; 130 | return; 131 | } 132 | 133 | this.setInGround(false); 134 | this.xd *= this.random.nextFloat() * 0.2F; 135 | this.yd *= this.random.nextFloat() * 0.2F; 136 | this.zd *= this.random.nextFloat() * 0.2F; 137 | this.ticksInAir = 0; 138 | this.ticksCatchable = 0; 139 | } 140 | 141 | ++this.ticksInAir; 142 | Vec3 currentPos = Vec3.getTempVec3(this.x, this.y, this.z); 143 | Vec3 nextPos = Vec3.getTempVec3(this.x + this.xd, this.y + this.yd, this.z + this.zd); 144 | HitResult clip = this.world.checkBlockCollisionBetweenPoints(currentPos, nextPos); 145 | currentPos = Vec3.getTempVec3(this.x, this.y, this.z); 146 | nextPos = Vec3.getTempVec3(this.x + this.xd, this.y + this.yd, this.z + this.zd); 147 | if (clip != null) { 148 | nextPos = Vec3.getTempVec3(clip.location.x, clip.location.y, clip.location.z); 149 | if (clip.hitType == HitResult.HitType.TILE && this.world.getBlockId( 150 | clip.x, 151 | clip.y, 152 | clip.z 153 | ) == Blocks.ROPE.id()) { 154 | this.setInGround(true); 155 | this.xTile = clip.x; 156 | this.yTile = clip.y; 157 | this.zTile = clip.z; 158 | } 159 | } 160 | 161 | Entity entity = null; 162 | List list = this.world.getEntitiesWithinAABBExcludingEntity( 163 | this, 164 | this.bb.expand(this.xd, this.yd, this.zd).grow(1.0F, 1.0F, 1.0F) 165 | ); 166 | double d3 = 0.0F; 167 | 168 | for (Entity e : list) { 169 | if (e.isPickable() && (e != this.owner || this.ticksInAir >= 5)) { 170 | float f2 = 0.3F; 171 | AABB aabb = e.bb.grow(f2, f2, f2); 172 | HitResult newHitResult = aabb.clip(currentPos, nextPos); 173 | if (newHitResult != null) { 174 | double d6 = currentPos.distanceTo(newHitResult.location); 175 | if (d6 < d3 || d3 == (double) 0.0F) { 176 | entity = e; 177 | d3 = d6; 178 | } 179 | } 180 | } 181 | } 182 | 183 | if (entity != null) { 184 | clip = new HitResult(entity); 185 | } 186 | 187 | if (clip != null && clip.entity != null && clip.entity.hurt(this.owner, 0, DamageType.COMBAT)) { 188 | this.hookedEntity = clip.entity; 189 | } 190 | 191 | this.move(this.xd, this.yd, this.zd); 192 | float f = MathHelper.sqrt(this.xd * this.xd + this.zd * this.zd); 193 | this.yRot = (float) (Math.atan2(this.xd, this.zd) * (double) 180.0F / Math.PI); 194 | 195 | for (this.xRot = (float) (Math.atan2( 196 | this.yd, 197 | f 198 | ) * (double) 180.0F / Math.PI); this.xRot - this.xRotO < -180.0F; this.xRotO -= 360.0F) { 199 | } 200 | 201 | while (this.xRot - this.xRotO >= 180.0F) { 202 | this.xRotO += 360.0F; 203 | } 204 | 205 | while (this.yRot - this.yRotO < -180.0F) { 206 | this.yRotO -= 360.0F; 207 | } 208 | 209 | while (this.yRot - this.yRotO >= 180.0F) { 210 | this.yRotO += 360.0F; 211 | } 212 | 213 | this.xRot = this.xRotO + (this.xRot - this.xRotO) * 0.2F; 214 | this.yRot = this.yRotO + (this.yRot - this.yRotO) * 0.2F; 215 | float movementScale = 0.92F; 216 | if (this.onGround || this.horizontalCollision) { 217 | movementScale = 0.5F; 218 | } 219 | 220 | int k = 5; 221 | double d5 = 0.0F; 222 | 223 | for (int l = 0; l < k; ++l) { 224 | double d8 225 | = this.bb.minY + (this.bb.maxY - this.bb.minY) * (double) l / (double) k - (double) 0.125F + (double) 0.125F; 226 | double d9 227 | = this.bb.minY + (this.bb.maxY - this.bb.minY) * (double) (l + 1) / (double) k - (double) 0.125F + (double) 0.125F; 228 | AABB axisalignedbb1 = AABB.getTemporaryBB( 229 | this.bb.minX, 230 | d8, 231 | this.bb.minZ, 232 | this.bb.maxX, 233 | d9, 234 | this.bb.maxZ 235 | ); 236 | if (this.world.isAABBInMaterial(axisalignedbb1, Material.water)) { 237 | d5 += (double) 1.0F / (double) k; 238 | } 239 | } 240 | 241 | if (d5 > (double) 0.0F) { 242 | if (this.ticksCatchable > 0) { 243 | --this.ticksCatchable; 244 | } else { 245 | int catchRate = 500; 246 | int rainRate = 0; 247 | int algaeRate = 0; 248 | if (this.world.canBlockBeRainedOn( 249 | MathHelper.floor(this.x), 250 | MathHelper.floor(this.y) + 1, 251 | MathHelper.floor(this.z) 252 | )) { 253 | rainRate = 200; 254 | } 255 | 256 | if (this.world.getBlockId( 257 | MathHelper.floor(this.x), 258 | MathHelper.floor(this.y) + 1, 259 | MathHelper.floor(this.z) 260 | ) == Blocks.ALGAE.id()) { 261 | algaeRate = 100; 262 | } 263 | 264 | catchRate = catchRate - rainRate - algaeRate; 265 | if (this.random.nextInt(catchRate) == 0) { 266 | // CODE MODIFICATION 267 | // from: 268 | // this.ticksCatchable = this.random.nextInt(30) + 10; 269 | // to: 270 | if (Essentials.AddedTicksCatchable <= -40) { 271 | this.remove(); 272 | } else { 273 | this.ticksCatchable 274 | = this.random.nextInt(30) + 10 + Essentials.AddedTicksCatchable; 275 | } 276 | // END 277 | this.yd -= 0.2; 278 | this.world.playSoundAtEntity( 279 | null, 280 | this, 281 | "random.splash", 282 | 0.25F, 283 | 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F 284 | ); 285 | float f3 = (float) MathHelper.floor(this.bb.minY); 286 | 287 | for (int i1 = 0; (float) i1 < 1.0F + this.bbWidth * 20.0F; ++i1) { 288 | double xOff = (this.random.nextFloat() * 2.0F - 1.0F) * this.bbWidth; 289 | double zOff = (this.random.nextFloat() * 2.0F - 1.0F) * this.bbWidth; 290 | this.world.spawnParticle( 291 | "bubble", 292 | this.x + xOff, 293 | f3 + 1.0F, 294 | this.z + zOff, 295 | this.xd, 296 | this.yd - (double) (this.random.nextFloat() * 0.2F), 297 | this.zd, 298 | 0 299 | ); 300 | } 301 | 302 | for (int j1 = 0; (float) j1 < 1.0F + this.bbWidth * 20.0F; ++j1) { 303 | double xOff = (this.random.nextFloat() * 2.0F - 1.0F) * this.bbWidth; 304 | double zOff = (this.random.nextFloat() * 2.0F - 1.0F) * this.bbWidth; 305 | this.world.spawnParticle( 306 | "splash", 307 | this.x + xOff, 308 | f3 + 1.0F, 309 | this.z + zOff, 310 | this.xd, 311 | this.yd, 312 | this.zd, 313 | 0 314 | ); 315 | } 316 | } 317 | } 318 | } 319 | 320 | if (this.ticksCatchable > 0) { 321 | this.yd 322 | -= (double) (this.random.nextFloat() * this.random.nextFloat() * this.random.nextFloat()) * 0.2; 323 | } 324 | 325 | double d7 = d5 * (double) 2.0F - (double) 1.0F; 326 | this.yd += 0.04 * d7; 327 | if (d5 > (double) 0.0F) { 328 | movementScale = (float) ((double) movementScale * 0.9); 329 | this.yd *= 0.8; 330 | } 331 | 332 | this.xd *= movementScale; 333 | this.yd *= movementScale; 334 | this.zd *= movementScale; 335 | this.setPos(this.x, this.y, this.z); 336 | } 337 | } 338 | 339 | @Shadow 340 | public boolean isInGround() { 341 | return true; 342 | } 343 | 344 | @Shadow 345 | public void setInGround(boolean b) {} 346 | } 347 | --------------------------------------------------------------------------------