package net.minecraft.tileentity; import javax.annotation.Nullable; import net.minecraft.command.CommandException; import net.minecraft.command.CommandResultStats; import net.minecraft.command.ICommandSender; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.Style; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentUtils; import net.minecraft.util.text.event.ClickEvent; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class TileEntitySign extends TileEntity { public final ITextComponent[] signText = new ITextComponent[] {new TextComponentString(""), new TextComponentString(""), new TextComponentString(""), new TextComponentString("")}; /** * The index of the line currently being edited. Only used on client side, but defined on both. Note this is only * really used when the > < are going to be visible. */ public int lineBeingEdited = -1; private boolean isEditable = true; private EntityPlayer player; private final CommandResultStats stats = new CommandResultStats(); public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); for (int i = 0; i < 4; ++i) { String s = ITextComponent.Serializer.componentToJson(this.signText[i]); compound.setString("Text" + (i + 1), s); } this.stats.writeStatsToNBT(compound); return compound; } protected void setWorldCreate(World worldIn) { this.setWorld(worldIn); } public void readFromNBT(NBTTagCompound compound) { this.isEditable = false; super.readFromNBT(compound); ICommandSender icommandsender = new ICommandSender() { /** * Get the name of this object. For players this returns their username */ public String getName() { return "Sign"; } /** * Returns {@code true} if the CommandSender is allowed to execute the command, {@code false} if not */ public boolean canUseCommand(int permLevel, String commandName) { return permLevel <= 2; //Forge: Fixes MC-75630 - Exploit with signs and command blocks } /** * Get the position in the world. {@code null} is not allowed! If you are not an entity in the world, * return the coordinates 0, 0, 0 */ public BlockPos getPosition() { return TileEntitySign.this.pos; } /** * Get the position vector. {@code null} is not allowed! If you are not an entity in the world, * return 0.0D, 0.0D, 0.0D */ public Vec3d getPositionVector() { return new Vec3d((double)TileEntitySign.this.pos.getX() + 0.5D, (double)TileEntitySign.this.pos.getY() + 0.5D, (double)TileEntitySign.this.pos.getZ() + 0.5D); } /** * Get the world, if available. {@code null} is not allowed! If you are not an entity in the world, * return the overworld */ public World getEntityWorld() { return TileEntitySign.this.world; } /** * Get the Minecraft server instance */ public MinecraftServer getServer() { return TileEntitySign.this.world.getMinecraftServer(); } }; for (int i = 0; i < 4; ++i) { String s = compound.getString("Text" + (i + 1)); ITextComponent itextcomponent = ITextComponent.Serializer.jsonToComponent(s); try { this.signText[i] = TextComponentUtils.processComponent(icommandsender, itextcomponent, (Entity)null); } catch (CommandException var7) { this.signText[i] = itextcomponent; } } this.stats.readStatsFromNBT(compound); } @Nullable public SPacketUpdateTileEntity getUpdatePacket() { return new SPacketUpdateTileEntity(this.pos, 9, this.getUpdateTag()); } public NBTTagCompound getUpdateTag() { return this.writeToNBT(new NBTTagCompound()); } public boolean onlyOpsCanSetNbt() { return true; } public boolean getIsEditable() { return this.isEditable; } /** * Sets the sign's isEditable flag to the specified parameter. */ @SideOnly(Side.CLIENT) public void setEditable(boolean isEditableIn) { this.isEditable = isEditableIn; if (!isEditableIn) { this.player = null; } } public void setPlayer(EntityPlayer playerIn) { this.player = playerIn; } public EntityPlayer getPlayer() { return this.player; } public boolean executeCommand(final EntityPlayer playerIn) { ICommandSender icommandsender = new ICommandSender() { /** * Get the name of this object. For players this returns their username */ public String getName() { return playerIn.getName(); } /** * Get the formatted ChatComponent that will be used for the sender's username in chat */ public ITextComponent getDisplayName() { return playerIn.getDisplayName(); } /** * Send a chat message to the CommandSender */ public void sendMessage(ITextComponent component) { } /** * Returns {@code true} if the CommandSender is allowed to execute the command, {@code false} if not */ public boolean canUseCommand(int permLevel, String commandName) { return permLevel <= 2; } /** * Get the position in the world. {@code null} is not allowed! If you are not an entity in the world, * return the coordinates 0, 0, 0 */ public BlockPos getPosition() { return TileEntitySign.this.pos; } /** * Get the position vector. {@code null} is not allowed! If you are not an entity in the world, * return 0.0D, 0.0D, 0.0D */ public Vec3d getPositionVector() { return new Vec3d((double)TileEntitySign.this.pos.getX() + 0.5D, (double)TileEntitySign.this.pos.getY() + 0.5D, (double)TileEntitySign.this.pos.getZ() + 0.5D); } /** * Get the world, if available. {@code null} is not allowed! If you are not an entity in the world, * return the overworld */ public World getEntityWorld() { return playerIn.getEntityWorld(); } /** * Returns the entity associated with the command sender. MAY BE NULL! */ public Entity getCommandSenderEntity() { return playerIn; } /** * Returns true if the command sender should be sent feedback about executed commands */ public boolean sendCommandFeedback() { return false; } public void setCommandStat(CommandResultStats.Type type, int amount) { if (TileEntitySign.this.world != null && !TileEntitySign.this.world.isRemote) { TileEntitySign.this.stats.setCommandStatForSender(TileEntitySign.this.world.getMinecraftServer(), this, type, amount); } } /** * Get the Minecraft server instance */ public MinecraftServer getServer() { return playerIn.getServer(); } }; for (ITextComponent itextcomponent : this.signText) { Style style = itextcomponent == null ? null : itextcomponent.getStyle(); if (style != null && style.getClickEvent() != null) { ClickEvent clickevent = style.getClickEvent(); if (clickevent.getAction() == ClickEvent.Action.RUN_COMMAND) { playerIn.getServer().getCommandManager().executeCommand(icommandsender, clickevent.getValue()); } } } return true; } public CommandResultStats getStats() { return this.stats; } }