diff --git a/src/main/java/org/ultramine/server/UMEventHandler.java b/src/main/java/org/ultramine/server/UMEventHandler.java index 66d07bf..373a5f7 100644 --- a/src/main/java/org/ultramine/server/UMEventHandler.java +++ b/src/main/java/org/ultramine/server/UMEventHandler.java @@ -184,7 +184,7 @@ if(!PermissionHandler.getInstance().has(e.getPlayer(), "ability.player.blockbreak")) { e.setCanceled(true); - e.getPlayer().addChatMessage(new ChatComponentTranslation("ultramine.ability.player.blockbreak").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); + e.getPlayer().addChatMessage(new ChatComponentTranslation("ultramine.abilityblockbreak").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); } } @@ -195,7 +195,7 @@ if(!PermissionHandler.getInstance().has(e.player, "ability.player.blockplace")) { e.setCanceled(true); - e.player.addChatMessage(new ChatComponentTranslation("ultramine.ability.player.blockplace").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); + e.player.addChatMessage(new ChatComponentTranslation("ultramine.ability.blockplace").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); } } @@ -206,12 +206,16 @@ if(!PermissionHandler.getInstance().has(e.entityPlayer, "ability.player.useitem")) { e.useItem = Event.Result.DENY; - e.entityPlayer.addChatMessage(new ChatComponentTranslation("ultramine.ability.player.useitem").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); + if(e.entityPlayer.inventory.getCurrentItem() != null) + e.entityPlayer.addChatMessage(new ChatComponentTranslation("ultramine.ability.useitem").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); } if(!PermissionHandler.getInstance().has(e.entityPlayer, "ability.player.useblock")) { e.useBlock = Event.Result.DENY; - e.entityPlayer.addChatMessage(new ChatComponentTranslation("ultramine.ability.player.useblock").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); + e.entityPlayer.addChatMessage(new ChatComponentTranslation("ultramine.ability.useblock").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); } + + if(e.useItem == Event.Result.DENY && e.useBlock == Event.Result.DENY) + e.setCanceled(true); } } diff --git a/src/main/java/org/ultramine/server/UltramineServerModContainer.java b/src/main/java/org/ultramine/server/UltramineServerModContainer.java index 618f69c..770d895 100644 --- a/src/main/java/org/ultramine/server/UltramineServerModContainer.java +++ b/src/main/java/org/ultramine/server/UltramineServerModContainer.java @@ -27,6 +27,7 @@ import cpw.mods.fml.common.network.NetworkCheckHandler; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; import org.ultramine.commands.CommandRegistry; import org.ultramine.commands.basic.BasicCommands; @@ -40,9 +41,13 @@ import org.ultramine.server.data.Databases; import org.ultramine.server.data.ServerDataLoader; import org.ultramine.server.data.player.PlayerCoreData; +import org.ultramine.server.tools.ButtonCommand; public class UltramineServerModContainer extends DummyModContainer { + @SideOnly(Side.SERVER) + private ButtonCommand buttonCommand; + public UltramineServerModContainer() { super(new ModMetadata()); @@ -94,6 +99,8 @@ public void serverAboutToStart(FMLServerAboutToStartEvent e) { e.getServer().getMultiWorld().register(); + if(e.getSide().isServer()) + buttonCommand = new ButtonCommand(e.getServer()); } @Subscribe @@ -107,6 +114,9 @@ e.registerCommands(TechCommands.class); e.getPermissionHandler().createGroup(OpPermissionProxySet.OP_GROUP, "*"); + + if(e.getSide().isServer()) + buttonCommand.load(e); } @Subscribe @@ -125,6 +135,9 @@ { MinecraftServer.getServer().getMultiWorld().unregister(); ChunkProfiler.instance().setEnabled(false); + + if(e.getSide().isServer()) + buttonCommand.unload(); } @NetworkCheckHandler diff --git a/src/main/java/org/ultramine/server/chunk/ChunkHash.java b/src/main/java/org/ultramine/server/chunk/ChunkHash.java index 6873d60..1650bc6 100644 --- a/src/main/java/org/ultramine/server/chunk/ChunkHash.java +++ b/src/main/java/org/ultramine/server/chunk/ChunkHash.java @@ -25,4 +25,9 @@ { return dim << 32 | (x & 0xffff) << 16 | (z & 0xffff); } + + public static long blockCoordToHash(int x, int y, int z) + { + return (long)(x & 0xffffff) | ((long)(z & 0xffffff) << 32) | ((long)(y & 0xff) << 56); + } } diff --git a/src/main/java/org/ultramine/server/tools/ButtonCommand.java b/src/main/java/org/ultramine/server/tools/ButtonCommand.java new file mode 100644 index 0000000..11caa1c --- /dev/null +++ b/src/main/java/org/ultramine/server/tools/ButtonCommand.java @@ -0,0 +1,239 @@ +package org.ultramine.server.tools; + +import gnu.trove.map.TIntObjectMap; +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.map.hash.TLongObjectHashMap; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.ultramine.commands.Command; +import org.ultramine.commands.CommandContext; +import org.ultramine.server.ConfigurationHandler; +import org.ultramine.server.PermissionHandler; +import org.ultramine.server.chunk.ChunkHash; +import org.ultramine.server.util.MinecraftUtil; +import org.ultramine.server.util.YamlConfigProvider; + +import cpw.mods.fml.common.event.FMLServerStartingEvent; +import cpw.mods.fml.common.eventhandler.EventPriority; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Blocks; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.ChatStyle; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MovingObjectPosition; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.BlockEvent; + +@SideOnly(Side.SERVER) +public class ButtonCommand +{ + private static ButtonCommand instance; + + private final MinecraftServer server; + private final File storage; + + private ButtomCMDs buttons; + private TIntObjectMap> buttonMap = new TIntObjectHashMap>(); + + public ButtonCommand(MinecraftServer server) + { + this.server = server; + this.storage = new File(ConfigurationHandler.getStorageDir(), "buttoncommand.yml"); + instance = this; + } + + public void load(FMLServerStartingEvent e) + { + e.registerCommands(this.getClass()); + MinecraftForge.EVENT_BUS.register(this); + buttons = YamlConfigProvider.getOrCreateConfig(storage, ButtomCMDs.class); + for(ButtomCMDs.ButtomCMD cmd : buttons.buttons) + putCmd(cmd); + } + + public void unload() + { + MinecraftForge.EVENT_BUS.unregister(this); + instance = null; + } + + private void save() + { + YamlConfigProvider.saveConfig(storage, buttons); + } + + private void putCmd(ButtomCMDs.ButtomCMD bt) + { + TLongObjectHashMap map = buttonMap.get(bt.dim); + if(map == null) + { + map = new TLongObjectHashMap(); + buttonMap.put(bt.dim, map); + } + + map.put(bt.getKey(), bt); + } + + private void add(ButtomCMDs.ButtomCMD bt) + { + buttons.buttons.add(bt); + putCmd(bt); + save(); + } + + private boolean exists(int dim, int x, int y, int z) + { + TLongObjectHashMap map = buttonMap.get(dim); + return map != null && map.contains(ChunkHash.blockCoordToHash(x, y, z)); + } + + private void add(int dim, int x, int y, int z, String permission, String[] cmds) + { + for(int i = 0; i < cmds.length; i++) + cmds[i] = cmds[i].trim(); + ButtomCMDs.ButtomCMD bt = new ButtomCMDs.ButtomCMD(dim, x, y, z, permission, cmds); + add(bt); + } + + private ButtomCMDs.ButtomCMD get(int dim, int x, int y, int z) + { + TLongObjectHashMap map = buttonMap.get(dim); + return map == null ? null : map.get(ChunkHash.blockCoordToHash(x, y, z)); + } + + private void remove(int dim, int x, int y, int z) + { + TLongObjectHashMap map = buttonMap.get(dim); + if(map != null) + { + ButtomCMDs.ButtomCMD bt = map.remove(ChunkHash.blockCoordToHash(x, y, z)); + if(bt != null) + { + buttons.buttons.remove(bt); + save(); + } + } + } + + @Command( + name = "buttoncommand", + aliases = {"bc"}, + group = "admin", + permissions = {"command.buttoncommand"}, + syntax = { + "[create c] ...", + "[perm p] ...", + "[get remove r rm]" + } + ) + public static void buttoncommand(CommandContext ctx) + { + EntityPlayerMP player = ctx.getSenderAsPlayer(); + MovingObjectPosition obj = MinecraftUtil.getMovingObjectPosition(player); + ctx.check(obj.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK, "command.buttoncommand.fail.noblock"); + Block block = player.worldObj.getBlock(obj.blockX, obj.blockY, obj.blockZ); + System.out.println(Block.blockRegistry.getNameForObject(block)); + ctx.check(block == Blocks.stone_button || block == Blocks.wooden_button || block == Blocks.standing_sign || block == Blocks.wall_sign, "command.buttoncommand.fail.noblock"); + if(ctx.getAction().startsWith("c") || ctx.getAction().startsWith("p")) + { + ctx.check(!instance.exists(player.dimension, obj.blockX, obj.blockY, obj.blockZ), "command.buttoncommand.fail.already"); + instance.add(player.dimension, obj.blockX, obj.blockY, obj.blockZ, ctx.contains("perm") ? ctx.get("perm").asString() : null, + ctx.get("commands").asString().split(";")); + ctx.sendMessage("command.buttoncommand.success.create"); + } + else if(ctx.getAction().startsWith("r")) + { + ctx.check(instance.exists(player.dimension, obj.blockX, obj.blockY, obj.blockZ), "command.buttoncommand.fail.none"); + instance.remove(player.dimension, obj.blockX, obj.blockY, obj.blockZ); + ctx.sendMessage("command.buttoncommand.success.remove"); + + } + else if(ctx.getAction().startsWith("g")) + { + ctx.check(instance.exists(player.dimension, obj.blockX, obj.blockY, obj.blockZ), "command.buttoncommand.fail.none"); + ButtomCMDs.ButtomCMD bt = instance.get(player.dimension, obj.blockX, obj.blockY, obj.blockZ); + ctx.sendMessage("command.buttoncommand.get.head"); + for(String cmd : bt.commands) + ctx.sendMessage(" - %s", cmd); + } + } + + @SubscribeEvent() + public void onPlayerInteractEvent(PlayerInteractEvent e) + { + ButtomCMDs.ButtomCMD bt = get(e.world.provider.dimensionId, e.x, e.y, e.z); + if(bt != null) + { + e.setCanceled(true); + if(bt.permission == null || PermissionHandler.getInstance().has(e.entityPlayer, bt.permission)) + { + for(String cmd : bt.commands) + server.getCommandManager().executeCommand(server, cmd.replace("@p", e.entityPlayer.getGameProfile().getName())); + } + else + { + e.entityPlayer.addChatMessage(new ChatComponentTranslation("command.buttoncommand.noperms").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))); + } + } + } + + @SubscribeEvent(priority = EventPriority.LOW) + public void onBreakEvent(BlockEvent.BreakEvent e) + { + if(e.block == Blocks.stone_button || e.block == Blocks.wooden_button || e.block == Blocks.standing_sign || e.block == Blocks.wall_sign) + remove(e.world.provider.dimensionId, e.x, e.y, e.z); + } + + public static class ButtomCMDs + { + public List buttons = new ArrayList(); + + public static class ButtomCMD + { + public int dim; + public int x; + public int y; + public int z; + public String permission; + public String[] commands; + + public ButtomCMD(){} + public ButtomCMD(int dim, int x, int y, int z, String permission, String[] commands) + { + this.dim = dim; + this.x = x; + this.y = y; + this.z = z; + this.permission = permission; + this.commands = commands; + } + + public boolean equals(Object o) + { + if(!(o instanceof ButtomCMD)) + return false; + ButtomCMD cmd = (ButtomCMD)o; + return dim == cmd.dim && x == cmd.x && y == cmd.y && z == cmd.z; + } + + public int hashCode() + { + return dim ^ ChunkHash.chunkCoordToHash(x, y, z); + } + + public long getKey() + { + return ChunkHash.blockCoordToHash(x, y, z); + } + } + } +} diff --git a/src/main/java/org/ultramine/server/util/MinecraftUtil.java b/src/main/java/org/ultramine/server/util/MinecraftUtil.java new file mode 100644 index 0000000..edb53e1 --- /dev/null +++ b/src/main/java/org/ultramine/server/util/MinecraftUtil.java @@ -0,0 +1,30 @@ +package org.ultramine.server.util; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.MathHelper; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; + +public class MinecraftUtil +{ + //from ItemBoat + public static MovingObjectPosition getMovingObjectPosition(EntityPlayer player) + { + float var4 = 1.0F; + float var5 = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * var4; + float var6 = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * var4; + double var7 = player.prevPosX + (player.posX - player.prevPosX) * (double)var4; + double var9 = player.prevPosY + (player.posY - player.prevPosY) * (double)var4 + 1.62D - (double)player.yOffset; + double var11 = player.prevPosZ + (player.posZ - player.prevPosZ) * (double)var4; + Vec3 var13 = Vec3.createVectorHelper(var7, var9, var11); + float var14 = MathHelper.cos(-var6 * 0.017453292F - (float)Math.PI); + float var15 = MathHelper.sin(-var6 * 0.017453292F - (float)Math.PI); + float var16 = -MathHelper.cos(-var5 * 0.017453292F); + float var17 = MathHelper.sin(-var5 * 0.017453292F); + float var18 = var15 * var16; + float var20 = var14 * var16; + double var21 = 5.0D; + Vec3 var23 = var13.addVector((double)var18 * var21, (double)var17 * var21, (double)var20 * var21); + return player.worldObj.rayTraceBlocks(var13, var23, true); + } +} diff --git a/src/main/resources/assets/ultramine/lang/en_US.lang b/src/main/resources/assets/ultramine/lang/en_US.lang index e0f1374..ac14058 100644 --- a/src/main/resources/assets/ultramine/lang/en_US.lang +++ b/src/main/resources/assets/ultramine/lang/en_US.lang @@ -155,6 +155,16 @@ command.gm.usage=/gm command.gm.description=Toggle gamemode +command.buttoncommand.usage=/buttoncommand OR /buttoncommand OR /buttoncommand +command.buttoncommand.description=Binds server command to button or sign in world +command.buttoncommand.fail.noblock=Button is not selected +command.buttoncommand.fail.already=Button is already created. Use /buttoncommand remove +command.buttoncommand.fail.none=ButtonCommand is not created for selected button +command.buttoncommand.success.create=ButtonCommand has been successfuly created +command.buttoncommand.success.remove=ButtonCommand has been successfuly removed +command.buttoncommand.get.head=Command list: +command.buttoncommand.noperms=You don't have permissions to use this button + #Technical commands command.id.usage=/id command.id.description=Displays information about specified item id diff --git a/src/main/resources/assets/ultramine/lang/ru_RU.lang b/src/main/resources/assets/ultramine/lang/ru_RU.lang index 674c4bc..8de3e26 100644 --- a/src/main/resources/assets/ultramine/lang/ru_RU.lang +++ b/src/main/resources/assets/ultramine/lang/ru_RU.lang @@ -155,6 +155,16 @@ command.gm.usage=/gm command.gm.description=Переключает режим игры +command.buttoncommand.usage=/buttoncommand <команды ...> ИЛИ /buttoncommand <команды ...> ИЛИ /buttoncommand +command.buttoncommand.description=Устанавливает серверную команду на кнопку или табличку в мире +command.buttoncommand.fail.noblock=Кнопка не выбрана, наведите курсор на кнопку +command.buttoncommand.fail.already=Кнопка уже создана. Используйте /buttoncommand remove +command.buttoncommand.fail.none=ButtonCommand не установлен на выбранную кнопку +command.buttoncommand.success.create=ButtonCommand был успешно создан +command.buttoncommand.success.remove=ButtonCommand был успешно удален +command.buttoncommand.get.head=Список команд: +command.buttoncommand.noperms=У вас нет прав для использования данной кнопки + #Technical commands command.id.usage=/id command.id.description=Показывает информацию об указанном id