diff --git a/src/main/java/train/client/core/ClientProxy.java b/src/main/java/train/client/core/ClientProxy.java index 789024044c..a240245f65 100644 --- a/src/main/java/train/client/core/ClientProxy.java +++ b/src/main/java/train/client/core/ClientProxy.java @@ -393,6 +393,8 @@ public Object getClientGuiElement(int ID, EntityPlayer player, World world, int return entity1 != null ? new GuiFixedOverlay(player, (EntityRollingStock) entity1) : null; case (GuiIDs.DYNAMIC_OVERLAY): return entity1 != null ? new GuiDynamicOverlay(player, (EntityRollingStock) entity1) : null; + case (GuiIDs.LOCK_MENU): + return entity1 != null ? new GuiLockMenu(player, ((EntityRollingStock) entity1)) : null; case (GuiIDs.SEAT_GUI): return entity1 != null ? new GUISeatManager(player, (EntityRollingStock) entity1) : null; default: diff --git a/src/main/java/train/client/gui/GuiButtonLockMenu.java b/src/main/java/train/client/gui/GuiButtonLockMenu.java new file mode 100644 index 0000000000..c954900fac --- /dev/null +++ b/src/main/java/train/client/gui/GuiButtonLockMenu.java @@ -0,0 +1,148 @@ +package train.client.gui; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import train.common.library.Info; + +/** + * @author 02skaplan + *
Class for buttons used for the lock menu.
+ */ +@SideOnly(Side.CLIENT) +class GuiButtonLockMenu extends GuiButton { + enum Type { + LOCKED, + UNLOCKED, + CLOSE, + REMOVE, + BREAKACCESSON, + BREAKACCESSOFF, + SAVETOALL, + ARROWUP, + ARROWDOWN, + COPY, + PASTE + } + enum Texture { + ACTIVE, + INACTIVE + } + /** + * if the button has to be drawn drawButton is more than just draw, it makes the button exists or not too + */ + public boolean showButton; + /** + * Starting x-value on texture. + */ + private int u; + /** + * Starting y-value on texture. + */ + private int v = 0; + private int TEXTURE_WIDTH; + private int TEXTURE_HEIGHT; + private Texture texture; + private Type type; + + public GuiButtonLockMenu(int buttonID, int x, int y, int xSize, int ySize, Type type) { + super(buttonID, x, y, xSize, ySize, ""); + this.setType(type, Texture.INACTIVE); + } + + /** + * Draws this button to the screen. + */ + @Override + public void drawButton(Minecraft mc, int par2, int par3) { + if (this.visible && showButton) { + if (par2 >= this.xPosition && par3 >= this.yPosition && par2 < this.xPosition + this.width && par3 < this.yPosition + this.height) { // If mouse is hovering over... + this.setType(this.type, Texture.ACTIVE); + } else { + this.setType(this.type, Texture.INACTIVE); + } + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + RenderHelper.enableGUIStandardItemLighting(); + GL11.glPushMatrix(); + mc.renderEngine.bindTexture(new ResourceLocation(Info.resourceLocation, Info.guiPrefix + "gui_lockmenu.png")); + this.drawTexturedModalRect(this.xPosition, this.yPosition, u, v, TEXTURE_WIDTH, TEXTURE_HEIGHT); + RenderHelper.disableStandardItemLighting(); + GL11.glPopMatrix(); + } + } + public void setType(Type type, Texture texture) { + this.type = type; + this.texture = texture; + switch (type) { + case LOCKED: + case UNLOCKED: + case CLOSE: + case REMOVE: + if (texture == Texture.INACTIVE) + v = 0; + else + v = 25; + if (type == Type.LOCKED || type == Type.UNLOCKED) { + TEXTURE_WIDTH = 17; + TEXTURE_HEIGHT = 25; + if (type == Type.LOCKED) + u = 176; + else + u = 193; + } else { + TEXTURE_WIDTH = 17; + TEXTURE_HEIGHT = 17; + if (type == Type.CLOSE) + u = 210; + else + u = 227; + } + break; + case BREAKACCESSON: + case BREAKACCESSOFF: + case SAVETOALL: + TEXTURE_WIDTH = 17; + TEXTURE_HEIGHT = 17; + if (texture == Texture.INACTIVE) + v = 50; + else + v = 75; + if (type == Type.BREAKACCESSON) + u = 193; + else if (type == Type.BREAKACCESSOFF) + u = 210; + else + u = 227; + break; + case ARROWUP: + case ARROWDOWN: + case COPY: + case PASTE: + if (texture == Texture.INACTIVE) + v = 92; + else + v = 117; + if (type == Type.ARROWUP || type == Type.ARROWDOWN) { + TEXTURE_WIDTH = 7; + TEXTURE_HEIGHT = 22; + if (type == Type.ARROWUP) + u = 176; + else + u = 192; + } else { + TEXTURE_WIDTH = 17; + TEXTURE_HEIGHT = 17; + if (type == Type.COPY) + u = 210; + else + u = 227; + } + } + } + public Texture getTexture() { return this.texture; } + public Type getType() { return this.type; } +} diff --git a/src/main/java/train/client/gui/GuiFreight.java b/src/main/java/train/client/gui/GuiFreight.java index e961c83caf..7eb0fe5713 100644 --- a/src/main/java/train/client/gui/GuiFreight.java +++ b/src/main/java/train/client/gui/GuiFreight.java @@ -15,6 +15,7 @@ import train.common.api.Freight; import train.common.core.network.PacketSetTrainLockedToClient; import train.common.inventory.InventoryFreight; +import train.common.library.GuiIDs; import train.common.library.Info; import java.util.List; @@ -54,8 +55,15 @@ public void initGui() { if (!freight.getTrainLockedFromPacket()) { this.buttonList.add(this.buttonLock = new GuiButton(3, buttonPosX + 124, buttonPosY - 10, 51, 10, "Unlocked")); - } else { - this.buttonList.add(this.buttonLock = new GuiButton(3, buttonPosX + 130, buttonPosY - 10, 43, 10, "Locked")); + } + else { + if (freight.getTrainOwner().equalsIgnoreCase(player.getDisplayName())) + this.buttonList.add(this.buttonLock = new GuiButton(3, buttonPosX + 130, buttonPosY - 10, 43, 10, "Locked")); + else if (freight.isPlayerTrusted(player.getDisplayName())) + if (freight.isPlayerTrustedToBreak(player.getDisplayName())) + this.buttonList.add(this.buttonLock = new GuiButton(3, buttonPosX + 125, buttonPosY - 10, 48, 10, "Trusted+")); + else + this.buttonList.add(this.buttonLock = new GuiButton(3, buttonPosX + 128, buttonPosY - 10, 45, 10, "Trusted")); } if (freight.seats.size() > 1) { this.buttonList.add(this.buttonSeatManager = new GUIButton(buttonPosX + 124,buttonPosY - 20, 51,10, "Seats") { @@ -84,35 +92,32 @@ public void onClick() { protected void actionPerformed(GuiButton guibutton) { if (guibutton.id == 3) { if (player != null && player.getCommandSenderName().equalsIgnoreCase(freight.getTrainOwner())) { - AxisAlignedBB box = freight.boundingBox.expand(5, 5, 5); - List lis3 = freight.worldObj.getEntitiesWithinAABBExcludingEntity(freight, box); - - if (!freight.getTrainLockedFromPacket()) { - if (lis3 != null && !lis3.isEmpty()) { - for (Object entity : lis3) { - if (entity instanceof EntityPlayer) { - Traincraft.lockChannel.sendToServer(new PacketSetTrainLockedToClient(true, freight.getEntityId())); - } - } - } - + if (!freight.getTrainLockedFromPacket() && !isShiftKeyDown()) { freight.locked = true; guibutton.displayString = "Locked"; - } else { - if (lis3 != null && !lis3.isEmpty()) { - for (Object entity : lis3) { - if (entity instanceof EntityPlayer) { - Traincraft.lockChannel.sendToServer(new PacketSetTrainLockedToClient(false, freight.getEntityId())); + this.initGui(); + } else if (!isShiftKeyDown()) { + freight.locked = false; + guibutton.displayString = "Unlocked"; + this.initGui(); + } + AxisAlignedBB box = freight.boundingBox.expand(5, 5, 5); + List lis3 = freight.worldObj.getEntitiesWithinAABBExcludingEntity(freight, box); + if (lis3 != null && !lis3.isEmpty()) { + for (Object entity : lis3) { + if (entity instanceof EntityPlayer) { + if (!isShiftKeyDown()) { + Traincraft.lockChannel.sendToServer(new PacketSetTrainLockedToClient(freight.locked, freight.getTrustedList(), freight.getEntityId(), false)); + } else { + this.mc.thePlayer.closeScreen(); + player.openGui(Traincraft.instance, GuiIDs.LOCK_MENU, player.getEntityWorld(), freight.getEntityId(), -1, (int) freight.posZ); + return; } } } - - freight.locked = false; - guibutton.displayString = "Unlocked"; } - - this.initGui(); - } else if (player != null) { + } + else if (player != null && player instanceof EntityPlayer) { player.addChatMessage(new ChatComponentText("You are not the owner")); } } else if (guibutton instanceof GUIButton) { @@ -124,12 +129,15 @@ protected void actionPerformed(GuiButton guibutton) { protected void drawCreativeTabHoveringText(String str, int t, int g) { String state = ""; if (freight.getTrainLockedFromPacket()) { - state = "Locked"; - } - - if (!freight.getTrainLockedFromPacket()) { - state = "Unlocked"; - } + if (freight.getTrainOwner().equalsIgnoreCase(player.getDisplayName())) + state = "Locked"; + else if (freight.isPlayerTrusted(player.getDisplayName())) + if (freight.isPlayerTrustedToBreak(player.getDisplayName())) + state = "Trusted Access+"; + else + state = "Trusted Access"; + } else + state = "Unlocked"; int textWidth = fontRendererObj.getStringWidth("the GUI, change speed, destroy it."); int startX = 90; diff --git a/src/main/java/train/client/gui/GuiLockMenu.java b/src/main/java/train/client/gui/GuiLockMenu.java new file mode 100644 index 0000000000..072b72558e --- /dev/null +++ b/src/main/java/train/client/gui/GuiLockMenu.java @@ -0,0 +1,42 @@ +package train.client.gui; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.entity.player.EntityPlayer; +import train.common.Traincraft; +import train.common.api.EntityRollingStock; +import train.common.core.network.PacketSetTrainLockedToClient; + +/** + * @author 02skaplan + *Lock and Trusted Players Menu
+ *Allows players to lock and unlock a piece of rolling stock and add & remove trusted individuals from using the rolling stock.
+ */ +@SideOnly(Side.CLIENT) +public class GuiLockMenu extends GuiLockMenuAbstract { + private final EntityRollingStock rollingStock; + + /** + * @author 02skaplan + */ + public GuiLockMenu(EntityPlayer editingPlayer, EntityRollingStock rollingStock) { + super(editingPlayer); + this.rollingStock = rollingStock; + currentTrustees.addAll(rollingStock.getTrustedList()); + } + + @Override + public boolean getLocked() { + return rollingStock.getTrainLockedFromPacket(); + } + + @Override + public void setLocked(boolean locked) { + rollingStock.setTrainLockedFromPacket(locked); + } + + @Override + public void sendUpdatePacket(boolean propagate) { + Traincraft.lockChannel.sendToServer(new PacketSetTrainLockedToClient(rollingStock.locked, exportTrustedPlayers(), rollingStock.getEntityId(), propagate)); + } +} diff --git a/src/main/java/train/client/gui/GuiLockMenuAbstract.java b/src/main/java/train/client/gui/GuiLockMenuAbstract.java new file mode 100644 index 0000000000..99150dada6 --- /dev/null +++ b/src/main/java/train/client/gui/GuiLockMenuAbstract.java @@ -0,0 +1,341 @@ +package train.client.gui; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; +import org.lwjgl.input.Mouse; +import train.common.core.handlers.ConfigHandler; +import train.common.entity.TrustedPlayer; +import train.common.library.Info; + +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author 02skaplan + *Lock and Trusted Players Menu
+ *Allows players to lock and unlock a piece of rolling stock and add & remove trusted individuals from using the rolling stock.
+ */ +@SuppressWarnings("unchecked") +@SideOnly(Side.CLIENT) +public abstract class GuiLockMenuAbstract extends GuiScreen { + private final EntityPlayer editingPlayer; + final private int MENU_TEXTURE_WIDTH = 176; + final private int MENU_TEXTURE_HEIGHT = 222; + /** + * X-coordinate of top left of GUI. + */ + private int GUI_ANCHOR_X; + /** + * X-coordinate of top center of GUI. + */ + private int GUI_ANCHOR_MID_X; + private int TEXTBOX_LEFT_ANCHOR; + /** + * Y-coordinate of top left of GUI. + */ + private int GUI_ANCHOR_Y; + private GuiButtonLockMenu lockUnlockButton; + private GuiButtonLockMenu closeButton; + protected GuiButtonLockMenu closeAndSavetoAll; + private GuiButtonLockMenu arrowUp; + private GuiButtonLockMenu arrowDown; + private GuiButtonLockMenu copyButton; + private GuiButtonLockMenu pasteButton; + public final int MAX_TRUSTEES_ON_PAGE; + protected final int textBoxWidth; + protected final int textBoxHeight; + protected final int textBoxAndButtonWidth; + private int numberOfActiveTextboxes = 1; + protected final ListList of players trusted to use the train
+ */ + private ListThis method is called on the client side when an entity is being loaded in. The additionalData buffer is sent from the server + * and is populated by the server using the writeSpawnData method.
+ *"this is basically NBT for entity spawn, to keep data between client and server in sync because some data is not automatically shared."
+ * @param additionalData The packet data stream */ @Override public void readSpawnData(ByteBuf additionalData) { locked = additionalData.readBoolean(); } + /** + *This method is called on the server side when a connected client is loading the entity. Data written + * to the ByteBuffer will be synced with the client and available to the client through the readSpawnData method.
+ *"this is basically NBT for entity spawn, to keep data between client and server in sync because some data is not automatically shared."
+ * @param buffer The packet data stream + */ @Override public void writeSpawnData(ByteBuf buffer) { buffer.writeBoolean(locked); @@ -384,6 +399,7 @@ protected void writeEntityToNBT(NBTTagCompound nbttagcompound) { nbttagcompound.setString("theOwner", trainOwner); nbttagcompound.setBoolean("locked", locked); nbttagcompound.setString("theCreator", trainCreator); + exportTrustedListToNBT(nbttagcompound); nbttagcompound.setString("theName", trainName); nbttagcompound.setInteger("uniqueID", uniqueID); //nbttagcompound.setInteger("uniqueIDs",uniqueIDs); @@ -404,6 +420,7 @@ protected void writeEntityToNBT(NBTTagCompound nbttagcompound) { if (acceptsOverlayTextures) { nbttagcompound.setTag("overlayTextureConfigTag", overlayTextureContainer.getOverlayConfigTag()); } + exportTrustedListToNBT(nbttagcompound); } @Override @@ -420,6 +437,7 @@ protected void readEntityFromNBT(NBTTagCompound nbttagcompound) { this.locked = nbttagcompound.getBoolean("locked"); setFlag(8, locked); trainCreator = nbttagcompound.getString("theCreator"); + importTrustedListFromNBT(nbttagcompound); trainName = nbttagcompound.getString("theName"); uniqueID = nbttagcompound.getInteger("uniqueID"); //uniqueIDs = nbttagcompound.getInteger("uniqueIDs"); @@ -495,6 +513,7 @@ protected void setUniqueIDToItem(ItemStack stack) { } if (this.uniqueID != -1) stack.getTagCompound().setInteger("uniqueID", this.uniqueID); if (this.trainCreator != null && !this.trainCreator.isEmpty()) stack.getTagCompound().setString("trainCreator", this.trainCreator); + exportTrustedListToNBT(stack.getTagCompound()); stack.getTagCompound().setString("trainColor", this.getColor()); // Only save the overlay configuration to NBT if it exists. No need to store an empty configuration in NBT as it will be initialized as the default when the entity spawns in. if (this.acceptsOverlayTextures && this.getOverlayTextureContainer().getType() != OverlayTextureManager.Type.NONE) { @@ -574,9 +593,10 @@ protected boolean canBeDestroyedByPlayer(DamageSource damagesource) { ((EntityPlayer) damagesource.getEntity()).inventory.getCurrentItem() != null && ((EntityPlayer) damagesource.getEntity()).inventory.getCurrentItem().getItem() instanceof ItemWrench) { - ((EntityPlayer) damagesource.getEntity()).addChatMessage(new ChatComponentText("Removing the train using OP permission")); + ((EntityPlayer) damagesource.getEntity()).addChatMessage(new ChatComponentText("Removing the train using OP permission.")); return false; - } else if (!((EntityPlayer) damagesource.getEntity()).getDisplayName().equalsIgnoreCase(this.trainOwner)) { + } + else if (!((EntityPlayer) damagesource.getEntity()).getDisplayName().equalsIgnoreCase(this.trainOwner) && !(this.isPlayerTrustedToBreak(((EntityPlayerMP) damagesource.getEntity()).getDisplayName()))) { ((EntityPlayer) damagesource.getEntity()).addChatMessage(new ChatComponentText("You are not the owner!")); return true; } @@ -735,6 +755,80 @@ public void updateLinks(){ } } + /** + * @return Returns String ArrayList of trusted players' usernames. + */ + public ListReturns whether a player is trusted to a piece of rolling stock.
+ * @param displayName Case-insensitive display name of player. + * @return True if the player is trusted, false if the player is not trusted. + */ + public boolean isPlayerTrusted(String displayName) { + for (TrustedPlayer trustedPlayer : this.getTrustedList()) { + if (trustedPlayer.getDisplayName().equalsIgnoreCase(displayName)) { + return true; + } + } + return false; + } + + /** + *Returns whether a player is trusted to break a piece of rolling stock.
+ * @param displayName Case-insensitive display name of player. + * @return True if player has break access, false if player does not have break access. + */ + public boolean isPlayerTrustedToBreak(String displayName) { + for (TrustedPlayer trustedPlayer : this.getTrustedList()) { + if (trustedPlayer.getDisplayName().equalsIgnoreCase(displayName)) { + return trustedPlayer.hasBreakAccess(); + } + } + return false; + } + + /** + *Export trusted players to NBT tag for data saving.
+ * @param nbttagcompound NBT tag into which to write trusted list. + */ + public void exportTrustedListToNBT(NBTTagCompound nbttagcompound) { + if (!trustedList.isEmpty()) { + NBTTagList trustedList = new NBTTagList(); + for (TrustedPlayer trustedPlayer : this.trustedList) { + NBTTagCompound trustedPlayerTag = new NBTTagCompound(); + trustedPlayerTag.setString("playerName", trustedPlayer.getDisplayName()); + trustedPlayerTag.setBoolean("breakAccess", trustedPlayer.hasBreakAccess()); + trustedList.appendTag(trustedPlayerTag); + } + nbttagcompound.setTag("trustedList", trustedList); + nbttagcompound.setString("trustedListPreviousOwner", getTrainOwner()); + } + } + + /** + *Import a trusted player list from a given NBT tag.
+ * @param nbttagcompound NBT tag from which to import trusted list. + */ + public void importTrustedListFromNBT(NBTTagCompound nbttagcompound) { + if (nbttagcompound.hasKey("trustedList")) { + NBTTagList trustedList = nbttagcompound.getTagList("trustedList", Constants.NBT.TAG_COMPOUND); + this.trustedList.clear(); + for (int i = 0; i < trustedList.tagCount(); i++) { + if (!trustedList.getCompoundTagAt(i).getString("playerName").equalsIgnoreCase(trainOwner)) // Check to ensure we're not adding the current owner to the trusted list... + this.trustedList.add(new TrustedPlayer(trustedList.getCompoundTagAt(i).getString("playerName"), trustedList.getCompoundTagAt(i).getBoolean("breakAccess"))); + } + if (nbttagcompound.hasKey("trustedListPreviousOwner")) { // If the previous owner is not the one who placed down the piece of rolling stock... + if (!nbttagcompound.getString("trustedListPreviousOwner").equalsIgnoreCase(trainOwner)) { + getTrustedList().add(new TrustedPlayer(nbttagcompound.getString("trustedListPreviousOwner"), true)); + } + } + } + } + /** * @author 02skaplan *Called to setup the overlay texture manager for the given AbstractTrain. It is recommended diff --git a/src/main/java/train/common/api/EntityRollingStock.java b/src/main/java/train/common/api/EntityRollingStock.java index f1185fc68c..4f37039207 100644 --- a/src/main/java/train/common/api/EntityRollingStock.java +++ b/src/main/java/train/common/api/EntityRollingStock.java @@ -52,7 +52,9 @@ import train.common.core.util.DepreciatedUtil; import train.common.entity.CollisionBox; import train.common.entity.EntityHitbox; +import train.common.entity.TrustedPlayer; import train.common.entity.rollingStockOld.special.EntityTracksBuilder; +import train.common.items.ItemPadlock; import train.common.items.ItemPaintbrushThing; import train.common.items.ItemRollingStock; import train.common.items.ItemWrench; @@ -223,20 +225,39 @@ public Entity[] getParts(){ } /** - * this is basically NBT for entity spawn, to keep data between client and server in sync because some data is not automatically shared. + *
This method is called on the client side when an entity is being loaded in. The additionalData buffer is sent from the server + * and is populated by the server using the writeSpawnData method.
+ *"this is basically NBT for entity spawn, to keep data between client and server in sync because some data is not automatically shared."
+ * @param additionalData The packet data stream */ @Override public void readSpawnData(ByteBuf additionalData) { isBraking = additionalData.readBoolean(); setTrainLockedFromPacket(additionalData.readBoolean()); + int numOfTrustedPlayers = additionalData.readInt(); + for (int i = 0; i < numOfTrustedPlayers; i++) { + getTrustedList().add(new TrustedPlayer(ByteBufUtils.readUTF8String(additionalData), additionalData.readBoolean())); + } if (additionalData.readBoolean()) { // If accepts overlay textures... getOverlayTextureContainer().importFromConfigTag(ByteBufUtils.readTag(additionalData)); } } + + /** + *This method is called on the server side when a connected client is loading the entity. Data written + * to the ByteBuffer will be synced with the client and available to the client through the readSpawnData method.
+ *"this is basically NBT for entity spawn, to keep data between client and server in sync because some data is not automatically shared."
+ * @param buffer The packet data stream + */ @Override public void writeSpawnData(ByteBuf buffer) { buffer.writeBoolean(isBraking); buffer.writeBoolean(getTrainLockedFromPacket()); + buffer.writeInt(getTrustedList().size()); + for (TrustedPlayer player : getTrustedList()) { + ByteBufUtils.writeUTF8String(buffer, player.getDisplayName()); + buffer.writeBoolean(player.hasBreakAccess()); + } buffer.writeBoolean(acceptsOverlayTextures()); if (acceptsOverlayTextures()) { ByteBufUtils.writeTag(buffer, getOverlayTextureContainer().getOverlayConfigTag()); @@ -511,7 +532,7 @@ public boolean isLockedAndNotOwner(int player) { return false; } if (this.getTrainLockedFromPacket()) { - return !((EntityPlayer) p).getDisplayName().equalsIgnoreCase(this.getTrainOwner()); + return !((EntityPlayer) p).getDisplayName().equalsIgnoreCase(this.getTrainOwner()) && !isPlayerTrusted(((EntityPlayer) p).getDisplayName()); } return false; } @@ -1187,16 +1208,16 @@ public boolean interactFirst(EntityPlayer entityplayer) { playerEntity = entityplayer; ItemStack itemstack = entityplayer.inventory.getCurrentItem(); - if (this.getTrainLockedFromPacket() && !worldObj.isRemote && - !playerEntity.getDisplayName().toLowerCase().equals(this.trainOwner.toLowerCase())) { - if (!canBeRiddenWhileLocked(this)) { - entityplayer.addChatMessage(new ChatComponentText("Train is locked")); + if (this.getTrainLockedFromPacket() && !worldObj.isRemote) { + boolean isTrustedPlayer = isPlayerTrusted(playerEntity.getDisplayName()); + if (!playerEntity.getDisplayName().equalsIgnoreCase(this.getTrainOwner()) && !canBeRiddenWhileLocked(this) && !isTrustedPlayer) { + if (!worldObj.isRemote) entityplayer.addChatMessage(new ChatComponentText("Train is locked by " + this.getTrainOwner() + ".")); return true; - } else if (entityplayer.inventory.getCurrentItem() != null && entityplayer.inventory.getCurrentItem().getItem() instanceof ItemDye && (this instanceof Locomotive)) { - entityplayer.addChatMessage(new ChatComponentText("Train is locked")); + } + else if (!playerEntity.getDisplayName().equalsIgnoreCase(this.getTrainOwner()) && entityplayer.inventory.getCurrentItem() != null && entityplayer.inventory.getCurrentItem().getItem() instanceof ItemDye && (this instanceof Locomotive) && !isTrustedPlayer) { + if (!worldObj.isRemote) entityplayer.addChatMessage(new ChatComponentText("Train is locked by " + this.getTrainOwner() + ".")); return true; } - } @@ -1277,6 +1298,14 @@ public boolean interactFirst(EntityPlayer entityplayer) { return true; } } + } else if (entityplayer.isSneaking() && itemstack.getItem() instanceof ItemPadlock) { + if (getTrainOwner().equalsIgnoreCase(entityplayer.getDisplayName())) { + entityplayer.openGui(Traincraft.instance, GuiIDs.LOCK_MENU, entityplayer.getEntityWorld(), this.getEntityId(), -1, (int) this.posZ); + return true; + } else { + if (!worldObj.isRemote) entityplayer.addChatMessage(new ChatComponentText("Train is locked by " + this.getTrainOwner() + ".")); + return false; + } } } @@ -1685,7 +1714,7 @@ public boolean shouldRiderSit(){ */ public boolean getPermissions(EntityPlayer player, boolean driverOnly) { //make sure the player is not null, and be sure that driver only rules are applied. - if (player ==null){ + if (player ==null) { return false; } else if (driverOnly && (!(player.ridingEntity instanceof EntitySeat) || ! ((EntitySeat) player.ridingEntity).isControlSeat())){ return false; @@ -1693,7 +1722,9 @@ public boolean getPermissions(EntityPlayer player, boolean driverOnly) { //be sure operators and owners can do whatever if ((player.capabilities.isCreativeMode && player.canCommandSenderUseCommand(2, "")) - || (this.getOwner()!=null && this.getOwner() == player.getGameProfile())) { + || (this.getOwner()!=null && this.getOwner() == player.getGameProfile()) + || isPlayerTrusted(player.getDisplayName()) + || canBeRiddenWhileLocked(this)) { return true; } diff --git a/src/main/java/train/common/core/handlers/ConfigHandler.java b/src/main/java/train/common/core/handlers/ConfigHandler.java index dc85488193..b574275b64 100644 --- a/src/main/java/train/common/core/handlers/ConfigHandler.java +++ b/src/main/java/train/common/core/handlers/ConfigHandler.java @@ -51,6 +51,7 @@ public class ConfigHandler { public static boolean TRACK_OVERLAP; public static boolean ENABLE_SLOPE_ACCELERATION; + public static int MAX_TRUSTEES_ON_PADLOCK; public static void init(File configFile) { @@ -104,6 +105,7 @@ public static void init(File configFile) { ALLOW_ATO_ON_STEAMERS = cf.get(CATEGORY_GENERAL, "ALLOW_ATO_ON_STEAMERS", false, "Allows Minecraft Train Control's ATO system to be used on steam trains").getBoolean(true); PAINTBRUSH_DEFAULT_LOW_PERFORMANCE_MODE = cf.get(CATEGORY_GENERAL, "PAINTBRUSH_DEFAULT_LOW_PERFORMANCE_MODE", false, "Defaults to low performance mode in paintbrush menu.").getBoolean(false); ENABLE_SLOPE_ACCELERATION = cf.get(CATEGORY_GENERAL,"ENABLE_SLOPE_ACCELERATION",true,"Defaults to true").getBoolean(true); + MAX_TRUSTEES_ON_PADLOCK = cf.get(CATEGORY_GENERAL, "MAX_TRUSTEES_ON_PADLOCK", false, "Maximum number of trustees allowed in the padlock menu.").getInt(30); PUSHABLE_ROLLINGSTOCK = cf.get(CATEGORY_GENERAL, "ENABLE_PUSHING_ROLLINGSTOCK", true, "Defaults to true").getBoolean(true); } catch (Exception e) { diff --git a/src/main/java/train/common/core/handlers/PacketHandler.java b/src/main/java/train/common/core/handlers/PacketHandler.java index 3115ac7ed4..49f60ff581 100644 --- a/src/main/java/train/common/core/handlers/PacketHandler.java +++ b/src/main/java/train/common/core/handlers/PacketHandler.java @@ -88,6 +88,8 @@ public static void init(){ PacketTextureOverlayConfig.class, 11, Side.SERVER); Traincraft.overlayTextureChannel.registerMessage(PacketTextureOverlayConfig.Handler.class, PacketTextureOverlayConfig.class, 12, Side.CLIENT); + Traincraft.lockChannel.registerMessage(PacketSetTrainLockedToClient.Handler.class, + PacketSetTrainLockedToClient.class, 13, Side.CLIENT); Traincraft.rollingStockLightsChannel.registerMessage(PacketRollingStockLights.Handler.class, PacketRollingStockLights.class, 19, Side.SERVER); diff --git a/src/main/java/train/common/core/network/PacketHandler.java b/src/main/java/train/common/core/network/PacketHandler.java index f96134f7cd..3d296ee2ff 100644 --- a/src/main/java/train/common/core/network/PacketHandler.java +++ b/src/main/java/train/common/core/network/PacketHandler.java @@ -44,6 +44,8 @@ public static void init() { 4, Side.SERVER); Traincraft.lockChannel.registerMessage(PacketSetTrainLockedToClient.Handler.class, PacketSetTrainLockedToClient.class, 5, Side.SERVER); + Traincraft.lockChannel.registerMessage(PacketSetTrainLockedToClient.Handler.class, + PacketSetTrainLockedToClient.class, 10, Side.CLIENT); Traincraft.ignitionChannel.registerMessage(PacketSetLocoTurnedOn.Handler.class, PacketSetLocoTurnedOn.class, 6, Side.SERVER); Traincraft.modChannel.registerMessage(PacketLantern.Handler.class, PacketLantern.class, 7, diff --git a/src/main/java/train/common/core/network/PacketSetTrainLockedToClient.java b/src/main/java/train/common/core/network/PacketSetTrainLockedToClient.java index a4ebed9182..9e57e69408 100644 --- a/src/main/java/train/common/core/network/PacketSetTrainLockedToClient.java +++ b/src/main/java/train/common/core/network/PacketSetTrainLockedToClient.java @@ -1,47 +1,148 @@ package train.common.core.network; +import cpw.mods.fml.common.network.ByteBufUtils; +import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayerMP; +import train.common.Traincraft; import train.common.api.AbstractTrains; +import train.common.api.EntityRollingStock; +import train.common.entity.TrustedPlayer; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; public class PacketSetTrainLockedToClient implements IMessage { - boolean bool; - int entityID; + boolean bool; + boolean requestPacket; + int entityID; + int playerEntityID; + boolean propagate; + ListClient <-> Server communication packet to update lock and trusted list.
+ * @param bool Locked status. True for locked, false for unlocked. + * @param trustedList Trusted players list. + * @param propagate Whether to propagate the changes throughout the consist. + */ + public PacketSetTrainLockedToClient(boolean bool, ListClient -> Server communication packet to request lock and trusted list from server.
+ */ + public PacketSetTrainLockedToClient(int trainEntity, int playerEntityID) { + this.entityID = trainEntity; + this.playerEntityID = playerEntityID; + requestPacket = true; } @Override public void fromBytes(ByteBuf bbuf) { - this.bool = bbuf.readBoolean(); this.entityID = bbuf.readInt(); + if (!bbuf.readBoolean()) { + requestPacket = false; + this.bool = bbuf.readBoolean(); + int numberOfTrustedPlayers = bbuf.readInt(); + for (int i = 0; i < numberOfTrustedPlayers; i++) { + trustedList.add(new TrustedPlayer(ByteBufUtils.readUTF8String(bbuf), bbuf.readBoolean())); + } + propagate = bbuf.readBoolean(); + } else { + requestPacket = true; + this.playerEntityID = bbuf.readInt(); + } } @Override public void toBytes(ByteBuf bbuf) { - bbuf.writeBoolean(this.bool); bbuf.writeInt(this.entityID); + bbuf.writeBoolean(requestPacket); + if (!requestPacket) { + bbuf.writeBoolean(this.bool); + bbuf.writeInt(trustedList.size()); + for (TrustedPlayer trustedPlayer : trustedList) { + ByteBufUtils.writeUTF8String(bbuf, trustedPlayer.getDisplayName()); + bbuf.writeBoolean(trustedPlayer.hasBreakAccess()); + } + bbuf.writeBoolean(propagate); + } else { + bbuf.writeInt(playerEntityID); + } } public static class Handler implements IMessageHandlerServer side method used to update the lock status and trusted players list for all cars in a given consist + * belonging to the train owner.
+ * @author 02skaplan + * @param rollingStock The main rolling stock entity being updated and from which we should propogate changes. + * @param trustedPlayerList List of trusted players. + */ + private static void propagateChanges(EntityRollingStock rollingStock, ListImport a trusted player list from a given NBT tag.
+ * @param nbttagcompound NBT tag from which to import trusted list. + */ + public static ListReturns whether or not a player is trusted to a piece of rolling stock.
+ * @param displayName Case-insensitive display name of player. + * @return True if the player is trusted, false if the player is not trusted. + */ + public static boolean isPlayerTrusted(String displayName, ListReturns whether or not a player is trusted to break a piece of rolling stock.
+ * @param displayName Case-insensitive display name of player. + * @return True if player has break access, false if player does not have break access. + */ + public static boolean isPlayerTrustedToBreak(String displayName, List