From 74f730e450fc1cea57159184b490a34ee475f713 Mon Sep 17 00:00:00 2001 From: Sen Date: Thu, 27 Mar 2025 17:54:03 +0100 Subject: [PATCH] character selector --- java/src/game/Game.java | 12 +- java/src/game/Server.java | 79 ++++++--- java/src/game/command/EntityListParser.java | 4 +- .../game/command/PlayerEntityListParser.java | 4 +- java/src/game/command/PlayerEntityParser.java | 4 +- .../command/commands/CommandOfflinetp.java | 2 +- .../game/command/commands/CommandSpawn.java | 2 +- java/src/game/entity/Entity.java | 8 +- java/src/game/entity/EntityTrackerEntry.java | 2 +- java/src/game/entity/npc/EntityNPC.java | 11 +- java/src/game/entity/npc/PlayerCharacter.java | 23 +++ java/src/game/entity/types/EntityLiving.java | 15 ++ java/src/game/gui/GuiCharacters.java | 104 +++++++++++ java/src/game/gui/GuiConsole.java | 6 +- java/src/game/gui/GuiMenu.java | 7 +- java/src/game/gui/GuiSkin.java | 107 +++++++----- java/src/game/network/ClientPlayer.java | 42 ++++- java/src/game/network/PacketRegistry.java | 2 + java/src/game/network/Player.java | 164 ++++++++++++------ java/src/game/packet/CPacketAction.java | 3 + .../src/game/packet/SPacketCharacterList.java | 85 +++++++++ java/src/game/packet/SPacketJoinGame.java | 10 +- java/src/game/packet/SPacketRespawn.java | 10 +- java/src/game/world/WorldServer.java | 2 +- 24 files changed, 554 insertions(+), 154 deletions(-) create mode 100644 java/src/game/entity/npc/PlayerCharacter.java create mode 100644 java/src/game/gui/GuiCharacters.java create mode 100644 java/src/game/packet/SPacketCharacterList.java diff --git a/java/src/game/Game.java b/java/src/game/Game.java index 7168e7c..55192a8 100755 --- a/java/src/game/Game.java +++ b/java/src/game/Game.java @@ -72,6 +72,7 @@ import game.gui.GuiGameOver; import game.gui.GuiInfo; import game.gui.GuiLoading; import game.gui.GuiMenu; +import game.gui.GuiSkin; import game.gui.Style; import game.gui.container.GuiContainer; import game.gui.container.GuiInventory; @@ -280,6 +281,7 @@ public class Game implements IThreadListener { public boolean dayCycle = true; public boolean debugPlayer; public boolean cameraUsed; + public boolean charEditor; private int leftClickCounter; private int rightClickTimer; @@ -489,6 +491,7 @@ public class Game implements IThreadListener { if(netHandler != null) netHandler.cleanup(); this.debugWorld = false; + this.charEditor = false; this.viewEntity = null; this.connection = null; this.theWorld = null; @@ -1483,7 +1486,8 @@ public class Game implements IThreadListener { // if (this.open instanceof GuiGameOver) // { - this.displayGuiScreen(null); +// if(!this.charEditor) +// this.displayGuiScreen(null); // } } @@ -2222,15 +2226,15 @@ public class Game implements IThreadListener { // this.displayGuiScreen(GuiChat.INSTANCE); // } if(this.theWorld != null && Bind.MENU.isPressed()) { - if(this.open != null) - this.displayGuiScreen(null); + if(this.open != (this.charEditor ? GuiSkin.INSTANCE : null)) + this.displayGuiScreen(this.charEditor ? GuiSkin.INSTANCE : null); else this.displayGuiScreen(GuiMenu.INSTANCE); } else if(this.theWorld == null && !(this.open instanceof GuiMenu) && Bind.MENU.isPressed()) { this.displayGuiScreen(GuiMenu.INSTANCE); } - if(this.theWorld != null && Bind.INVENTORY.isPressed()) { + if(this.theWorld != null && !this.charEditor && Bind.INVENTORY.isPressed()) { if(this.open instanceof GuiContainer) { this.displayGuiScreen(null); } diff --git a/java/src/game/Server.java b/java/src/game/Server.java index 239cbb0..8293287 100755 --- a/java/src/game/Server.java +++ b/java/src/game/Server.java @@ -168,9 +168,9 @@ public final class Server implements Runnable, IThreadListener { for(int i = 0; i < list.length; ++i) { if(list[i].endsWith(".nbt")) { list[i] = list[i].substring(0, list[i].length() - 4); - Player player = this.getPlayer(list[i]); - if(player != null) - list[i] = player.getUser(); +// Player player = this.getPlayer(list[i]); +// if(player != null) +// list[i] = player.getUser(); } } return list; @@ -192,7 +192,7 @@ public final class Server implements Runnable, IThreadListener { return null; NBTTagCompound tag = null; try { - File dat = new File(this.playerDir, user.toLowerCase() + ".nbt"); + File dat = new File(this.playerDir, user + ".nbt"); if(dat.exists() && dat.isFile()) { tag = NBTLoader.readGZip(dat); @@ -537,7 +537,7 @@ public final class Server implements Runnable, IThreadListener { } public Player getPlayer(String user) { - return this.usermap.get(user.toLowerCase()); + return this.usermap.get(user); } public String getMessage() { @@ -629,6 +629,24 @@ public final class Server implements Runnable, IThreadListener { player.setPosition(player.posX, player.posY + 1.0D, player.posZ); } } + + public Position getRandomSpawnPosition() { + WorldServer world = this.getWorld(Config.spawnDim); + world = world == null ? this.space : world; + BlockPos pos = new BlockPos(Config.spawnX, Config.spawnY, Config.spawnZ); + int radius = Config.spawnRadius; + if(radius > 0) { + pos = world.getTopSolidOrLiquidBlock(pos.add( + ExtMath.clampi(world.rand.excl(-radius, radius), -World.MAX_SIZE + 1, World.MAX_SIZE - 1), 0, + ExtMath.clampi(world.rand.excl(-radius, radius), -World.MAX_SIZE + 1, World.MAX_SIZE - 1))); + } + int y = pos.getY(); + while(world.getState(new BlockPos(pos.getX(), y, pos.getZ())).getBlock().getMaterial().blocksMovement() && y < 511) + y++; + return new Position(pos.getX() + 0.5d, (double)y, pos.getZ() + 0.5d, + radius > 0 ? (-180.0f + world.rand.floatv() * 360.0f) : Config.spawnYaw, + radius > 0 ? 0.0f : Config.spawnPitch, world.dimension.getDimensionId()); + } public String addPlayer(NetConnection connection, String loginUser, String loginPass) { NBTTagCompound tag = this.readPlayer(loginUser); @@ -667,10 +685,10 @@ public final class Server implements Runnable, IThreadListener { connection.sendPacket(new RPacketLoginSuccess()); connection.setNetHandler(conn); this.players.add(conn); - this.usermap.put(loginUser.toLowerCase(), conn); + this.usermap.put(loginUser, conn); - tag = conn.getSelectedCharacter(false); - WorldServer world = this.getWorld(tag == null ? Config.spawnDim : tag.getInteger("Dimension")); + tag = conn.readCharacter(); + WorldServer world = tag == null ? this.space : this.getWorld(tag.getInteger("Dimension")); world = world == null ? this.space : world; EntityNPC player = conn.createPlayer(world, tag == null ? EntityRegistry.getEntityString(EntityHuman.class) : tag.getString("id")); if(tag != null) @@ -679,16 +697,16 @@ public final class Server implements Runnable, IThreadListener { player.onInitialSpawn(null); // player.setWorld(world); if(tag == null) - this.movePlayerToSpawn(player); + /* this.movePlayerToSpawn(player); */ player.moveToBlockPosAndAngles(new BlockPos(0, 16384, 0), 0.0f, 0.0f); Log.JNI.info(loginUser + "[" + connection.getCutAddress() + "] hat sich mit Objekt-ID " + player.getId() + " auf Level " + world.dimension.getDimensionId() + ": " - + String.format("%.2f %.2f %.2f", player.posX, player.posY, player.posZ) + " verbunden"); + + String.format("%.2f %.2f %.2f", player.posX, player.posY, player.posZ) + " verbunden (" + (tag == null ? " (Charakter-Editor)" : "'" + player.getCommandName() + "'") + ")"); if(Config.preloadAll || (Config.preloadLocal && conn.isLocal())) this.preload(player); - conn.sendPacket(new SPacketJoinGame(player.getId(), world.dimension, EntityRegistry.getEntityID(player))); + conn.sendPacket(new SPacketJoinGame(player.getId(), world.dimension, EntityRegistry.getEntityID(player), tag == null)); conn.sendPacket(new SPacketHeldItemChange(player.inventory.currentItem)); conn.sendPacket(new SPacketWorld(WorldServer.clampGravity(), Config.dayCycle, Config.timeFlow)); @@ -722,7 +740,7 @@ public final class Server implements Runnable, IThreadListener { world.removeEntity(player); world.removePlayer(player); this.players.remove(conn); - this.usermap.remove(conn.getUser().toLowerCase()); + this.usermap.remove(conn.getUser()); this.sendPacket(new S38PacketPlayerListItem(true, conn)); } @@ -740,7 +758,7 @@ public final class Server implements Runnable, IThreadListener { return null; NBTTagCompound tag = null; try { - File dat = new File(this.playerDir, user.toLowerCase() + ".nbt"); + File dat = new File(this.playerDir, user + ".nbt"); if(dat.exists() && dat.isFile()) { tag = NBTLoader.readGZip(dat); @@ -757,13 +775,19 @@ public final class Server implements Runnable, IThreadListener { return; try { NBTTagCompound tag = new NBTTagCompound(); - NBTTagCompound etag = conn.getSelectedCharacter(true); - conn.getEntity().writeToNBT(etag); - etag.setInteger("Dimension", conn.getEntity().worldObj.dimension.getDimensionId()); - etag.setString("id", EntityRegistry.getEntityString(conn.getEntity())); + EntityNPC entity = conn.getPresentEntity(); + if(entity != null) { + NBTTagCompound etag = new NBTTagCompound(); + entity.writeToNBT(etag); + etag.setInteger("Dimension", entity.worldObj.dimension.getDimensionId()); + etag.setString("id", EntityRegistry.getEntityString(entity)); + conn.writeCharacter(etag); + } +// else +// etag = new NBTTagCompound(); conn.writeToNBT(tag); - File tmp = new File(this.playerDir, conn.getUser().toLowerCase() + ".nbt.tmp"); - File dat = new File(this.playerDir, conn.getUser().toLowerCase() + ".nbt"); + File tmp = new File(this.playerDir, conn.getUser() + ".nbt.tmp"); + File dat = new File(this.playerDir, conn.getUser() + ".nbt"); NBTLoader.writeGZip(tag, tmp); if(dat.exists()) { dat.delete(); @@ -820,7 +844,7 @@ public final class Server implements Runnable, IThreadListener { nplayer.setPosition(nplayer.posX, nplayer.posY + 1.0D, nplayer.posZ); } } - conn.sendPacket(new SPacketRespawn(world.dimension, EntityRegistry.getEntityID(nplayer))); + conn.sendPacket(new SPacketRespawn(world.dimension, EntityRegistry.getEntityID(nplayer), conn.isInEditor())); conn.setPlayerLocation(nplayer.posX, nplayer.posY, nplayer.posZ, nplayer.rotYaw, nplayer.rotPitch); conn.sendPacket(new SPacketSetExperience(nplayer.experience, nplayer.experienceTotal, nplayer.experienceLevel)); this.updateTimeAndWeatherForPlayer(conn, world); @@ -835,10 +859,10 @@ public final class Server implements Runnable, IThreadListener { old.worldObj.dimension.getFormattedName(false)); } - public void swapPlayer(Player conn, NBTTagCompound tag) { + public NBTTagCompound swapPlayer(Player conn, NBTTagCompound tag, Class clazz) { EntityNPC old = conn.getEntity(); old.unmount(); - NBTTagCompound oldTag = conn.getSelectedCharacter(true); + NBTTagCompound oldTag = new NBTTagCompound(); old.writeToNBT(oldTag); oldTag.setInteger("Dimension", old.worldObj.dimension.getDimensionId()); oldTag.setString("id", EntityRegistry.getEntityString(old)); @@ -849,9 +873,9 @@ public final class Server implements Runnable, IThreadListener { old.getServerWorld().removePlayerEntityDangerously(old); // old.dead = false; - WorldServer world = this.getWorld(tag == null ? Config.spawnDim : tag.getInteger("Dimension")); + WorldServer world = tag == null ? this.space : this.getWorld(tag.getInteger("Dimension")); world = world == null ? this.space : world; - EntityNPC nplayer = conn.createPlayer(world, tag == null ? EntityRegistry.getEntityString(EntityHuman.class) : tag.getString("id")); + EntityNPC nplayer = conn.createPlayer(world, tag == null ? EntityRegistry.getEntityString(clazz) : tag.getString("id")); // conn.sendPacket(new SPacketRespawn(world.dimension, EntityRegistry.getEntityID(nplayer))); if(tag != null) nplayer.readFromNBT(tag); @@ -860,11 +884,11 @@ public final class Server implements Runnable, IThreadListener { // nplayer.clonePlayer(old); nplayer.setId(old.getId()); if(tag == null) - this.movePlayerToSpawn(nplayer); + /* this.movePlayerToSpawn(nplayer); */ nplayer.moveToBlockPosAndAngles(new BlockPos(0, 16384, 0), 0.0f, 0.0f); world.loadChunk((int)nplayer.posX >> 4, (int)nplayer.posZ >> 4); world.addPlayer(nplayer); world.spawnEntityInWorld(nplayer); - conn.sendPacket(new SPacketRespawn(world.dimension, EntityRegistry.getEntityID(nplayer))); + conn.sendPacket(new SPacketRespawn(world.dimension, EntityRegistry.getEntityID(nplayer), conn.isInEditor())); conn.sendPacket(new SPacketSkin(nplayer.getId(), nplayer.getSkin())); // , nplayer.getModel())); conn.setPlayerLocation(nplayer.posX, nplayer.posY, nplayer.posZ, nplayer.rotYaw, nplayer.rotPitch); conn.sendPacket(new SPacketSetExperience(nplayer.experience, nplayer.experienceTotal, nplayer.experienceLevel)); @@ -877,13 +901,14 @@ public final class Server implements Runnable, IThreadListener { conn.sendPacket(new S1DPacketEntityEffect(nplayer.getId(), effect)); } conn.sendPlayerAbilities(); + return oldTag; } public void transferToDimension(EntityNPC player, int dimension, BlockPos pos, float yaw, float pitch, PortalType portal) { WorldServer oldWorld = player.getServerWorld(); // this.getWorld(player.dimension); // player.dimension = dimension; WorldServer newWorld = this.getWorld(dimension); - player.connection.sendPacket(new SPacketRespawn(newWorld.dimension, EntityRegistry.getEntityID(player))); + player.connection.sendPacket(new SPacketRespawn(newWorld.dimension, EntityRegistry.getEntityID(player), player.connection.isInEditor())); oldWorld.removePlayerEntityDangerously(player); player.dead = false; this.placeInDimension(player, oldWorld, newWorld, pos, portal); diff --git a/java/src/game/command/EntityListParser.java b/java/src/game/command/EntityListParser.java index 2ebe75e..b21f17b 100644 --- a/java/src/game/command/EntityListParser.java +++ b/java/src/game/command/EntityListParser.java @@ -40,8 +40,8 @@ public class EntityListParser extends EntityParser { else if(input.equals("*")) { List list = Lists.newArrayList(); for(Player plr : env.getServer().getPlayers()) { - if(plr.getEntity() != null) - list.add(plr.getEntity()); + if(plr.getPresentEntity() != null) + list.add(plr.getPresentEntity()); } if(list.isEmpty()) throw new RunException("Keine Spieler gefunden"); diff --git a/java/src/game/command/PlayerEntityListParser.java b/java/src/game/command/PlayerEntityListParser.java index f0ad7dc..06335f6 100644 --- a/java/src/game/command/PlayerEntityListParser.java +++ b/java/src/game/command/PlayerEntityListParser.java @@ -19,8 +19,8 @@ public class PlayerEntityListParser extends PlayerEntityParser { if(input.equals("*")) { List list = Lists.newArrayList(); for(Player plr : env.getServer().getPlayers()) { - if(plr.getEntity() != null) - list.add(plr.getEntity()); + if(plr.getPresentEntity() != null) + list.add(plr.getPresentEntity()); } if(list.isEmpty()) throw new RunException("Keine Spieler gefunden"); diff --git a/java/src/game/command/PlayerEntityParser.java b/java/src/game/command/PlayerEntityParser.java index f740047..1239f06 100644 --- a/java/src/game/command/PlayerEntityParser.java +++ b/java/src/game/command/PlayerEntityParser.java @@ -10,7 +10,7 @@ public class PlayerEntityParser extends PlayerParser { public Object parse(CommandEnvironment env, String input) { Player net = (Player)super.parse(env, input); - EntityNPC entity = net.getEntity(); + EntityNPC entity = net.getPresentEntity(); if(entity == null) throw new RunException("Spieler-Objekt von '%s' wurde nicht gefunden", input); return entity; @@ -18,7 +18,7 @@ public class PlayerEntityParser extends PlayerParser { public Object getDefault(CommandEnvironment env) { Player net = (Player)super.getDefault(env); - return net == null ? null : net.getEntity(); + return net == null ? null : net.getPresentEntity(); } public Class getTypeClass() { diff --git a/java/src/game/command/commands/CommandOfflinetp.java b/java/src/game/command/commands/CommandOfflinetp.java index 7ad7c0a..a7340b7 100644 --- a/java/src/game/command/commands/CommandOfflinetp.java +++ b/java/src/game/command/commands/CommandOfflinetp.java @@ -28,7 +28,7 @@ public class CommandOfflinetp extends Command { public Object exec(CommandEnvironment env, Executor exec, String user, List entities) { Player player = env.getServer().getPlayer(user); - Position pos = player != null ? player.getEntity().getPos() : env.getServer().getOfflinePosition(user); + Position pos = player != null ? (player.getPresentEntity() != null ? player.getPresentEntity().getPos() : null) : env.getServer().getOfflinePosition(user); if(pos == null) throw new RunException("Spieler '%s' konnte nicht gefunden werden", user); for(Entity entity : entities) { diff --git a/java/src/game/command/commands/CommandSpawn.java b/java/src/game/command/commands/CommandSpawn.java index d4c8096..aff6b20 100644 --- a/java/src/game/command/commands/CommandSpawn.java +++ b/java/src/game/command/commands/CommandSpawn.java @@ -54,7 +54,7 @@ public class CommandSpawn extends Command { } world.strikeLightning(pos.xCoord, pos.yCoord, pos.zCoord, color, tag != null && tag.hasKey("damage", 3) ? tag.getInteger("damage") : 0, tag != null && tag.hasKey("fire", 1) && tag.getBoolean("fire"), - exec instanceof Player && tag != null && tag.hasKey("summoned", 1) && tag.getBoolean("summoned") ? ((Player)exec).getEntity() : null); + exec instanceof Player && tag != null && tag.hasKey("summoned", 1) && tag.getBoolean("summoned") ? ((Player)exec).getPresentEntity() : null); } exec.logConsole("%sBlitz bei %d, %d, %d in %s erschaffen", count == 1 ? "" : (count + "x "), (int)pos.xCoord, (int)pos.yCoord, (int)pos.zCoord, world.dimension.getFormattedName(false)); return null; diff --git a/java/src/game/entity/Entity.java b/java/src/game/entity/Entity.java index dcf7b23..2ea54cc 100755 --- a/java/src/game/entity/Entity.java +++ b/java/src/game/entity/Entity.java @@ -2569,10 +2569,10 @@ public abstract class Entity // return new HoverEvent(HoverEvent.Action.SHOW_ENTITY, new ChatComponentText(nbttagcompound.toString())); // } -// public boolean isVisibleTo(EntityNPCMP player) -// { -// return true; -// } + public boolean isVisibleTo(EntityNPC player) + { + return true; + } public BoundingBox getEntityBoundingBox() { diff --git a/java/src/game/entity/EntityTrackerEntry.java b/java/src/game/entity/EntityTrackerEntry.java index 64709e0..b560415 100755 --- a/java/src/game/entity/EntityTrackerEntry.java +++ b/java/src/game/entity/EntityTrackerEntry.java @@ -371,7 +371,7 @@ public class EntityTrackerEntry { double d1 = playerMP.posZ - (double)(this.encodedPosZ / 32); return d0 >= (double)(-this.trackingDistanceThreshold) && d0 <= (double)this.trackingDistanceThreshold && d1 >= (double)(-this.trackingDistanceThreshold) && d1 <= (double)this.trackingDistanceThreshold - ; // && this.trackedEntity.isVisibleTo(playerMP); + && this.trackedEntity.isVisibleTo(playerMP); } private boolean isPlayerWatchingThisChunk(EntityNPC playerMP) { diff --git a/java/src/game/entity/npc/EntityNPC.java b/java/src/game/entity/npc/EntityNPC.java index 623132e..30edcaf 100755 --- a/java/src/game/entity/npc/EntityNPC.java +++ b/java/src/game/entity/npc/EntityNPC.java @@ -1134,6 +1134,11 @@ public abstract class EntityNPC extends EntityLiving public float getHeightDeviation(Random rand) { return 0.0f; } + + public boolean isVisibleTo(EntityNPC player) + { + return this.connection == null || !this.connection.isInEditor(); + } // public abstract Alignment getNaturalAlign(Random rand); @@ -3256,7 +3261,7 @@ public abstract class EntityNPC extends EntityLiving } public void onDataWatcherUpdate(int data) { - if(this.isPlayer() && (data == 29 || data == 11)) // && this.worldObj.client) + if(this.isPlayer() && data == 29) // (data == 29 || data == 11)) // && this.worldObj.client) this.updateSize(); } @@ -3457,7 +3462,7 @@ public abstract class EntityNPC extends EntityLiving // align = this.getNaturalAlign(this.rand); // } this.setAlignment(align); - this.setHeight(tagCompund.hasKey("Height", 5) ? tagCompund.getFloat("Height") : this.getBaseSize(this.rand)); + this.setHeight(tagCompund.hasKey("Height", 5) ? tagCompund.getFloat("Height") : (this.isPlayer() ? this.getBaseSize(this.rand) / this.species.renderer.height * this.species.size : this.getBaseSize(this.rand))); this.setManaPoints(tagCompund.getInteger("Mana")); Enum type = null; if(tagCompund.hasKey("ClassType", 8) && this.species != null && this.species.classEnum != null) { @@ -4426,7 +4431,7 @@ public abstract class EntityNPC extends EntityLiving if(!this.isPlayer()) this.setItemInfo(info); this.setAlignment(align != null ? align.alignment : this.getNaturalAlign(this.rand)); - this.setHeight(this.getBaseSize(this.rand)); + this.setHeight(this.isPlayer() ? this.getBaseSize(this.rand) / this.species.renderer.height * this.species.size : this.getBaseSize(this.rand)); return align != null ? align : new AlignmentData(this.alignment); } diff --git a/java/src/game/entity/npc/PlayerCharacter.java b/java/src/game/entity/npc/PlayerCharacter.java new file mode 100644 index 0000000..cc39e4e --- /dev/null +++ b/java/src/game/entity/npc/PlayerCharacter.java @@ -0,0 +1,23 @@ +package game.entity.npc; + +import game.world.BlockPos; + +public class PlayerCharacter { + public final String name; + public final String info; + public final Alignment align; + public final String dim; + public final BlockPos pos; + public final String type; + public final int level; + + public PlayerCharacter(String name, String info, Alignment align, String dim, BlockPos pos, String type, int level) { + this.name = name; + this.info = info; + this.align = align; + this.dim = dim; + this.pos = pos; + this.type = type; + this.level = level; + } +} diff --git a/java/src/game/entity/types/EntityLiving.java b/java/src/game/entity/types/EntityLiving.java index 4ba56ac..2ca2798 100755 --- a/java/src/game/entity/types/EntityLiving.java +++ b/java/src/game/entity/types/EntityLiving.java @@ -144,6 +144,8 @@ public abstract class EntityLiving extends Entity protected boolean firstEffectUpdate = true; private boolean attacked; private boolean damaged; + + private String description; private String blockType; @@ -477,6 +479,14 @@ public abstract class EntityLiving extends Entity // /** // * Only use is to identify if class is an instance of player for experience dropping // */ + + public String getDescription() { + return this.description; + } + + public void setDescription(String desc) { + this.description = desc; + } public Random getRNG() { @@ -594,6 +604,8 @@ public abstract class EntityLiving extends Entity // tagCompound.setBoolean("NoAI", this.isAIDisabled()); // } tagCompound.setInteger("Age", this.getGrowingAge()); + if(this.description != null) + tagCompound.setString("Description", this.description); } /** @@ -661,6 +673,9 @@ public abstract class EntityLiving extends Entity // this.setNoAI(tagCompund.getBoolean("NoAI")); this.setGrowingAge(tagCompund.getInteger("Age")); + this.description = tagCompund.hasKey("Description", 8) ? tagCompund.getString("Description") : null; + if(this.description != null && this.description.isEmpty()) + this.description = null; } protected void updateEffects() diff --git a/java/src/game/gui/GuiCharacters.java b/java/src/game/gui/GuiCharacters.java new file mode 100644 index 0000000..1c82153 --- /dev/null +++ b/java/src/game/gui/GuiCharacters.java @@ -0,0 +1,104 @@ +package game.gui; + +import game.color.TextColor; +import game.entity.npc.PlayerCharacter; +import game.gui.element.ActButton; +import game.gui.element.ActButton.Mode; +import game.gui.element.GuiList; +import game.gui.element.ListEntry; +import game.gui.element.NavButton; +import game.gui.element.TransparentBox; +import game.packet.CPacketAction; +import game.renderer.Drawing; + +public class GuiCharacters extends GuiList +{ + protected class CharacterEntry implements ListEntry + { + private final PlayerCharacter character; + private final boolean initial; + + protected CharacterEntry(PlayerCharacter character, boolean initial) + { + this.character = character; + this.initial = initial; + } + + public void draw(int x, int y, int mouseX, int mouseY, boolean hovered) + { + if(this.initial) + Drawing.drawRect(x, y, 1, 36, 0xffaf0000); + String str = this.character == null ? TextColor.BLUE + "[" + TextColor.CYAN + "+" + TextColor.BLUE + "]" : + String.format(TextColor.GREEN + "Level " + TextColor.DGREEN + "%d " + TextColor.YELLOW + "%s " + TextColor.VIOLET + "%s" + TextColor.GRAY + " [%s%s" + TextColor.GRAY + "]", + character.level, character.type, character.name, character.align.color, character.align.display); + String pos = this.character == null ? TextColor.BROWN + "Neuen Charakter erstellen" : + String.format(TextColor.NEON + "%s " + TextColor.GRAY + "bei " + TextColor.ACID + "%d" + TextColor.GRAY + ", " + TextColor.ACID + "%d" + TextColor.GRAY + ", " + TextColor.ACID + "%d", + character.dim, character.pos.getX(), character.pos.getY(), character.pos.getZ()); + Drawing.drawText(str, x + 3, y, 0xffffffff); + Drawing.drawText(pos, x + 3, y + 16, 0xffffffff); + } + + public void select(boolean dclick, int mx, int my) + { + GuiCharacters.this.updateButtons(); + } + } + + public static final GuiCharacters INSTANCE = new GuiCharacters(); + + private TransparentBox descField; + private ActButton actionButtom; + + private GuiCharacters() { + } + + private void updateButtons() { + CharacterEntry entry = this.getSelected(); + this.descField.setText(entry != null && entry.character == null ? "*neuer Charakter*" : (entry == null || entry.character.info == null ? "*keine Beschreibung vorhanden*" : this.getSelected().character.info)); + this.actionButtom.setText(entry != null && entry.character == null ? "Charakter erstellen" : "Charakter spielen"); + this.actionButtom.enabled = entry != null; + } + + public void init(int width, int height) + { + super.init(width, height); + this.setDimensions(width - 400, height, 52, height - 52); + this.elements.clear(); + if(this.gm.getNetHandler() != null) { + int initialSelection = this.gm.getNetHandler().getSelectedCharacter(); + for(PlayerCharacter character : this.gm.getNetHandler().getCharacterList()) { + this.elements.add(new CharacterEntry(character, initialSelection == this.elements.size())); + } + this.elements.add(new CharacterEntry(null, false)); + this.setSelected(initialSelection); + } + this.descField = this.add(new TransparentBox(width - 400, 0, 400, height - 28, "")); + this.actionButtom = this.add(new ActButton(width - 198 * 2, height - 24, 194, 20, new ActButton.Callback() { + public void use(ActButton elem, Mode action) { + CharacterEntry entry = GuiCharacters.this.getSelected(); + if(entry != null && GuiCharacters.this.gm.getNetHandler() != null) { + if(entry.character == null) + GuiCharacters.this.gm.getNetHandler().addToSendQueue(new CPacketAction(CPacketAction.Action.OPEN_EDITOR)); + else + GuiCharacters.this.gm.getNetHandler().addToSendQueue(new CPacketAction(CPacketAction.Action.SELECT_CHARACTER, GuiCharacters.this.selectedElement)); + } + } + }, "")); + this.add(new NavButton(width - 198, height - 24, 194, 20, GuiMenu.INSTANCE, "Abbrechen")); + this.updateButtons(); + } + + public String getTitle() { + return "Charakter anpassen"; + } + + public int getListWidth() + { + return 560; + } + + public int getSlotHeight() + { + return 36 + 4; + } +} diff --git a/java/src/game/gui/GuiConsole.java b/java/src/game/gui/GuiConsole.java index 5574fc1..0a984e5 100644 --- a/java/src/game/gui/GuiConsole.java +++ b/java/src/game/gui/GuiConsole.java @@ -170,9 +170,9 @@ public class GuiConsole extends Gui implements Textbox.Callback { int i = this.inputField.getNthCharFromPos(); this.foundPlayerNames.clear(); this.autocompleteIndex = 0; - String s = this.inputField.getText().substring(i).toLowerCase(); +// String s = this.inputField.getText().substring(i).toLowerCase(); String s1 = this.inputField.getText().substring(0, this.inputField.getCursorPosition()); - String[] localMatches = this.sendAutocompleteRequest(s1, s); + String[] localMatches = this.sendAutocompleteRequest(s1); if(localMatches != null) { this.onAutocompleteResponse(localMatches); return; @@ -236,7 +236,7 @@ public class GuiConsole extends Gui implements Textbox.Callback { // return Lists.newArrayList(); } - private String[] sendAutocompleteRequest(String currentText, String newText) + private String[] sendAutocompleteRequest(String currentText) { if (currentText.length() >= 1) { diff --git a/java/src/game/gui/GuiMenu.java b/java/src/game/gui/GuiMenu.java index 538aa24..c138fbc 100644 --- a/java/src/game/gui/GuiMenu.java +++ b/java/src/game/gui/GuiMenu.java @@ -107,9 +107,10 @@ public class GuiMenu extends Gui { this.pickSplash(); } else { - this.add(new NavButton(0, 0, 400, 24, null, "Zurück zum Spiel")); - this.add(new NavButton(0, 28, 198, 24, GuiOptions.getPage(), "Einstellungen")); - this.add(new NavButton(202, 28, 198, 24, GuiSkin.INSTANCE, "Charakter")); + this.add(new NavButton(0, 0, 400, 24, this.gm.charEditor ? GuiSkin.INSTANCE : null, this.gm.charEditor ? "Zurück zum Charakter-Editor" : "Zurück zum Spiel")); + this.add(new NavButton(0, 28, this.gm.charEditor ? 400 : 198, 24, GuiOptions.getPage(), "Einstellungen")); + if(!this.gm.charEditor) + this.add(new NavButton(202, 28, 198, 24, GuiCharacters.INSTANCE, "Charakter")); if(!this.gm.isRemote() && !this.gm.debugWorld) { this.add(new Textbox(0, 56, 96, 24, 5, true, new Textbox.Callback() { public void use(Textbox elem, Action value) { diff --git a/java/src/game/gui/GuiSkin.java b/java/src/game/gui/GuiSkin.java index 3c0faa3..459b6b6 100755 --- a/java/src/game/gui/GuiSkin.java +++ b/java/src/game/gui/GuiSkin.java @@ -25,7 +25,6 @@ import game.gui.element.Element; import game.gui.element.GuiList; import game.gui.element.Label; import game.gui.element.ListEntry; -import game.gui.element.NavButton; import game.gui.element.Slider; import game.gui.element.Textbox; import game.gui.element.Textbox.Action; @@ -174,43 +173,43 @@ public class GuiSkin extends GuiList { // if(GuiSkin.this.adjust.dragging) // return; - if (dclick) - { - GuiSkin.this.gm.displayGuiScreen(GuiMenu.INSTANCE); - return; - } - else { - BufferedImage img = this.skinImage; +// if (dclick) +// { +// GuiSkin.this.gm.displayGuiScreen(GuiMenu.INSTANCE); +// return; +// } +// else { + BufferedImage img = this.skinImage; // boolean slim = false; - if(this.charinfo != null) { - try { - img = TextureUtil.readImage(FileUtils.getResource( - EntityNPC.getSkinTexture(this.charinfo.skin.startsWith("~") ? this.charinfo.skin.substring(1) : - this.charinfo.skin))); - } - catch(IOException e) { - if(e instanceof FileNotFoundException) - Log.JNI.warn("Textur für Skin ist nicht vorhanden: " + - EntityNPC.getSkinTexture(this.charinfo.skin.startsWith("~") ? this.charinfo.skin.substring(1) : - this.charinfo.skin)); - else - Log.JNI.error(e, "Konnte Textur nicht laden"); - return; - } + if(this.charinfo != null) { + try { + img = TextureUtil.readImage(FileUtils.getResource( + EntityNPC.getSkinTexture(this.charinfo.skin.startsWith("~") ? this.charinfo.skin.substring(1) : + this.charinfo.skin))); + } + catch(IOException e) { + if(e instanceof FileNotFoundException) + Log.JNI.warn("Textur für Skin ist nicht vorhanden: " + + EntityNPC.getSkinTexture(this.charinfo.skin.startsWith("~") ? this.charinfo.skin.substring(1) : + this.charinfo.skin)); + else + Log.JNI.error(e, "Konnte Textur nicht laden"); + return; + } // slim = this.charinfo.skin.startsWith("~"); - } + } // else if(this.skinFile != null) { // slim = this.skinFile.getName().startsWith("slim_"); // } // GuiSkin.this.selectEntry(slotIndex, slim); - GuiSkin.this.convertButton1.enabled = this.canConvert(); - GuiSkin.this.convertButton2.enabled = this.canConvert(); - GuiSkin.this.templateButton.enabled = this.canCopy(); - GuiSkin.this.selectSkin(img, this.model); - if(mx < 16 && mx > 0) - GuiSkin.this.gm.displayGuiScreen(GuiMenu.INSTANCE); - return; - } + GuiSkin.this.convertButton1.enabled = this.canConvert(); + GuiSkin.this.convertButton2.enabled = this.canConvert(); + GuiSkin.this.templateButton.enabled = this.canCopy(); + GuiSkin.this.selectSkin(img, this.model); +// if(mx < 16 && mx > 0) +// GuiSkin.this.gm.displayGuiScreen(GuiMenu.INSTANCE); +// return; +// } } public File getFile() @@ -285,6 +284,7 @@ public class GuiSkin extends GuiList private DragAdjust adjust; private float yaw = -15.0f; private float pitch = -15.0f; + private boolean waiting = true; private GuiSkin() { } @@ -292,7 +292,13 @@ public class GuiSkin extends GuiList public void init(int width, int height) { super.init(width, height); + this.waiting = true; this.setDimensions(400, height, 52, height - 52); + if(this.gm.getRenderManager().gm == null) { + this.unload(); + this.adjust = null; + return; + } this.load(null, this.gm.thePlayer == null ? ModelType.HUMANOID : this.gm.thePlayer.getModel()); this.convertButton1 = this.add(new ActButton(10, height - 48, 200, 20, new ActButton.Callback() { public void use(ActButton elem, Mode action) { @@ -356,7 +362,7 @@ public class GuiSkin extends GuiList this.add(new ActButton(width - 400 + (z % 2) * 196, 4 + 23 * (z / 2), 194, 20, new ActButton.Callback() { public void use(ActButton elem, Mode action) { if(GuiSkin.this.gm.thePlayer != null) { - GuiSkin.this.gm.displayGuiScreen(GuiMenu.INSTANCE); + GuiSkin.this.gm.displayGuiScreen(null); GuiSkin.this.gm.thePlayer.sendQueue.addToSendQueue(new CPacketAction(CPacketAction.Action.SET_SPECIES, EntityRegistry.getEntityID(species.clazz))); // for(ActButton btn : speciesBtns) { // btn.enabled = btn != elem; @@ -375,6 +381,7 @@ public class GuiSkin extends GuiList alignBtns[z] = this.add(new ActButton(width - 400 + (z % 3) * 131, height - 198 + 23 * (z / 3), 129, 20, new ActButton.Callback() { public void use(ActButton elem, Mode action) { if(GuiSkin.this.gm.thePlayer != null) { + GuiSkin.this.waiting = false; GuiSkin.this.gm.thePlayer.sendQueue.addToSendQueue(new CPacketAction(CPacketAction.Action.SET_ALIGN, align.ordinal())); for(ActButton btn : alignBtns) { btn.enabled = btn != elem; @@ -384,22 +391,31 @@ public class GuiSkin extends GuiList }, align.color + align.display)); alignBtns[z].enabled = this.gm.thePlayer == null || this.gm.thePlayer.getAlignment() != align; } - this.add(new Slider(width - 400, height - 28 - 84, 390, 20, 1, 120, 320, 180, this.gm.thePlayer == null ? 180 : (int)(this.gm.thePlayer.getSpecies().size * this.gm.thePlayer.getHeight() * 100.0f + 0.5f), new Slider.Callback() { + this.add(new Slider(width - 400, height - 28 - 84, 390, 20, 1, 120, 320, 180, this.gm.thePlayer == null ? 180 : (int)(this.gm.thePlayer.getSpecies().renderer.height * this.gm.thePlayer.getHeight() * 100.0f + 0.5f), new Slider.Callback() { public void use(Slider elem, int value) { - if(GuiSkin.this.gm.thePlayer != null) + if(GuiSkin.this.gm.thePlayer != null) { + GuiSkin.this.waiting = false; GuiSkin.this.gm.thePlayer.sendQueue.addToSendQueue(new CPacketAction(CPacketAction.Action.SET_HEIGHT, value)); + } } }, "Spieler-Größe", "cm")); this.add(new Label(width - 400, height + 2 - 28 - 24 - 30, 390, 20, "Anzeigename", true)); - this.add(new NavButton(width - 274 + 154, height - 24, 264 - 154, 20, GuiMenu.INSTANCE, "Fertig")); + this.add(new ActButton(width - 274 + 154, height - 24, 264 - 154, 20, new ActButton.Callback() { + public void use(ActButton elem, Mode action) { + if(GuiSkin.this.gm.thePlayer != null) + GuiSkin.this.gm.thePlayer.sendQueue.addToSendQueue(new CPacketAction(CPacketAction.Action.CLOSE_EDITOR)); + } + }, "Fertig")); Textbox nameField = this.add(new Textbox(width - 400, height + 2 - 28 - 34, 390, 20, Player.MAX_NICK_LENGTH, true, new Textbox.Callback() { public void use(Textbox elem, Action value) { if(value == Action.SEND || value == Action.UNFOCUS) { String name = elem.getText(); if(name.isEmpty()) elem.setText(GuiSkin.this.gm.thePlayer == null ? "..." : GuiSkin.this.gm.thePlayer.getCustomNameTag()); - else if(GuiSkin.this.gm.thePlayer != null) + else if(GuiSkin.this.gm.thePlayer != null) { + GuiSkin.this.waiting = false; GuiSkin.this.gm.thePlayer.sendQueue.addToSendQueue(new CPacketMessage(CPacketMessage.Type.DISPLAY, name)); + } } } }, Player.VALID_NICK, this.gm.thePlayer == null ? "" : this.gm.thePlayer.getCustomNameTag())); @@ -420,8 +436,21 @@ public class GuiSkin extends GuiList public void drawOverlays() { - drawEntity(400 + (this.gm.fb_x - 400 - 400) / 2, this.gm.fb_y / 2 + 160, 160.0f - / this.gm.thePlayer.getHeight(), this.yaw, this.pitch, this.gm.thePlayer); + if(this.adjust != null) + drawEntity(400 + (this.gm.fb_x - 400 - 400) / 2, this.gm.fb_y / 2 + 160, 160.0f + / this.gm.thePlayer.getHeight(), this.yaw, this.pitch, this.gm.thePlayer); + } + + public void updateScreen() { + if(this.adjust == null && this.gm.getRenderManager().gm != null) + this.gm.displayGuiScreen(this); + } + + public void checkReopen() { + if(this.adjust != null && this.waiting) { + this.waiting = false; + this.gm.displayGuiScreen(this); + } } public String getTitle() { diff --git a/java/src/game/network/ClientPlayer.java b/java/src/game/network/ClientPlayer.java index 45dc511..7e3ab99 100755 --- a/java/src/game/network/ClientPlayer.java +++ b/java/src/game/network/ClientPlayer.java @@ -1,5 +1,6 @@ package game.network; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -20,10 +21,12 @@ import game.entity.effect.EntityLightning; import game.entity.item.EntityBoat; import game.entity.item.EntityXp; import game.entity.npc.EntityNPC; +import game.entity.npc.PlayerCharacter; import game.entity.projectile.EntityProjectile; import game.entity.types.EntityLiving; import game.gui.Gui; import game.gui.GuiConsole; +import game.gui.GuiSkin; import game.gui.container.GuiMachine; import game.gui.container.GuiMerchant; import game.init.EntityRegistry; @@ -73,6 +76,7 @@ import game.packet.SPacketBlockAction; import game.packet.SPacketBlockBreakAnim; import game.packet.SPacketBlockChange; import game.packet.SPacketCamera; +import game.packet.SPacketCharacterList; import game.packet.SPacketChunkData; import game.packet.SPacketCollectItem; import game.packet.SPacketDestroyEntities; @@ -137,8 +141,9 @@ public class ClientPlayer extends NetHandler private boolean doneLoadingTerrain; // private boolean travelSound; private final Map playerList = Maps.newTreeMap(); + private final Map characterList = Maps.newHashMap(); // private final List> players = Lists.newArrayList(); -// private boolean field_147308_k = false; + private int selectedCharacter = -1; /** * Just an ordinary random number generator, used to randomize audio pitch of item/orb pickup and randomize both @@ -168,13 +173,14 @@ public class ClientPlayer extends NetHandler public void handleJoinGame(SPacketJoinGame packetIn) { NetHandler.checkThread(packetIn, this, this.gameController); + this.gameController.charEditor = packetIn.isInEditor(); this.gameController.controller = new PlayerController(this.gameController, this); this.clientWorldController = new WorldClient(this.gameController.debugWorld, packetIn.getDimension()); // this.gameController.gameSettings.difficulty = packetIn.getDifficulty(); this.gameController.loadWorld(this.clientWorldController, packetIn.getEntityType()); // this.gameController.thePlayer.dimension = this.clientWorldController.dimension.getDimensionId(); - this.gameController.displayGuiScreen(null); this.gameController.thePlayer.setId(packetIn.getEntityId()); + this.gameController.displayGuiScreen(this.gameController.charEditor ? GuiSkin.INSTANCE : null); // this.currentServerMaxPlayers = packetIn.getMaxPlayers(); // this.gameController.controller.setCheat(packetIn.getCheat()); // this.gameController.updateViewDistance(); @@ -435,6 +441,9 @@ public class ClientPlayer extends NetHandler if (entity != null && packetIn.func_149376_c() != null) { entity.getDataWatcher().updateWatchedObjectsFromList(packetIn.func_149376_c()); + + if(entity == this.gameController.thePlayer && this.gameController.open instanceof GuiSkin) + ((GuiSkin)this.gameController.open).checkReopen(); } } @@ -993,6 +1002,7 @@ public class ClientPlayer extends NetHandler public void handleRespawn(SPacketRespawn packetIn) { NetHandler.checkThread(packetIn, this, this.gameController, this.clientWorldController); + this.gameController.charEditor = packetIn.isInEditor(); Dimension dim = packetIn.getDimension(); if (dim.getDimensionId() != this.clientWorldController.dimension.getDimensionId()) // this.gameController.thePlayer.dimension) @@ -1006,10 +1016,13 @@ public class ClientPlayer extends NetHandler // this.clientWorldController.setWorldScoreboard(scoreboard); this.gameController.loadWorld(this.clientWorldController, packetIn.getEntityType()); // this.gameController.thePlayer.dimension = dim.getDimensionId(); - this.gameController.displayGuiScreen(null); } +// else if(this.gameController.charEditor) { +// this.gameController.displayGuiScreen(GuiSkin.INSTANCE); +// } this.gameController.setDimensionAndSpawnPlayer(dim.getDimensionId(), packetIn.getEntityType()); + this.gameController.displayGuiScreen(this.gameController.charEditor ? GuiSkin.INSTANCE : null); // this.gameController.controller.setCheat(packetIn.getCheat()); } @@ -1506,6 +1519,19 @@ public class ClientPlayer extends NetHandler // this.gameController.infolist(list, data); } + public void handleCharacterList(SPacketCharacterList packet) + { + NetHandler.checkThread(packet, this, this.gameController); + + for(Entry data : packet.getEntries()) { + if(data.getValue() == null) + this.characterList.remove(data.getKey()); + else + this.characterList.put(data.getKey(), data.getValue()); + } + this.selectedCharacter = packet.getSelected(); + } + public void handleKeepAlive(SPacketKeepAlive packetIn) { this.addToSendQueue(new CPacketKeepAlive(packetIn.getValue())); @@ -1858,6 +1884,16 @@ public class ClientPlayer extends NetHandler return this.playerList.entrySet(); } + public Collection getCharacterList() + { + return this.characterList.values(); + } + + public int getSelectedCharacter() + { + return this.selectedCharacter; + } + public Iterable getPlayerNames() { return this.playerList.keySet(); diff --git a/java/src/game/network/PacketRegistry.java b/java/src/game/network/PacketRegistry.java index 904472c..918a383 100755 --- a/java/src/game/network/PacketRegistry.java +++ b/java/src/game/network/PacketRegistry.java @@ -58,6 +58,7 @@ import game.packet.SPacketBlockAction; import game.packet.SPacketBlockBreakAnim; import game.packet.SPacketBlockChange; import game.packet.SPacketCamera; +import game.packet.SPacketCharacterList; import game.packet.SPacketChunkData; import game.packet.SPacketCollectItem; import game.packet.SPacketDestroyEntities; @@ -176,6 +177,7 @@ public enum PacketRegistry this.server(SPacketTrades.class); // this.server(SPacketNotify.class); this.server(SPacketDimensionName.class); + this.server(SPacketCharacterList.class); this.client(CPacketKeepAlive.class); this.client(CPacketMessage.class); diff --git a/java/src/game/network/Player.java b/java/src/game/network/Player.java index c9022eb..bdc9ba9 100755 --- a/java/src/game/network/Player.java +++ b/java/src/game/network/Player.java @@ -24,6 +24,7 @@ import game.clipboard.RotationValue; import game.clipboard.Vector; import game.color.TextColor; import game.command.Executor; +import game.dimension.Dimension; import game.entity.Entity; import game.entity.animal.EntityHorse; import game.entity.item.EntityItem; @@ -31,6 +32,7 @@ import game.entity.item.EntityXp; import game.entity.npc.Alignment; import game.entity.npc.EntityHuman; import game.entity.npc.EntityNPC; +import game.entity.npc.PlayerCharacter; import game.entity.projectile.EntityArrow; import game.entity.types.EntityLiving; import game.init.BlockRegistry; @@ -40,6 +42,7 @@ import game.init.EntityRegistry; import game.init.Items; import game.init.RotationRegistry; import game.init.SoundEvent; +import game.init.UniverseRegistry; import game.inventory.Container; import game.inventory.ContainerChest; import game.inventory.ContainerHorseInventory; @@ -54,11 +57,10 @@ import game.item.ItemStack; import game.log.Log; import game.material.Material; import game.nbt.NBTTagCompound; -import game.nbt.NBTTagDouble; -import game.nbt.NBTTagFloat; import game.nbt.NBTTagList; import game.nbt.NBTTagString; import game.packet.CPacketAction; +import game.packet.CPacketAction.Action; import game.packet.CPacketBook; import game.packet.CPacketBreak; import game.packet.CPacketCheat; @@ -88,6 +90,7 @@ import game.packet.S39PacketPlayerAbilities; import game.packet.S3APacketTabComplete; import game.packet.SPacketAnimation; import game.packet.SPacketBlockChange; +import game.packet.SPacketCharacterList; import game.packet.SPacketChunkData; import game.packet.SPacketDestroyEntities; import game.packet.SPacketDisconnect; @@ -140,7 +143,7 @@ public class Player extends NetHandler implements ICrafting, Executor public static class UserValidator implements CharValidator { public boolean valid(char ch) { - return /* (ch >= 'A' && ch <= 'Z') || */ (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-'; + return (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-'; } } @@ -154,6 +157,7 @@ public class Player extends NetHandler implements ICrafting, Executor public static final int MAX_NICK_LENGTH = 32; public static final int MAX_PASS_LENGTH = 64; public static final int MAX_CMD_LENGTH = 1024; + public static final int MAX_INFO_LENGTH = 4096; public static final CharValidator VALID_USER = new UserValidator(); public static final CharValidator VALID_NICK = new NickValidator(); @@ -176,6 +180,7 @@ public class Player extends NetHandler implements ICrafting, Executor private double lastPosY; private double lastPosZ; private boolean hasMoved = true; + private boolean charEditor = true; private boolean admin; private int ping; @@ -310,6 +315,14 @@ public class Player extends NetHandler implements ICrafting, Executor this.respawnTimer = ExtMath.clampi(Config.respawnTime, 2, 20); } + public boolean isInEditor() { + return this.charEditor; + } + + public EntityNPC getPresentEntity() { + return this.charEditor ? null : this.entity; + } + public EntityNPC getEntity() { return this.entity; } @@ -610,6 +623,7 @@ public class Player extends NetHandler implements ICrafting, Executor this.characters.add(list.getCompoundTagAt(z)); } this.selected = Math.min(this.selected, this.characters.size() - 1); + this.charEditor = this.selected < 0; // this.stats.clear(); // if(tag.hasKey("Stats", 10)) { // NBTTagCompound stats = tag.getCompoundTag("Stats"); @@ -1501,40 +1515,15 @@ public class Player extends NetHandler implements ICrafting, Executor String info = this.getRotationInfo(); this.addHotbar(TextColor.YELLOW + (info.isEmpty() ? "Keine Drehung" : info)); } - - - public List getCharacters() { - return this.characters; - } - - public NBTTagCompound addCharacter(String id) { - NBTTagCompound tag = new NBTTagCompound(); - this.characters.add(tag); - tag.setString("id", id); - return tag; - } - - public NBTTagCompound getSelectedCharacter(boolean create) { - NBTTagCompound tag = this.characters.isEmpty() || this.selected < 0 ? null : this.characters.get(this.selected); - if(create && tag == null) { - tag = new NBTTagCompound(); - this.selected = this.characters.size(); - this.characters.add(tag); - return tag; - } - else if(create) { - tag.getKeySet().clear(); - } - return tag; - } - - public void selectCharacter(int index) { - if(index == this.selected || index >= this.characters.size()) - return; - this.server.swapPlayer(this, index < 0 ? null : this.characters.get(index)); - this.selected = index; + + public NBTTagCompound readCharacter() { + return this.characters.isEmpty() || this.selected < 0 ? null : this.characters.get(this.selected); } + public void writeCharacter(NBTTagCompound tag) { + if(!this.characters.isEmpty() && this.selected >= 0) + this.characters.set(this.selected, tag); + } public void disconnect() { @@ -1563,7 +1552,27 @@ public class Player extends NetHandler implements ICrafting, Executor this.server.removePlayer(this); } + public PlayerCharacter getCharacterInfo(NBTTagCompound tag) { + String name = tag.getString("CustomName"); + String info = tag.getString("Description"); + if(info != null && info.isEmpty()) + info = null; + Alignment align = Alignment.getByName(tag.getString("Align")); + NBTTagList position = tag.getTagList("Pos", 6); + Dimension dimension = UniverseRegistry.getDimension(tag.getInteger("Dimension")); + String dim = dimension == null ? "???" : dimension.getFormattedName(false); + BlockPos pos = new BlockPos(position.getDoubleAt(0), position.getDoubleAt(1), position.getDoubleAt(2)); + String type = EntityRegistry.getEntityName(tag.getString("id")); + int level = tag.getInteger("XpLevel"); + return new PlayerCharacter(name, info, align, dim, pos, type, level); + } + public void onConnect() { + List chars = Lists.newArrayList(); + for(NBTTagCompound tag : this.characters) { + chars.add(this.getCharacterInfo(tag)); + } + this.sendPacket(new SPacketCharacterList(this.selected, chars)); if(!this.local) this.server.sendPacket(new SPacketMessage(String.format("%s hat das Spiel betreten", this.user), Type.FEED)); } @@ -1946,7 +1955,12 @@ public class Player extends NetHandler implements ICrafting, Executor if(c < 32 || c == 127) throw new IllegalArgumentException("Ungültige Zeichen in Nachricht"); } - switch(packetIn.getType()) { + + CPacketMessage.Type type = packetIn.getType(); + if(this.charEditor != (type == CPacketMessage.Type.DISPLAY)) + return; + + switch(type) { case COMMAND: if(!this.setVar(msg)) this.runCommand(msg); // this.addFeed(TextColor.RED + "Befehl wurde nicht gefunden"); @@ -2009,7 +2023,7 @@ public class Player extends NetHandler implements ICrafting, Executor public void processComplete(CPacketComplete packetIn) { NetHandler.checkThread(packetIn, this, this.server); - if(!this.isAdmin()) { + if(this.charEditor || !this.isAdmin()) { this.entity.connection.sendPacket(new S3APacketTabComplete(new String[0])); return; } @@ -2043,6 +2057,8 @@ public class Player extends NetHandler implements ICrafting, Executor public void processPlayer(CPacketPlayer packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(this.charEditor) + return; if (!isFinite(packetIn.getPositionX()) || !isFinite(packetIn.getPositionY()) || !isFinite(packetIn.getPositionZ()) || !isFinite(packetIn.getPitch()) || !isFinite(packetIn.getYaw())) { @@ -2285,6 +2301,8 @@ public class Player extends NetHandler implements ICrafting, Executor public void processBreak(CPacketBreak packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(this.charEditor) + return; WorldServer worldserver = this.entity.getServerWorld(); // this.serverController.getWorld(this.playerEntity.dimension); BlockPos blockpos = packetIn.getPosition(); @@ -2369,6 +2387,8 @@ public class Player extends NetHandler implements ICrafting, Executor public void processPlace(CPacketPlace packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(this.charEditor) + return; WorldServer worldserver = this.entity.getServerWorld(); // this.serverController.getWorld(this.playerEntity.dimension); ItemStack itemstack = this.entity.inventory.getCurrentItem(); boolean flag = false; @@ -2472,8 +2492,40 @@ public class Player extends NetHandler implements ICrafting, Executor { NetHandler.checkThread(packetIn, this, this.server); - switch (packetIn.getAction()) + CPacketAction.Action action = packetIn.getAction(); + if(this.charEditor != (action == Action.SET_ALIGN || action == Action.SET_SPECIES || action == Action.SET_HEIGHT || action == Action.CLOSE_EDITOR)) + return; + + switch (action) { + case OPEN_EDITOR: + this.charEditor = true; + NBTTagCompound tag = this.server.swapPlayer(this, null, EntityHuman.class); + if(!this.characters.isEmpty() && this.selected >= 0) + this.characters.set(this.selected, tag); + this.selected = -1; + this.sendPacket(new SPacketCharacterList(this.selected)); + break; + + case CLOSE_EDITOR: + this.charEditor = false; + this.selected = this.characters.size(); + this.characters.add(new NBTTagCompound()); + this.entity.teleport(this.server.getRandomSpawnPosition()); + this.sendPacket(new SPacketCharacterList(this.selected, this.selected, new PlayerCharacter(this.entity.getCustomNameTag(), this.entity.getDescription(), this.entity.getAlignment(), this.entity.worldObj.dimension.getFormattedName(false), this.entity.getPosition(), EntityRegistry.getEntityName(EntityRegistry.getEntityString(this.entity)), this.entity.experienceLevel))); + break; + + case SELECT_CHARACTER: + int index = packetIn.getAuxData(); + if(index == this.selected || index >= this.characters.size() || index < 0) + return; + NBTTagCompound etag = this.server.swapPlayer(this, this.characters.get(index), null); + if(!this.characters.isEmpty() && this.selected >= 0) + this.characters.set(this.selected, etag); + this.selected = index; + this.sendPacket(new SPacketCharacterList(this.selected)); + break; + case START_SNEAKING: this.entity.setSneaking(true); break; @@ -2540,7 +2592,8 @@ public class Player extends NetHandler implements ICrafting, Executor // break; case SET_HEIGHT: - this.entity.setHeight(((float)ExtMath.clampi(packetIn.getAuxData(), 120, 320) * 0.01f) / this.entity.getSpecies().size); + this.entity.setHeight(((float)ExtMath.clampi(packetIn.getAuxData(), 120, 320) * 0.01f) / this.entity.getSpecies().renderer.height); +// Log.CONSOLE.info("" + this.entity.height + "(" + this.entity.getHeight() + ")"); break; case SELECT_TRADE: @@ -2759,23 +2812,9 @@ public class Player extends NetHandler implements ICrafting, Executor case SET_SPECIES: Class clazz = EntityRegistry.getEntityClass(packetIn.getAuxData()); - if(EntityNPC.class.isAssignableFrom(clazz)) { - NBTTagCompound tag = this.addCharacter(EntityRegistry.getEntityString(clazz)); - tag.setInteger("Dimension", this.entity.worldObj.dimension.getDimensionId()); - NBTTagList pos = new NBTTagList(); - pos.appendTag(new NBTTagDouble(this.entity.posX)); - pos.appendTag(new NBTTagDouble(this.entity.posY)); - pos.appendTag(new NBTTagDouble(this.entity.posZ)); - tag.setTag("Pos", pos); - NBTTagList rot = new NBTTagList(); - rot.appendTag(new NBTTagFloat(this.entity.rotYaw)); - rot.appendTag(new NBTTagFloat(this.entity.rotPitch)); - tag.setTag("Rotation", rot); - tag.setString("CustomName", this.entity.getCustomNameTag()); - tag.setString("Align", this.entity.getAlignment().name); - tag.setFloat("Height", this.entity.getHeight()); - this.server.swapPlayer(this, tag); - } + if(EntityNPC.class.isAssignableFrom(clazz)) + this.server.swapPlayer(this, null, (Class)clazz); +// Log.CONSOLE.info("" + this.entity.height + "(" + this.entity.getHeight() + ")"); break; default: @@ -2786,12 +2825,16 @@ public class Player extends NetHandler implements ICrafting, Executor public void processInput(CPacketInput packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(this.charEditor) + return; this.setEntityActionState(packetIn.getStrafeSpeed(), packetIn.getForwardSpeed(), packetIn.isJumping(), packetIn.isSneaking()); } public void processClick(CPacketClick packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(this.charEditor) + return; if (this.entity.openContainer.windowId == packetIn.getWindowId() && this.entity.openContainer.getCanCraft(this.entity)) { @@ -2839,6 +2882,8 @@ public class Player extends NetHandler implements ICrafting, Executor public void processCheat(CPacketCheat packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(this.charEditor) + return; if(!this.isAdmin()) return; @@ -2929,6 +2974,8 @@ public class Player extends NetHandler implements ICrafting, Executor public void processSign(CPacketSign packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(this.charEditor) + return; WorldServer worldserver = this.entity.getServerWorld(); // this.serverController.getWorld(this.playerEntity.dimension); BlockPos blockpos = packetIn.getPosition(); @@ -2984,6 +3031,8 @@ public class Player extends NetHandler implements ICrafting, Executor public void processSkin(CPacketSkin packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(!this.charEditor) + return; // if(!this.netManager.isLocalChannel() && System.currentTimeMillis() - this.lastSkinUpdate < 1000L) { // String comp = "Bitte warte 1 Sekunde bevor du deinen Skin änderst"; //// comp.setColor(); @@ -3003,6 +3052,9 @@ public class Player extends NetHandler implements ICrafting, Executor public void processBook(CPacketBook packetIn) { NetHandler.checkThread(packetIn, this, this.server); + if(this.charEditor) + return; + String[] pages = packetIn.getPages(); // if (!ItemWritableBook.isNBTValid(itemstack1.getTagCompound())) // throw new IOException("Fehlerhafter Buch-Tag!"); diff --git a/java/src/game/packet/CPacketAction.java b/java/src/game/packet/CPacketAction.java index 42f2aae..f65fd47 100755 --- a/java/src/game/packet/CPacketAction.java +++ b/java/src/game/packet/CPacketAction.java @@ -55,6 +55,9 @@ public class CPacketAction implements Packet public static enum Action { + OPEN_EDITOR, + CLOSE_EDITOR, + SELECT_CHARACTER, SWING_ARM, SET_ITEMSLOT, START_SNEAKING, diff --git a/java/src/game/packet/SPacketCharacterList.java b/java/src/game/packet/SPacketCharacterList.java new file mode 100644 index 0000000..b5a0440 --- /dev/null +++ b/java/src/game/packet/SPacketCharacterList.java @@ -0,0 +1,85 @@ +package game.packet; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; + +import game.collect.Maps; +import game.entity.npc.Alignment; +import game.entity.npc.PlayerCharacter; +import game.network.ClientPlayer; +import game.network.Player; +import game.world.BlockPos; +import game.network.Packet; +import game.network.PacketBuffer; + +public class SPacketCharacterList implements Packet { + private final Map players = Maps.newHashMap(); + + private int selected; + + public SPacketCharacterList() { + } + + public SPacketCharacterList(int selected) { + this.selected = selected; + } + + public SPacketCharacterList(int selected, int index, PlayerCharacter conns) { + this.players.put(index, conns); + this.selected = selected; + } + + public SPacketCharacterList(int selected, Iterable conns) { + int pos = 0; + for(PlayerCharacter conn : conns) { + this.players.put(pos++, conn); + } + this.selected = selected; + } + + public void readPacketData(PacketBuffer buf) throws IOException { + int n = buf.readVarIntFromBuffer(); + for(int z = 0; z < n; z++) { + int id = buf.readVarIntFromBuffer(); + String name = buf.readStringFromBuffer(Player.MAX_NICK_LENGTH); + String info = buf.readStringFromBuffer(Player.MAX_INFO_LENGTH); + Alignment align = buf.readEnumValue(Alignment.class); + String dim = buf.readStringFromBuffer(256); + BlockPos pos = buf.readBlockPos(); + String type = buf.readStringFromBuffer(256); + int level = buf.readVarIntFromBuffer(); + this.players.put(id, new PlayerCharacter(name, info, align, dim, pos, type, level)); + } + this.selected = buf.readVarIntFromBuffer(); + } + + public void writePacketData(PacketBuffer buf) throws IOException { + buf.writeVarIntToBuffer(this.players.size()); + for(Entry data : this.players.entrySet()) { + PlayerCharacter chr = data.getValue(); + buf.writeVarIntToBuffer(data.getKey()); + buf.writeString(chr.name); + buf.writeString(chr.info); + buf.writeEnumValue(chr.align); + buf.writeString(chr.dim); + buf.writeBlockPos(chr.pos); + buf.writeString(chr.type); + buf.writeVarIntToBuffer(chr.level); + } + buf.writeVarIntToBuffer(this.selected); + } + + public void processPacket(ClientPlayer handler) { + handler.handleCharacterList(this); + } + + public Collection> getEntries() { + return this.players.entrySet(); + } + + public int getSelected() { + return this.selected; + } +} diff --git a/java/src/game/packet/SPacketJoinGame.java b/java/src/game/packet/SPacketJoinGame.java index 3bb18b5..59568d8 100755 --- a/java/src/game/packet/SPacketJoinGame.java +++ b/java/src/game/packet/SPacketJoinGame.java @@ -12,26 +12,30 @@ public class SPacketJoinGame implements Packet { private int entityId; private NBTTagCompound dimension; private int type; + private boolean editor; public SPacketJoinGame() { } - public SPacketJoinGame(int entityIdIn, Dimension dimensionIn, int type) { + public SPacketJoinGame(int entityIdIn, Dimension dimensionIn, int type, boolean editor) { this.entityId = entityIdIn; this.dimension = dimensionIn.toNbt(false); this.type = type; + this.editor = editor; } public void readPacketData(PacketBuffer buf) throws IOException { this.entityId = buf.readInt(); this.dimension = buf.readNBTTagCompoundFromBuffer(); this.type = buf.readUnsignedShort(); + this.editor = buf.readBoolean(); } public void writePacketData(PacketBuffer buf) throws IOException { buf.writeInt(this.entityId); buf.writeNBTTagCompoundToBuffer(this.dimension); buf.writeShort(this.type & 65535); + buf.writeBoolean(this.editor); } public void processPacket(ClientPlayer handler) { @@ -49,4 +53,8 @@ public class SPacketJoinGame implements Packet { public int getEntityType() { return this.type; } + + public boolean isInEditor() { + return this.editor; + } } diff --git a/java/src/game/packet/SPacketRespawn.java b/java/src/game/packet/SPacketRespawn.java index c94d4bb..4366f0f 100755 --- a/java/src/game/packet/SPacketRespawn.java +++ b/java/src/game/packet/SPacketRespawn.java @@ -12,15 +12,17 @@ public class SPacketRespawn implements Packet { private NBTTagCompound dimension; private int type; + private boolean editor; public SPacketRespawn() { } - public SPacketRespawn(Dimension dimensionIn, int type) + public SPacketRespawn(Dimension dimensionIn, int type, boolean editor) { this.dimension = dimensionIn.toNbt(false); this.type = type; + this.editor = editor; } public void processPacket(ClientPlayer handler) @@ -32,12 +34,14 @@ public class SPacketRespawn implements Packet { this.dimension = buf.readNBTTagCompoundFromBuffer(); this.type = buf.readUnsignedShort(); + this.editor = buf.readBoolean(); } public void writePacketData(PacketBuffer buf) throws IOException { buf.writeNBTTagCompoundToBuffer(this.dimension); buf.writeShort(this.type & 65535); + buf.writeBoolean(this.editor); } public Dimension getDimension() @@ -49,4 +53,8 @@ public class SPacketRespawn implements Packet { return this.type; } + + public boolean isInEditor() { + return this.editor; + } } diff --git a/java/src/game/world/WorldServer.java b/java/src/game/world/WorldServer.java index b94763e..b5e2c34 100755 --- a/java/src/game/world/WorldServer.java +++ b/java/src/game/world/WorldServer.java @@ -1693,7 +1693,7 @@ public final class WorldServer extends World { { for (Player conn : this.server.getPlayers()) { - EntityNPC player = conn.getEntity(); + EntityNPC player = conn.getPresentEntity(); if (player != null && player.worldObj == this && player.getId() != breakerId) { double d0 = (double)pos.getX() - player.posX;