diff --git a/core/build.gradle b/core/build.gradle index 797ef6a6..6440bed5 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -24,6 +24,8 @@ dependencies { includeLibs group: 'com.google.inject', name: 'guice', version:'5.0.1' implementation group: 'com.google.inject', name: 'guice', version:'5.0.1' implementation group: 'com.google.guava', name: 'guava', version: '30.1.1-jre' + implementation group: 'io.netty', name: 'netty-buffer', version: '4.1.53.Final' + implementation group: 'io.netty', name: 'netty-codec', version: '4.1.53.Final' } jar { diff --git a/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsCore.java b/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsCore.java index a359d707..3a055c99 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsCore.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsCore.java @@ -4,6 +4,7 @@ import com.google.inject.Injector; import com.sekwah.advancedportals.core.commands.CommandWithSubCommands; import com.sekwah.advancedportals.core.commands.subcommands.desti.CreateDestiSubCommand; +import com.sekwah.advancedportals.core.commands.subcommands.desti.ListDestiSubCommand; import com.sekwah.advancedportals.core.commands.subcommands.desti.RemoveDestiSubCommand; import com.sekwah.advancedportals.core.commands.subcommands.portal.*; import com.sekwah.advancedportals.core.connector.commands.CommandRegister; @@ -99,7 +100,8 @@ private void registerPortalCommand(CommandRegister commandRegister) { this.portalCommand.registerSubCommand("endgatewayblock", new EndGatewayBlockSubCommand()); this.portalCommand.registerSubCommand("create", new CreatePortalSubCommand()); this.portalCommand.registerSubCommand("remove", new RemovePortalSubCommand()); - this.portalCommand.registerSubCommand("list", new ListSubCommand()); + this.portalCommand.registerSubCommand("list", new ListPortalsSubCommand()); + this.portalCommand.registerSubCommand("debug", new DebugPortalsSubCommand()); commandRegister.registerCommand("portal", this.portalCommand); } @@ -108,6 +110,7 @@ private void registerDestinationCommand(CommandRegister commandRegister) { this.destiCommand = new CommandWithSubCommands(this); this.destiCommand.registerSubCommand("create", new CreateDestiSubCommand()); this.destiCommand.registerSubCommand("remove", new RemoveDestiSubCommand()); + this.destiCommand.registerSubCommand("list", new ListDestiSubCommand()); commandRegister.registerCommand("destination", this.destiCommand); } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/commands/CommandWithSubCommands.java b/core/src/main/java/com/sekwah/advancedportals/core/commands/CommandWithSubCommands.java index b02582b8..fc0771f1 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/commands/CommandWithSubCommands.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/commands/CommandWithSubCommands.java @@ -65,7 +65,7 @@ public void onCommand(CommandSenderContainer sender, String commandExecuted, Str if(this.subCommandRegistry.isArgRegistered(subCommand)) { sender.sendMessage(""); var helpTitle = Lang.centeredTitle(Lang.translateInsertVariables("command.help.subcommandheader", - command, helpPage, pages)); + command, subCommand)); sender.sendMessage(helpTitle); sender.sendMessage("\u00A77" + this.getSubCommand(subCommand).getDetailedHelpText()); } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/CreateDestiSubCommand.java b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/CreateDestiSubCommand.java index 57270c81..8379832b 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/CreateDestiSubCommand.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/CreateDestiSubCommand.java @@ -30,7 +30,7 @@ public void onCommand(CommandSenderContainer sender, String[] args) { if(args.length > 1) { PlayerContainer player = sender.getPlayerContainer(); if(player == null) { - sender.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.createdesti.console")); + sender.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.create.destination.console")); return; } ArrayList destinationTags = TagReader.getTagsFromArgs(args); @@ -48,7 +48,7 @@ public void onCommand(CommandSenderContainer sender, String[] args) { sender.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.error.noname")); return; } - sender.sendMessage(Lang.centeredTitle(Lang.translate("command.createdesti.prep"))); + sender.sendMessage(Lang.centeredTitle(Lang.translate("command.create.destination.prep"))); sender.sendMessage(""); sender.sendMessage(Lang.translate("command.create.tags")); @@ -59,11 +59,11 @@ public void onCommand(CommandSenderContainer sender, String[] args) { sender.sendMessage(""); Destination destination = destinationServices.createDesti(player, player.getLoc(), destinationTags); if(destination != null) { - sender.sendMessage(Lang.translate("messageprefix.positive") + Lang.translate("command.createdesti.complete")); + sender.sendMessage(Lang.translate("messageprefix.positive") + Lang.translate("command.create.destination.complete")); } else { sender.sendMessage(""); - sender.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.createdesti.error")); + sender.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.create.destination.error")); } } else { @@ -85,11 +85,11 @@ protected List getRelatedTags() { @Override public String getBasicHelpText() { - return Lang.translate("command.createdesti.help"); + return Lang.translate("command.create.destination.help"); } @Override public String getDetailedHelpText() { - return Lang.translate("command.createdesti.detailedhelp"); + return Lang.translate("command.create.destination.detailedhelp"); } } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/ListDestiSubCommand.java b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/ListDestiSubCommand.java new file mode 100644 index 00000000..e1de4201 --- /dev/null +++ b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/ListDestiSubCommand.java @@ -0,0 +1,44 @@ +package com.sekwah.advancedportals.core.commands.subcommands.desti; + +import com.google.inject.Inject; +import com.sekwah.advancedportals.core.commands.SubCommand; +import com.sekwah.advancedportals.core.connector.containers.CommandSenderContainer; +import com.sekwah.advancedportals.core.services.DestinationServices; +import com.sekwah.advancedportals.core.services.PortalServices; +import com.sekwah.advancedportals.core.util.Lang; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ListDestiSubCommand implements SubCommand { + + @Inject + DestinationServices portalServices; + + @Override + public void onCommand(CommandSenderContainer sender, String[] args) { + sender.sendMessage(Lang.translate("messageprefix.positive") + Lang.translate("command.destination.list") + + " " + portalServices.getDestinations().stream().sorted().collect(Collectors.joining(", "))); + } + + @Override + public boolean hasPermission(CommandSenderContainer sender) { + return true; + } + + @Override + public List onTabComplete(CommandSenderContainer sender, String[] args) { + return null; + } + + @Override + public String getBasicHelpText() { + return Lang.translate("command.destination.list.help"); + } + + @Override + public String getDetailedHelpText() { + return Lang.translate("command.destination.list.help"); + } +} diff --git a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/CreatePortalSubCommand.java b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/CreatePortalSubCommand.java index cd24becb..d40ed386 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/CreatePortalSubCommand.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/CreatePortalSubCommand.java @@ -5,6 +5,7 @@ import com.sekwah.advancedportals.core.commands.subcommands.reusable.CreateTaggedSubCommand; import com.sekwah.advancedportals.core.connector.containers.CommandSenderContainer; import com.sekwah.advancedportals.core.connector.containers.PlayerContainer; +import com.sekwah.advancedportals.core.destination.Destination; import com.sekwah.advancedportals.core.registry.TagRegistry; import com.sekwah.advancedportals.core.serializeddata.DataTag; import com.sekwah.advancedportals.core.permissions.PortalPermissions; @@ -40,7 +41,28 @@ public void onCommand(CommandSenderContainer sender, String[] args) { // Find the tag with the "name" NAME DataTag nameTag = portalTags.stream().findFirst().filter(tag -> tag.NAME.equals("name")).orElse(null); - AdvancedPortal portal = portalServices.createPortal(nameTag == null ? null : nameTag.VALUES[0], player, portalTags); + // If the tag is null, check if arg[1] has a : to check it's not a tag. + if(nameTag == null && !args[1].contains(":")) { + nameTag = new DataTag("name", args[1]); + portalTags.add(nameTag); + } + + if (nameTag == null) { + sender.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.error.noname")); + return; + } + + sender.sendMessage(Lang.centeredTitle(Lang.translate("command.create.portal.prep"))); + sender.sendMessage(""); + sender.sendMessage(Lang.translate("command.create.tags")); + + if(!portalTags.isEmpty()) { + this.filterAndProcessTags(portalTags); + this.printTags(sender, portalTags); + } + sender.sendMessage(""); + + AdvancedPortal portal = portalServices.createPortal(player, portalTags); if(portal != null) { sender.sendMessage(Lang.translate("messageprefix.positive") + Lang.translate("command.create.complete")); sender.sendMessage(Lang.translate("command.create.tags")); diff --git a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/DebugPortalsSubCommand.java b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/DebugPortalsSubCommand.java new file mode 100644 index 00000000..d3439697 --- /dev/null +++ b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/DebugPortalsSubCommand.java @@ -0,0 +1,106 @@ +package com.sekwah.advancedportals.core.commands.subcommands.portal; + +import com.google.inject.Inject; +import com.sekwah.advancedportals.core.commands.SubCommand; +import com.sekwah.advancedportals.core.connector.containers.CommandSenderContainer; +import com.sekwah.advancedportals.core.connector.containers.PlayerContainer; +import com.sekwah.advancedportals.core.serializeddata.BlockLocation; +import com.sekwah.advancedportals.core.serializeddata.PlayerTempData; +import com.sekwah.advancedportals.core.services.PortalTempDataServices; +import com.sekwah.advancedportals.core.util.Debug; +import com.sekwah.advancedportals.core.util.FriendlyDataOutput; +import com.sekwah.advancedportals.core.util.Lang; + +import java.awt.*; +import java.util.List; + +public class DebugPortalsSubCommand implements SubCommand { + + @Inject + PortalTempDataServices tempDataServices; + + @Override + public void onCommand(CommandSenderContainer sender, String[] args) { + sender.sendMessage("Debug"); + if(sender.getPlayerContainer() != null) { + PlayerContainer playerContainer = sender.getPlayerContainer(); + PlayerTempData tempData = tempDataServices.getPlayerTempData(playerContainer); + if(tempData.getPos1() != null) { + Debug.addMarker(sender.getPlayerContainer(), tempData.getPos1(), "Pos1", new Color(0, 255, 0), 1000 * 10); + } + if(tempData.getPos2() != null) { + Debug.addMarker(sender.getPlayerContainer(), tempData.getPos2(), "Pos2", new Color(255, 0, 0), 1000 * 10); + } + + if (tempData.getPos1() != null && tempData.getPos2() != null) { + int minX = Math.min(tempData.getPos1().posX, tempData.getPos2().posX); + int minY = Math.min(tempData.getPos1().posY, tempData.getPos2().posY); + int minZ = Math.min(tempData.getPos1().posZ, tempData.getPos2().posZ); + + int maxX = Math.max(tempData.getPos1().posX, tempData.getPos2().posX); + int maxY = Math.max(tempData.getPos1().posY, tempData.getPos2().posY); + int maxZ = Math.max(tempData.getPos1().posZ, tempData.getPos2().posZ); + + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + if ((x == minX || x == maxX) && (y == minY || y == maxY || z == minZ || z == maxZ) || + (y == minY || y == maxY) && (x == minX || x == maxX || z == minZ || z == maxZ) || + (z == minZ || z == maxZ) && (x == minX || x == maxX || y == minY || y == maxY)) { + + var pos = new BlockLocation(tempData.getPos1().worldName, x, y, z); + if (pos.equals(tempData.getPos1()) || pos.equals(tempData.getPos2())) + continue; + Debug.addMarker(sender.getPlayerContainer(), pos, "", new Color(255, 0, 0, 100), 1000 * 10); + } + } + } + } + } + /*int minX = Math.min(tempData.getPos1().posX, tempData.getPos2().posX); + int minY = Math.min(tempData.getPos1().posY, tempData.getPos2().posY); + int minZ = Math.min(tempData.getPos1().posZ, tempData.getPos2().posZ); + + int maxX = Math.max(tempData.getPos1().posX, tempData.getPos2().posX); + int maxY = Math.max(tempData.getPos1().posY, tempData.getPos2().posY); + int maxZ = Math.max(tempData.getPos1().posZ, tempData.getPos2().posZ); + + FriendlyDataOutput out = new FriendlyDataOutput(); + + out.writeUtf("minecraft:overworld"); + + // Bounding Box + out.writeInt(minX); + out.writeInt(minY); + out.writeInt(minZ); + out.writeInt(maxX); + out.writeInt(maxY); + out.writeInt(maxZ); + + // Count + out.writeInt(0); + + playerContainer.sendPacket("minecraft:debug/structures", out.toByteArray());*/ + } + } + + @Override + public boolean hasPermission(CommandSenderContainer sender) { + return true; + } + + @Override + public List onTabComplete(CommandSenderContainer sender, String[] args) { + return null; + } + + @Override + public String getBasicHelpText() { + return Lang.translate("command.portal.list.debug"); + } + + @Override + public String getDetailedHelpText() { + return Lang.translate("command.portal.list.debug"); + } +} diff --git a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ListSubCommand.java b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ListPortalsSubCommand.java similarity index 83% rename from core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ListSubCommand.java rename to core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ListPortalsSubCommand.java index 4993c502..e83d7a01 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ListSubCommand.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ListPortalsSubCommand.java @@ -10,14 +10,14 @@ import java.util.Map; import java.util.stream.Collectors; -public class ListSubCommand implements SubCommand { +public class ListPortalsSubCommand implements SubCommand { @Inject PortalServices portalServices; @Override public void onCommand(CommandSenderContainer sender, String[] args) { - sender.sendMessage(Lang.translate("messageprefix.positive") + Lang.translate("command.list") + sender.sendMessage(Lang.translate("messageprefix.positive") + Lang.translate("command.portal.list") + " " + portalServices.getPortals().asList().stream().map(Map.Entry::getKey).sorted().collect(Collectors.joining(", "))); } @@ -33,11 +33,11 @@ public List onTabComplete(CommandSenderContainer sender, String[] args) @Override public String getBasicHelpText() { - return Lang.translate("command.list.help"); + return Lang.translate("command.portal.list.help"); } @Override public String getDetailedHelpText() { - return Lang.translate("command.list.help"); + return Lang.translate("command.portal.list.help"); } } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/connector/containers/PlayerContainer.java b/core/src/main/java/com/sekwah/advancedportals/core/connector/containers/PlayerContainer.java index 4b3d5b2e..27bff697 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/connector/containers/PlayerContainer.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/connector/containers/PlayerContainer.java @@ -18,6 +18,8 @@ public interface PlayerContainer { PlayerLocation getLoc(); + BlockLocation getBlockLoc(); + double getEyeHeight(); void teleport(PlayerLocation location); @@ -41,4 +43,6 @@ public interface PlayerContainer { void sendFakeBlockWithData(BlockLocation blockPos, String material, byte data); void giveItem(String material, String itemName, String... itemDescription); + + boolean sendPacket(String channel, byte[] bytes); } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/portal/AdvancedPortal.java b/core/src/main/java/com/sekwah/advancedportals/core/portal/AdvancedPortal.java index d11fafdb..33987903 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/portal/AdvancedPortal.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/portal/AdvancedPortal.java @@ -4,8 +4,8 @@ import com.google.inject.Inject; import com.sekwah.advancedportals.core.connector.containers.PlayerContainer; import com.sekwah.advancedportals.core.registry.TagTarget; +import com.sekwah.advancedportals.core.serializeddata.BlockLocation; import com.sekwah.advancedportals.core.serializeddata.DataTag; -import com.sekwah.advancedportals.core.serializeddata.WorldLocation; import com.sekwah.advancedportals.core.registry.TagRegistry; import com.sekwah.advancedportals.core.warphandler.ActivationData; import com.sekwah.advancedportals.core.warphandler.Tag; @@ -23,10 +23,10 @@ public class AdvancedPortal implements TagTarget { transient TagRegistry tagRegistry; @SerializedName("max") - private WorldLocation maxLoc; + private BlockLocation maxLoc; @SerializedName("min") - private WorldLocation minLoc; + private BlockLocation minLoc; @SerializedName("t") private String[] triggerBlocks = {"PORTAL"}; @@ -34,16 +34,16 @@ public class AdvancedPortal implements TagTarget { @SerializedName("a") private HashMap args = new HashMap<>(); - public AdvancedPortal(WorldLocation maxLoc, WorldLocation minLoc) { + public AdvancedPortal(BlockLocation maxLoc, BlockLocation minLoc) { this.maxLoc = maxLoc; this.minLoc = minLoc; } - public WorldLocation getMaxLoc() { + public BlockLocation getMaxLoc() { return this.maxLoc; } - public WorldLocation getMinLoc() { + public BlockLocation getMinLoc() { return this.minLoc; } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/registry/TagRegistry.java b/core/src/main/java/com/sekwah/advancedportals/core/registry/TagRegistry.java index bfa4d373..a3907138 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/registry/TagRegistry.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/registry/TagRegistry.java @@ -1,6 +1,7 @@ package com.sekwah.advancedportals.core.registry; import com.google.inject.Inject; +import com.google.inject.Singleton; import com.sekwah.advancedportals.core.AdvancedPortalsCore; import com.sekwah.advancedportals.core.warphandler.Tag; @@ -25,6 +26,9 @@ public class TagRegistry { private final Map creationTags = new HashMap<>(); private final Map statusTags = new HashMap<>(); + @Inject + private AdvancedPortalsCore pluginCore; + /** * Portals to trigger when a portal is activated * @@ -58,6 +62,7 @@ public Tag.TagStatus getTagStatusHandler(String arg) { * @return if the tag has been registered or if it already exists. */ public boolean registerTag(Tag tag) { + pluginCore.getModule().getInjector().injectMembers(tag); String tagName = tag.getName(); diff --git a/core/src/main/java/com/sekwah/advancedportals/core/serializeddata/BlockLocation.java b/core/src/main/java/com/sekwah/advancedportals/core/serializeddata/BlockLocation.java index 2676ba7b..680eff8f 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/serializeddata/BlockLocation.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/serializeddata/BlockLocation.java @@ -31,4 +31,8 @@ public BlockLocation(BlockLocation location, Direction direction) { this.posZ = location.posZ + direction.z; } + + public boolean equals(BlockLocation location) { + return location.posX == this.posX && location.posY == this.posY && location.posZ == this.posZ && location.worldName.equals(this.worldName); + } } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/services/DestinationServices.java b/core/src/main/java/com/sekwah/advancedportals/core/services/DestinationServices.java index f4c4e4a8..bccb4352 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/services/DestinationServices.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/services/DestinationServices.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; /** * Handles logic for all destination, this is a transient layer so it should @@ -30,13 +29,8 @@ @Singleton public class DestinationServices { - - private final IDestinationRepository destinationRepository; - @Inject - private DestinationServices(IDestinationRepository destinationRepository) { - this.destinationRepository = destinationRepository; - } + private IDestinationRepository destinationRepository; public Response.Creation create(String name, Destination destination) { if (!destinationRepository.containsKey(name)) { diff --git a/core/src/main/java/com/sekwah/advancedportals/core/services/PortalServices.java b/core/src/main/java/com/sekwah/advancedportals/core/services/PortalServices.java index 890a7297..4b8e3055 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/services/PortalServices.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/services/PortalServices.java @@ -3,9 +3,12 @@ import com.google.common.collect.ImmutableList; import com.google.inject.Inject; import com.sekwah.advancedportals.core.connector.containers.PlayerContainer; +import com.sekwah.advancedportals.core.repository.IDestinationRepository; +import com.sekwah.advancedportals.core.repository.IPortalRepository; import com.sekwah.advancedportals.core.serializeddata.DataTag; import com.sekwah.advancedportals.core.serializeddata.PlayerLocation; import com.sekwah.advancedportals.core.portal.AdvancedPortal; +import com.sekwah.advancedportals.core.serializeddata.PlayerTempData; import com.sekwah.advancedportals.core.util.InfoLogger; import com.sekwah.advancedportals.core.util.Lang; @@ -20,6 +23,12 @@ public class PortalServices { @Inject InfoLogger infoLogger; + @Inject + private IPortalRepository portalRepository; + + @Inject + private PortalTempDataServices portalTempDataServices; + public void loadPortals() { } @@ -40,12 +49,39 @@ public boolean removePortal(String name, PlayerContainer player) { return false; } - public AdvancedPortal createPortal(String name, PlayerContainer player, ArrayList portalTags) { - if(name == null){ - infoLogger.warning("Attempted to make a portal with no name"); + public AdvancedPortal createPortal(PlayerContainer player, ArrayList tags) { + // Find the tag with the "name" NAME + DataTag nameTag = tags.stream().filter(tag -> tag.NAME.equals("name")).findFirst().orElse(null); + + String name = nameTag == null ? null : nameTag.VALUES[0]; + if(nameTag == null) { + player.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("desti.error.noname")); + return null; + } + + if(name == null || name.equals("")) { player.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.error.noname")); return null; } + else if(this.portalRepository.containsKey(name)) { + player.sendMessage(Lang.translate("messageprefix.negative") + Lang.translateInsertVariables("command.error.nametaken", name)); + return null; + } + + PlayerTempData tempData = portalTempDataServices.getPlayerTempData(player); + + if(tempData.getPos1() == null || tempData.getPos2() == null) { + player.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("portal.selector.error.missing")); + return null; + } + + if(!tempData.getPos1().worldName.equals(tempData.getPos2().worldName)) { + player.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("portal.selector.error.worlds")); + return null; + } + + AdvancedPortal portal = new AdvancedPortal(tempData.getPos1(), tempData.getPos2()); + return null; } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/services/PortalTempDataServices.java b/core/src/main/java/com/sekwah/advancedportals/core/services/PortalTempDataServices.java index ab4181eb..b2e99d35 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/services/PortalTempDataServices.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/services/PortalTempDataServices.java @@ -18,7 +18,7 @@ public final class PortalTempDataServices { */ private Map tempDataMap = new HashMap<>(); - private PlayerTempData getPlayerTempData(PlayerContainer player) { + public PlayerTempData getPlayerTempData(PlayerContainer player) { return tempDataMap.computeIfAbsent(player.getUUID(), uuid -> new PlayerTempData()); } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/tags/activation/DestiTag.java b/core/src/main/java/com/sekwah/advancedportals/core/tags/activation/DestiTag.java index 2c516b67..270e668c 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/tags/activation/DestiTag.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/tags/activation/DestiTag.java @@ -1,16 +1,19 @@ package com.sekwah.advancedportals.core.tags.activation; +import com.google.inject.Inject; import com.sekwah.advancedportals.core.connector.containers.PlayerContainer; import com.sekwah.advancedportals.core.registry.TagTarget; +import com.sekwah.advancedportals.core.services.DestinationServices; import com.sekwah.advancedportals.core.util.Lang; import com.sekwah.advancedportals.core.warphandler.ActivationData; import com.sekwah.advancedportals.core.warphandler.Tag; - -import java.util.ArrayList; import java.util.List; public class DestiTag implements Tag.Activation, Tag.AutoComplete { + @Inject + DestinationServices destinationServices; + private final TagType[] tagTypes = new TagType[]{ TagType.PORTAL }; @Override @@ -50,12 +53,6 @@ public boolean activated(TagTarget target, PlayerContainer player, ActivationDat @Override public List autoComplete(String argData) { - List autoCompletes = new ArrayList<>(); - // Get all and filter by the argData - - autoCompletes.add("somedesti"); - autoCompletes.add("hereigo"); - - return autoCompletes; + return destinationServices.getDestinations(); } } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/util/Debug.java b/core/src/main/java/com/sekwah/advancedportals/core/util/Debug.java new file mode 100644 index 00000000..892208bf --- /dev/null +++ b/core/src/main/java/com/sekwah/advancedportals/core/util/Debug.java @@ -0,0 +1,51 @@ +package com.sekwah.advancedportals.core.util; + +import com.sekwah.advancedportals.core.connector.containers.PlayerContainer; +import com.sekwah.advancedportals.core.serializeddata.BlockLocation; +import com.sekwah.advancedportals.core.util.FriendlyDataOutput; + +import java.awt.*; + +public class Debug { + public static boolean addMarker(PlayerContainer player, BlockLocation blockPos, String name, Color color, int milliseconds) { + FriendlyDataOutput out = new FriendlyDataOutput(); + out.writeBlock(blockPos); + out.writeInt(color(color)); + out.writeUtf(name); + out.writeInt(milliseconds); + return player.sendPacket("minecraft:debug/game_test_add_marker", out.toByteArray()); + } + + public static boolean clear(PlayerContainer player) { + FriendlyDataOutput out = new FriendlyDataOutput(); + return player.sendPacket("minecraft:debug/game_test_clear", out.toByteArray()); + } + + public static int color(Color color) { + return color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + } + + public static int color(int r, int g, int b) { + return color(r, g, b, 255); + } + + public static int color(int r, int g, int b, int a) { + return a << 24 | r << 16 | g << 8 | b; + } + + public float getR(int color) { + return (float)(color >> 16 & 255) / 255.0F; + } + + public float getG(int color) { + return (float)(color >> 8 & 255) / 255.0F; + } + + public float getB(int color) { + return (float)(color & 255) / 255.0F; + } + + public float getA(int color) { + return (float)(color >> 24 & 255) / 255.0F; + } +} diff --git a/core/src/main/java/com/sekwah/advancedportals/core/util/FriendlyDataOutput.java b/core/src/main/java/com/sekwah/advancedportals/core/util/FriendlyDataOutput.java new file mode 100644 index 00000000..19423ae3 --- /dev/null +++ b/core/src/main/java/com/sekwah/advancedportals/core/util/FriendlyDataOutput.java @@ -0,0 +1,120 @@ +package com.sekwah.advancedportals.core.util; + +import com.sekwah.advancedportals.core.serializeddata.BlockLocation; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.handler.codec.EncoderException; + +import java.nio.charset.StandardCharsets; + +/** + * Meant to be similar to FriendlyByteBuf if you have used that before. + */ +public class FriendlyDataOutput { + + private final ByteBuf dataOutput; + + public FriendlyDataOutput() { + dataOutput = Unpooled.buffer(); + } + + public void writeBoolean(boolean value) { + dataOutput.writeBoolean(value); + } + + public void writeByte(byte value) { + dataOutput.writeByte(value); + } + + public void writeShort(short value) { + dataOutput.writeShort(value); + } + + public void writeInt(int value) { + dataOutput.writeInt(value); + } + + public void writeLong(long value) { + dataOutput.writeLong(value); + } + + public void writeFloat(float value) { + dataOutput.writeFloat(value); + } + + public void writeDouble(double value) { + dataOutput.writeDouble(value); + } + + public void writeUtf(String text) { + this.writeUtf(text, 32767); + } + + public void writeUtf(String text, int maxLength) { + if (text.length() > maxLength) { + throw new EncoderException("String too big (was " + text.length() + " characters, max " + maxLength + ")"); + } else { + byte[] abyte = text.getBytes(StandardCharsets.UTF_8); + int i = getMaxEncodedUtfLength(maxLength); + if (abyte.length > i) { + throw new EncoderException("String too big (was " + abyte.length + " bytes encoded, max " + i + ")"); + } else { + this.writeVarInt(abyte.length); + this.writeBytes(abyte); + } + } + } + + public void writeVarInt(int p_130131_) { + while((p_130131_ & -128) != 0) { + this.writeByte(p_130131_ & 127 | 128); + p_130131_ >>>= 7; + } + + this.writeByte(p_130131_); + } + + public void writeBytes(byte[] p_130493_) { + this.dataOutput.writeBytes(p_130493_); + } + + public void writeByte(int p_130470_) { + this.dataOutput.writeByte(p_130470_); + } + + private static int getMaxEncodedUtfLength(int p_236871_) { + return p_236871_ * 3; + } + + public byte[] toByteArray() { + if (this.dataOutput.readableBytes() <= 0) { + return new byte[0]; + } + + byte[] bytes = new byte[this.dataOutput.readableBytes()]; + this.dataOutput.readBytes(bytes); + return bytes; + } + + // Only for block serialising and such + private static final int PACKED_X_LENGTH = 26; // 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000)) (im not gonna add all the mojang math stuff to calculate this. + private static final int PACKED_Z_LENGTH = PACKED_X_LENGTH; + public static final int PACKED_Y_LENGTH = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH; + private static final long PACKED_X_MASK = (1L << PACKED_X_LENGTH) - 1L; + private static final long PACKED_Y_MASK = (1L << PACKED_Y_LENGTH) - 1L; + private static final long PACKED_Z_MASK = (1L << PACKED_Z_LENGTH) - 1L; + private static final int Z_OFFSET = PACKED_Y_LENGTH; + private static final int X_OFFSET = PACKED_Y_LENGTH + PACKED_Z_LENGTH; + + public void writeBlock(BlockLocation blockLoc) { + dataOutput.writeLong(this.blockAsLong(blockLoc)); + } + + private long blockAsLong(BlockLocation blockLoc) { + + long i = 0L; + i |= ((long)blockLoc.posX & PACKED_X_MASK) << X_OFFSET; + i |= ((long)blockLoc.posY & PACKED_Y_MASK) << 0; + return i | ((long)blockLoc.posZ & PACKED_Z_MASK) << Z_OFFSET; + } +} diff --git a/lang/src/main/resources/lang/en_GB.lang b/lang/src/main/resources/lang/en_GB.lang index cf28667a..a8175837 100644 --- a/lang/src/main/resources/lang/en_GB.lang +++ b/lang/src/main/resources/lang/en_GB.lang @@ -57,16 +57,16 @@ command.reload.reloaded= All Advanced Portals data reloaded command.create.help=Creates portals command.create.error= There was a problem making the portal: -command.create.console= You cannot create a portal using the console. +command.create.portal.console= You cannot create a portal using the console. command.create.detailedhelp=Format is /portal create (name) [tag:tagvalue] List tags after create in the format tag:value, if your value needs spaces use the format tag:"value with spaces" command.create.complete= The portal has been successfully created. -command.createdesti.help=Creates destinations -command.createdesti.error= There was a problem making the destination -command.createdesti.console= You cannot create a destination using the console. -command.createdesti.detailedhelp=Format is /desti create (name) [tag:tagvalue] List tags after create in the format tag:value, if your value needs spaces use the format tag:"value with spaces" -command.createdesti.prep=&aCreating destination -command.createdesti.complete= The destination has been successfully created. +command.create.destination.help=Creates destinations +command.create.destination.error= There was a problem making the destination +command.create.destination.console= You cannot create a destination using the console. +command.create.destination.detailedhelp=Format is /desti create (name) [tag:tagvalue] List tags after create in the format tag:value, if your value needs spaces use the format tag:"value with spaces" +command.create.destination.prep=&aCreating destination +command.create.destination.complete= The destination has been successfully created. command.create.tags=&aTags&7: @@ -81,8 +81,11 @@ command.portal.remove.complete= The portal has been successfully removed. command.destination.remove.error= There was a problem removing the destination. -command.list.help=Lists portals -command.list=&7 Portals&e: +command.portal.list.help=Lists portals +command.portal.list=&7 Portals&a: + +command.destination.list.help=Lists destinations +command.destination.list=&7 Destinations&a: command.selector= You have been given a portal selector. command.selector.help=Gives you a portal region selector diff --git a/spigot/build.gradle b/spigot/build.gradle index 9e66dc05..364d6de1 100644 --- a/spigot/build.gradle +++ b/spigot/build.gradle @@ -20,6 +20,7 @@ dependencies { // We are using an older version to try and ensure that we are not using anything new older versions cant use. implementation "org.spigotmc:spigot-api:1.13-R0.1-SNAPSHOT" implementation "net.md-5:bungeecord-api:1.16-R0.4" + implementation "com.mojang:authlib:3.5.41" implementation group: 'com.google.inject', name: 'guice', version:'5.0.1' // Be careful to only use what you need to from paper, otherwise it will become incompatible with spigot. //compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT' diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/AdvancedPortalsPlugin.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/AdvancedPortalsPlugin.java index c2c90b4d..8714caa1 100644 --- a/spigot/src/main/java/com/sekwah/advancedportals/spigot/AdvancedPortalsPlugin.java +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/AdvancedPortalsPlugin.java @@ -12,6 +12,16 @@ public class AdvancedPortalsPlugin extends JavaPlugin { private AdvancedPortalsCore portalsCore; + private static AdvancedPortalsPlugin instance; + + public static AdvancedPortalsPlugin getInstance() { + return instance; + } + + public AdvancedPortalsPlugin() { + instance = this; + } + @Override public void onEnable() { @@ -34,7 +44,6 @@ public void onEnable() { new Metrics(this); } - @Override public void onDisable() { this.portalsCore.onDisable(); diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/connector/container/SpigotPlayerContainer.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/connector/container/SpigotPlayerContainer.java index 037ad497..e5fdd639 100644 --- a/spigot/src/main/java/com/sekwah/advancedportals/spigot/connector/container/SpigotPlayerContainer.java +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/connector/container/SpigotPlayerContainer.java @@ -6,6 +6,7 @@ import com.sekwah.advancedportals.core.connector.containers.WorldContainer; import com.sekwah.advancedportals.core.serializeddata.BlockLocation; import com.sekwah.advancedportals.core.serializeddata.PlayerLocation; +import com.sekwah.advancedportals.spigot.reflection.MinecraftCustomPayload; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -47,6 +48,12 @@ public PlayerLocation getLoc() { return new PlayerLocation(loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); } + @Override + public BlockLocation getBlockLoc() { + Location loc = this.player.getLocation(); + return new BlockLocation(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + } + public double getEyeHeight() { return 0; } @@ -89,4 +96,14 @@ public void giveItem(String material, String itemName, String... itemDescription regionselector.setItemMeta(selectorname); this.player.getInventory().addItem(regionselector); } + + @Override + public boolean sendPacket(String channel, byte[] bytes) { + if(channel.startsWith("minecraft:")) { + return MinecraftCustomPayload.sendCustomPayload(player, channel, bytes); + } else { + player.sendPluginMessage(null, channel, bytes); + } + return true; + } } diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/reflection/MinecraftCustomPayload.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/reflection/MinecraftCustomPayload.java new file mode 100644 index 00000000..56138fb0 --- /dev/null +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/reflection/MinecraftCustomPayload.java @@ -0,0 +1,41 @@ +package com.sekwah.advancedportals.spigot.reflection; + +import org.bukkit.entity.Player; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * Just a util class to force spigot to allow us to have fun with the minecraft: channel category + * + * Atm at least this is just designed to be able to access debug/ for showing visuals of the portals and such + * + */ +public class MinecraftCustomPayload { + + public static boolean sendCustomPayload(Player player, String channel, byte[] data) { + try { + // Access the MinecraftKey class using reflection + Class minecraftKeyClass = Class.forName("net.minecraft.resources.MinecraftKey"); + Constructor minecraftKeyConstructor = minecraftKeyClass.getConstructor(String.class); + + // Create an instance of MinecraftKey with the channel name + Object minecraftKey = minecraftKeyConstructor.newInstance(channel); + + // Access the sendCustomPayload method in the CraftPlayer class + Method sendCustomPayloadMethod = player.getClass().getDeclaredMethod("sendCustomPayload", minecraftKeyClass, byte[].class); + + // Make the private method accessible + sendCustomPayloadMethod.setAccessible(true); + + // Invoke the sendCustomPayload method with the MinecraftKey and data + sendCustomPayloadMethod.invoke(player, minecraftKey, data); + + return true; // Successfully sent the custom payload + } catch (Exception e) { + // Catch any reflection-related errors + e.printStackTrace(); + return false; // Return false if there was an error + } + } +}