From 72dc4a13058b3399a519bd0de84db83919e2fbd0 Mon Sep 17 00:00:00 2001 From: Sen Date: Thu, 7 Aug 2025 02:17:59 +0200 Subject: [PATCH] fix and improve camera system --- client/src/main/java/client/Client.java | 28 ++++++- client/src/main/java/client/gui/GuiMenu.java | 3 +- .../main/java/client/init/RenderRegistry.java | 3 + .../main/java/client/renderer/Renderer.java | 3 +- .../client/renderer/entity/RenderCamera.java | 22 ++++++ .../main/java/common/ai/EntityAITarget.java | 3 +- .../common/entity/npc/EntityCameraHolder.java | 44 +++++++++++ .../java/common/entity/npc/EntityCpu.java | 64 --------------- .../java/common/entity/npc/EntityMage.java | 2 +- .../java/common/entity/npc/EntityNPC.java | 27 ++++--- .../main/java/common/init/EntityRegistry.java | 2 + .../java/common/init/SpeciesRegistry.java | 5 +- .../command/commands/CommandCamera.java | 2 +- .../server/command/commands/CommandNocam.java | 2 +- .../src/main/java/server/network/Player.java | 78 +++++++++++++------ 15 files changed, 180 insertions(+), 108 deletions(-) create mode 100644 client/src/main/java/client/renderer/entity/RenderCamera.java create mode 100755 common/src/main/java/common/entity/npc/EntityCameraHolder.java delete mode 100755 common/src/main/java/common/entity/npc/EntityCpu.java diff --git a/client/src/main/java/client/Client.java b/client/src/main/java/client/Client.java index ef4f37f7..4abe7c6a 100755 --- a/client/src/main/java/client/Client.java +++ b/client/src/main/java/client/Client.java @@ -111,9 +111,10 @@ import common.effect.StatusEffect; import common.entity.Entity; import common.entity.animal.EntityHorse; import common.entity.item.EntityCamera; +import common.entity.item.EntityCamera.CameraType; import common.entity.item.EntityCart; import common.entity.npc.Energy; -import common.entity.npc.EntityCpu; +import common.entity.npc.EntityCameraHolder; import common.entity.npc.EntityNPC; import common.entity.npc.EntityWaterNPC; import common.entity.npc.PlayerCharacter; @@ -431,6 +432,7 @@ public class Client implements IThreadListener { public boolean charEditor; public boolean fullscreen; public boolean interrupted; + public boolean freecam; private int leftClickCounter; private int rightClickTimer; @@ -717,7 +719,7 @@ public class Client implements IThreadListener { this.dimensionName = "debug"; Space.INSTANCE.setDisplay("Debug-Welt"); this.controller = new PlayerController(this, player); - this.loadWorld(Space.INSTANCE, EntityRegistry.getEntityID(EntityCpu.class)); + this.loadWorld(Space.INSTANCE, EntityRegistry.getEntityID(EntityCameraHolder.class)); this.player.setId(0); this.show(null); this.player.flying = true; @@ -737,6 +739,7 @@ public class Client implements IThreadListener { this.debugWorld = false; this.charEditor = false; this.viewEntity = null; + this.freecam = false; this.connection = null; this.world = null; this.resetWorld(); @@ -1644,6 +1647,7 @@ public class Client implements IThreadListener { { this.resetWorld(); this.viewEntity = null; + this.freecam = false; this.connection = null; this.soundManager.stopSounds(); this.world = new WorldClient(dim); @@ -1691,6 +1695,7 @@ public class Client implements IThreadListener { this.player = this.controller.createPlayerEntity(this.world, type); this.player.getDataWatcher().updateWatchedObjectsFromList(entityplayersp.getDataWatcher().getAllWatched()); this.viewEntity = this.player; + this.freecam = false; this.player.preparePlayerToSpawn(); this.spawnEntity(this.player); this.player.rotYaw = -180.0F; @@ -1750,6 +1755,7 @@ public class Client implements IThreadListener { public void setRenderViewEntity(Entity viewingEntity) { this.viewEntity = viewingEntity; + this.freecam = false; } public void schedule(Runnable task) { @@ -1838,8 +1844,12 @@ public class Client implements IThreadListener { if(this.viewEntity instanceof EntityCamera camera) { camera.onUpdate(); camera.setMovement(this.moveStrafe, this.moveForward, this.jump, this.sneak); - this.getNetHandler().addToSendQueue(new CPacketInput(this.moveStrafe, this.moveForward, this.jump, this.sneak, true)); - this.getNetHandler().addToSendQueue(new CPacketPlayerPosLook(camera.posX, camera.posY, camera.posZ, camera.rotYaw, camera.rotPitch, this.sprint).setCamera()); + if(!this.freecam) { + this.getNetHandler().addToSendQueue(new CPacketInput(this.moveStrafe, this.moveForward, this.jump, this.sneak, true)); + this.getNetHandler().addToSendQueue(new CPacketPlayerPosLook(camera.posX, camera.posY, camera.posZ, camera.rotYaw, camera.rotPitch, this.sprint).setCamera()); + if(this.player != null) + this.player.setPositionAndRotation(camera.posX, camera.posY, camera.posZ, camera.rotYaw, camera.rotPitch); + } // if(!camera.fixed && this.sprint) // this.viewEntity = this.player; } @@ -2723,6 +2733,16 @@ public class Client implements IThreadListener { } } }); + if(Util.DEVMODE) + this.registerDebug(Keysym.SPACE, "Kamera umschalten", new DebugRunner() { + public void execute(Keysym key) { + if(Client.this.world != null && Client.this.player != null) { + Client.this.viewEntity = Client.this.viewEntity == Client.this.player ? new EntityCamera(Client.this.world, + Client.this.player.posX, Client.this.player.posY, Client.this.player.posZ, Client.this.player.rotYaw, Client.this.player.rotPitch, 256, 2.5f, CameraType.FREE, false) : Client.this.player; + Client.this.freecam = Client.this.viewEntity != Client.this.player; + } + } + }); if(Util.DEVMODE) this.registerDebug(Keysym.AE, "Programm sofort beenden und server beenden", new DebugRunner() { public void execute(Keysym key) { diff --git a/client/src/main/java/client/gui/GuiMenu.java b/client/src/main/java/client/gui/GuiMenu.java index bf43d452..cb132539 100644 --- a/client/src/main/java/client/gui/GuiMenu.java +++ b/client/src/main/java/client/gui/GuiMenu.java @@ -11,6 +11,7 @@ import client.gui.element.PressType; import client.gui.options.GuiOptions; import client.renderer.Drawing; import client.window.Keysym; +import common.entity.npc.EntityCameraHolder; import common.rng.Random; import common.util.ExtMath; import common.util.Color; @@ -112,7 +113,7 @@ public class GuiMenu extends Gui { this.add(new NavButton(0, 0, 180, 0, this.gm.charEditor ? GuiChar.INSTANCE : null, this.gm.charEditor ? "Zurück zum Editor" : "Zurück zum Spiel")); this.add(new NavButton(0, 20, 180, 0, GuiOptions.getPage(), "Einstellungen")); if(!this.gm.charEditor) - this.add(new NavButton(0, 40, 180, 0, GuiCharacters.INSTANCE, "Charakter")); + this.add(new NavButton(0, 40, 180, 0, GuiCharacters.INSTANCE, "Charakter")).enabled = !(this.gm.player instanceof EntityCameraHolder); this.add(new ActButton(0, this.gm.charEditor ? 50 : 70, 180, 0, new ButtonCallback() { public void use(ActButton elem, PressType action) { GuiMenu.this.gm.unload(true); diff --git a/client/src/main/java/client/init/RenderRegistry.java b/client/src/main/java/client/init/RenderRegistry.java index bbf175d9..a3b14554 100644 --- a/client/src/main/java/client/init/RenderRegistry.java +++ b/client/src/main/java/client/init/RenderRegistry.java @@ -9,6 +9,7 @@ import client.renderer.entity.RenderBat; import client.renderer.entity.RenderBlockEntity; import client.renderer.entity.RenderBoat; import client.renderer.entity.RenderBullet; +import client.renderer.entity.RenderCamera; import client.renderer.entity.RenderChicken; import client.renderer.entity.RenderCow; import client.renderer.entity.RenderCrystal; @@ -85,6 +86,7 @@ import common.entity.item.EntityOrb; import common.entity.item.EntityTnt; import common.entity.item.EntityTntCart; import common.entity.item.EntityXp; +import common.entity.npc.EntityCameraHolder; import common.entity.npc.SpeciesInfo; import common.entity.projectile.EntityArrow; import common.entity.projectile.EntityBox; @@ -150,6 +152,7 @@ public abstract class RenderRegistry { models.put(ModelType.DWARF, new RenderHumanoid(mgr, 10, 10, "textures/npc/dwarf.png")); models.put(ModelType.HALFLING, new RenderHumanoid(mgr, 8, 8, "textures/npc/goblin.png")); models.put(ModelType.SPACE_MARINE, new RenderSpaceMarine(mgr)); + map.put(EntityCameraHolder.class, new RenderCamera(mgr)); for(int z = 0; z < SpeciesRegistry.SPECIMEN.size(); z++) { SpeciesInfo info = SpeciesRegistry.SPECIMEN.get(z); map.put(info.clazz, models.get(info.renderer)); diff --git a/client/src/main/java/client/renderer/Renderer.java b/client/src/main/java/client/renderer/Renderer.java index fe11a8e5..7c731514 100755 --- a/client/src/main/java/client/renderer/Renderer.java +++ b/client/src/main/java/client/renderer/Renderer.java @@ -48,6 +48,7 @@ import common.collect.Sets; import common.dimension.DimType; import common.effect.Effect; import common.entity.Entity; +import common.entity.npc.EntityCameraHolder; import common.entity.npc.EntityNPC; import common.entity.types.EntityAnimal; import common.entity.types.EntityLiving; @@ -1280,7 +1281,7 @@ public class Renderer { this.renderCloudsCheck(partialTicks); } - if (entity == this.gm.player) + if (entity == this.gm.player && !(this.gm.player instanceof EntityCameraHolder)) { GL11.glClear(256); this.renderHand(partialTicks); diff --git a/client/src/main/java/client/renderer/entity/RenderCamera.java b/client/src/main/java/client/renderer/entity/RenderCamera.java new file mode 100644 index 00000000..4c5b018b --- /dev/null +++ b/client/src/main/java/client/renderer/entity/RenderCamera.java @@ -0,0 +1,22 @@ +package client.renderer.entity; + +import common.entity.npc.EntityNPC; + +public class RenderCamera extends RenderNpc { + public RenderCamera(RenderManager renderManagerIn) { + super(renderManagerIn, null); + } + + public void doRender(EntityNPC entity, double x, double y, double z, float partialTicks) { + } + + public String getDefaultTexture() { + return null; + } + + public void getSegments(TexList opaque, TexList alpha) { + } + + public void getHeadUVs(CoordList list) { + } +} diff --git a/common/src/main/java/common/ai/EntityAITarget.java b/common/src/main/java/common/ai/EntityAITarget.java index fae31b06..77990577 100755 --- a/common/src/main/java/common/ai/EntityAITarget.java +++ b/common/src/main/java/common/ai/EntityAITarget.java @@ -1,5 +1,6 @@ package common.ai; +import common.entity.npc.EntityCameraHolder; import common.entity.types.EntityLiving; import common.entity.types.IEntityOwnable; import common.pathfinding.PathEntity; @@ -139,7 +140,7 @@ public abstract class EntityAITarget extends EntityAIBase { return false; } - else if (!target.isEntityAlive()) + else if (!target.isEntityAlive() || target instanceof EntityCameraHolder) { return false; } diff --git a/common/src/main/java/common/entity/npc/EntityCameraHolder.java b/common/src/main/java/common/entity/npc/EntityCameraHolder.java new file mode 100755 index 00000000..ee1f13fd --- /dev/null +++ b/common/src/main/java/common/entity/npc/EntityCameraHolder.java @@ -0,0 +1,44 @@ +package common.entity.npc; + +import common.entity.DamageSource; +import common.rng.Random; +import common.world.World; + +public class EntityCameraHolder extends EntityNPC { + public EntityCameraHolder(World worldIn) { + super(worldIn); + } + + public int getBaseHealth(Random rand) { + return 1; + } + + public Alignment getNaturalAlign() { + return Alignment.NEUTRAL; + } + + public float getSpeciesBaseSize() { + return 0.1f; + } + + public boolean isVisibleTo(EntityNPC player) { + return false; + } + + public Object onInitialSpawn(Object livingdata) { + this.setCustomNameTag("Kamera"); + this.setHeight(0.1f); + return livingdata; + } + + public boolean canBeCollidedWith() { + return false; + } + + public float getEyeHeight() { + return 0.0F; + } + + protected void damageEntity(DamageSource damageSrc, int damageAmount) { + } +} diff --git a/common/src/main/java/common/entity/npc/EntityCpu.java b/common/src/main/java/common/entity/npc/EntityCpu.java deleted file mode 100755 index e9aaa3ab..00000000 --- a/common/src/main/java/common/entity/npc/EntityCpu.java +++ /dev/null @@ -1,64 +0,0 @@ -package common.entity.npc; - -import common.init.Items; -import common.item.ItemStack; -import common.rng.Random; -import common.world.World; - -public class EntityCpu extends EntityNPC { - public EntityCpu(World worldIn) { - super(worldIn); - } - -// public boolean isAggressive() { -// return false; -// } -// -// public boolean isPeaceful() { -// return false; -// } - -// public boolean isAggressive(Class clazz) { -// return false; -// } - -// public boolean isPeaceful(Class clazz) { -// return false; -// } - -// public boolean canInfight(Alignment align) { -// return false; -// } -// -// public boolean canMurder(Alignment align) { -// return false; -// } - - public boolean canUseMagic() { - return true; - } - -// public int getBaseEnergy(Random rand) { -// return Integer.MAX_VALUE; -// } - - public int getBaseHealth(Random rand) { - return 1024; - } - -// public float getHeightDeviation(Random rand) { -// return 0.0f; -// } - - public Alignment getNaturalAlign() { - return Alignment.NEUTRAL; - } - - public boolean isBreedingItem(ItemStack stack) { - return stack.getItem() == Items.nieh_fragment; - } - - public float getSpeciesBaseSize() { - return 1.8f; - } -} diff --git a/common/src/main/java/common/entity/npc/EntityMage.java b/common/src/main/java/common/entity/npc/EntityMage.java index 3486df4a..40cc4609 100755 --- a/common/src/main/java/common/entity/npc/EntityMage.java +++ b/common/src/main/java/common/entity/npc/EntityMage.java @@ -27,7 +27,7 @@ public class EntityMage extends EntityNPC public void onLivingUpdate() { - if (!this.worldObj.client && !this.isPlayer()) + if (!this.worldObj.client && !this.isPlayer() && !this.dummy) { if (this.drinking) { diff --git a/common/src/main/java/common/entity/npc/EntityNPC.java b/common/src/main/java/common/entity/npc/EntityNPC.java index 9906e56d..722bc603 100755 --- a/common/src/main/java/common/entity/npc/EntityNPC.java +++ b/common/src/main/java/common/entity/npc/EntityNPC.java @@ -215,6 +215,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory public IPlayer connection; public IClientPlayer client; protected boolean slave; + protected boolean dummy; protected InventoryWarpChest warpChest; public ContainerPlayer inventoryContainer; @@ -436,6 +437,11 @@ public abstract class EntityNPC extends EntityLiving implements IInventory this.renderDistWeight = 10.0D; } + public final void setPlayerDummy(TagObject tag) { + this.dummy = true; + this.readTags(tag); + } + public final boolean isPlayer() { return this.connection != null || this.slave; } @@ -2487,7 +2493,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory public ItemStack getHeldItem() { - return this.isPlayer() ? (this.getSelectedIndex() < 9 && this.getSelectedIndex() >= 0 ? this.getStackInSlot(this.getSelectedIndex()) : null) : this.heldItem; + return this.isPlayer() || this.dummy ? (this.getSelectedIndex() < 9 && this.getSelectedIndex() >= 0 ? this.getStackInSlot(this.getSelectedIndex()) : null) : this.heldItem; } public ItemStack[] getArmor() @@ -2507,7 +2513,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory public void setHeldItem(ItemStack stack) { - if(this.isPlayer()) { + if(this.isPlayer() || this.dummy) { this.setInventorySlotContents(this.getSelectedIndex(), stack); } else { @@ -3340,7 +3346,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory // this.setCanPickUpLoot(true); this.setCombatTask(); - if(this.isPlayer()) { + if(this.isPlayer() || this.dummy) { // this.entityUniqueID = getOfflineUUID(this.user); // this.sleeping = tagCompund.getBoolean("Sleeping"); // this.sleepTimer = tagCompund.getShort("SleepTimer"); @@ -3459,7 +3465,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory if(this.skin != null) tag.setByteArray("Skin", this.skin); - if(this.isPlayer()) { + if(this.isPlayer() || this.dummy) { // tagCompound.setBoolean("Sleeping", this.sleeping); // tagCompound.setShort("SleepTimer", (short)this.sleepTimer); tag.setFloat("XpP", this.experience); @@ -3511,7 +3517,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory protected void damageArmor(int damage) { - if(this.isPlayer()) { + if(this.isPlayer() || this.dummy) { damage = damage / 4; if (damage < 1) damage = 1; @@ -4027,7 +4033,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory */ protected int getExperiencePoints(EntityNPC player) { - return this.isPlayer() ? 0 : this.worldObj.rand.range(2, 5); + return this.isPlayer() || this.dummy ? 0 : this.worldObj.rand.range(2, 5); } /** @@ -4168,7 +4174,8 @@ public abstract class EntityNPC extends EntityLiving implements IInventory protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier) { if(!this.isPlayer()) { - super.dropFewItems(wasRecentlyHit, lootingModifier); + if(!this.dummy) + super.dropFewItems(wasRecentlyHit, lootingModifier); this.dropEquipment(); } } @@ -4304,7 +4311,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory } public boolean getCanSpawnHere() { - return this.isPlayer() || super.getCanSpawnHere(); + return this.isPlayer() || this.dummy || super.getCanSpawnHere(); } // npc overrides @@ -4321,7 +4328,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory if(this.isPlayer()) return; ItemStack itemstack1 = this.getHeldItem(); - if (itemstack1 != null) + if (itemstack1 != null && !this.dummy) { this.entityDropItem(itemstack1, 0.0F); } @@ -4429,7 +4436,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory } protected boolean canRegenerateHealth() { - return this.isPlayer(); + return this.isPlayer() || this.dummy; } // END PLAYER diff --git a/common/src/main/java/common/init/EntityRegistry.java b/common/src/main/java/common/init/EntityRegistry.java index b30a7004..94aa08d7 100755 --- a/common/src/main/java/common/init/EntityRegistry.java +++ b/common/src/main/java/common/init/EntityRegistry.java @@ -29,6 +29,7 @@ import common.entity.item.EntityOrb; import common.entity.item.EntityTnt; import common.entity.item.EntityTntCart; import common.entity.item.EntityXp; +import common.entity.npc.EntityCameraHolder; import common.entity.npc.SpeciesInfo; import common.entity.projectile.EntityArrow; import common.entity.projectile.EntityBox; @@ -260,6 +261,7 @@ public abstract class EntityRegistry { registerEntity("Bullet", EntityBullet.class, "Kugel"); registerEggs(); + registerEntity("Camera", EntityCameraHolder.class, "Kamera"); for(ItemMobTemplate item : ItemMobTemplate.TEMPLATES) { item.delegateSetDisplay(); diff --git a/common/src/main/java/common/init/SpeciesRegistry.java b/common/src/main/java/common/init/SpeciesRegistry.java index 61371a6d..2f4004a8 100755 --- a/common/src/main/java/common/init/SpeciesRegistry.java +++ b/common/src/main/java/common/init/SpeciesRegistry.java @@ -7,7 +7,7 @@ import common.collect.Maps; import common.entity.npc.EntityArachnoid; import common.entity.npc.EntityBloodElf; import common.entity.npc.EntityChaosMarine; -import common.entity.npc.EntityCpu; +import common.entity.npc.EntityCameraHolder; import common.entity.npc.EntityCultivator; import common.entity.npc.EntityDarkMage; import common.entity.npc.EntityDwarf; @@ -36,6 +36,7 @@ import common.entity.npc.SpeciesInfo; public abstract class SpeciesRegistry { public static enum ModelType { + CAMERA("camera", 0.1f, 0.1f, 16, 16, "Kamera"), HUMANOID("humanoid", 0.6f, 1.8f, 64, 64, "Humanoid"), ARACHNOID("arachnoid", 1.4f, 1.6f, 128, 64, "Arachnoidea"), SLIME("slime", 1.0f, 1.0f, 64, 32, "Schleim"), @@ -86,7 +87,7 @@ public abstract class SpeciesRegistry { } static void register() { - registerSpecies("Cpu", EntityCpu.class, null, "Test-NSC", 0x202020, 0x8000ff, "Troll:trollface", "Hacker"); + new SpeciesInfo("Camera", EntityCameraHolder.class, null, false, null, "Kamera", ModelType.CAMERA, 0x202020, 0x8000ff); registerSpecies("Cultivator", EntityCultivator.class, "nienrath", "Kultivator", 0x000000, 0xff0000, "Wei Wuxian", 0x000000, 0xff0000, "Lan Wangji", 0xffffff, 0x80e0ff, "Jiang Cheng", 0x200000, 0xaf00ff, "Shen Qingqiu", 0xffffff, 0x80ff80, "Luo Binghe", 0x600000, 0x000000); diff --git a/server/src/main/java/server/command/commands/CommandCamera.java b/server/src/main/java/server/command/commands/CommandCamera.java index 2e686d3d..3d6b3520 100644 --- a/server/src/main/java/server/command/commands/CommandCamera.java +++ b/server/src/main/java/server/command/commands/CommandCamera.java @@ -28,6 +28,6 @@ public class CommandCamera extends Command { } public void exec(CommandEnvironment env, Executor exec, Vec3 position, Dimension dim, double yaw, double pitch, int radius, double speed, CameraType type, boolean fixed, Player player) { - player.setCamera(position.xCoord, position.yCoord, position.zCoord, (float)yaw, (float)pitch, radius, (float)speed, type, fixed); + player.setCamera(dim, position.xCoord, position.yCoord, position.zCoord, (float)yaw, (float)pitch, radius, (float)speed, type, fixed); } } diff --git a/server/src/main/java/server/command/commands/CommandNocam.java b/server/src/main/java/server/command/commands/CommandNocam.java index 635e282f..392fe224 100644 --- a/server/src/main/java/server/command/commands/CommandNocam.java +++ b/server/src/main/java/server/command/commands/CommandNocam.java @@ -14,6 +14,6 @@ public class CommandNocam extends Command { } public void exec(CommandEnvironment env, Executor exec, Player player) { - player.removeCamera(); + player.unsetCamera(); } } diff --git a/server/src/main/java/server/network/Player.java b/server/src/main/java/server/network/Player.java index fa50a8d4..d3abbf02 100755 --- a/server/src/main/java/server/network/Player.java +++ b/server/src/main/java/server/network/Player.java @@ -24,6 +24,7 @@ import common.entity.item.EntityCamera.CameraType; import common.entity.item.EntityItem; import common.entity.item.EntityXp; import common.entity.npc.Alignment; +import common.entity.npc.EntityCameraHolder; import common.entity.npc.EntityHuman; import common.entity.npc.EntityNPC; import common.entity.npc.PlayerCharacter; @@ -164,6 +165,7 @@ public class Player extends User implements Executor, IPlayer private int lastMoved; private int pingKey; private int selected = -1; + private int lastSelected = -1; private long lastPingTime = System.nanoTime() / 1000000L; private int lastSentPingPacket; private double lastPosX; @@ -217,6 +219,8 @@ public class Player extends User implements Executor, IPlayer private Executor forcedExec; private Position deathPos; private Position teleportPos; + private Position lastDeathPos; + private Position lastTeleportPos; private EntityCamera camera; public Player(Server server, NetConnection connection, String user) @@ -359,16 +363,39 @@ public class Player extends User implements Executor, IPlayer - public void setCamera(double x, double y, double z, float yaw, float pitch, int radius, float speed, CameraType type, boolean fixed) { + public boolean setCamera(Dimension dim, double x, double y, double z, float yaw, float pitch, int radius, float speed, CameraType type, boolean fixed) { + if(this.charEditor || this.characters.isEmpty() || this.selected < 0 || this.lastSelected >= 0) + return false; + this.lastDeathPos = this.deathPos; + this.lastTeleportPos = this.teleportPos; + String name = this.entity.getCustomNameTag(); + TagObject tag = this.server.swapPlayer(this, null, EntityCameraHolder.class); + this.characters.set(this.selected, tag); + this.lastSelected = this.selected; + this.selected = this.characters.size(); + this.characters.add(new TagObject()); + WorldServer world = this.server.getWorld(dim); + world = world == null ? this.server.getSpace() : world; + this.entity.teleport(x, y, z, yaw, pitch, world); + this.entity.setNoclip(true); + this.entity.setCustomNameTag("Kamera von " + name); + this.teleportPos = this.deathPos = null; this.camera = new EntityCamera(this.entity.worldObj, x, y, z, yaw, pitch, radius, speed, type, fixed); this.sendPacket(new SPacketCamera(this.camera)); + return true; } - - public void removeCamera() { - if(this.camera != null) { - this.camera = null; - this.sendPacket(new SPacketCamera(null)); - } + + public boolean unsetCamera() { + if(this.charEditor || this.lastSelected >= this.characters.size() || this.lastSelected < 0) + return false; + this.server.swapPlayer(this, this.characters.get(this.selected = this.lastSelected), null); + this.characters.removeLast(); + this.lastSelected = -1; + this.deathPos = this.lastDeathPos; + this.teleportPos = this.lastTeleportPos; + this.camera = null; + this.sendPacket(new SPacketCamera(null)); + return true; } @@ -626,11 +653,13 @@ public class Player extends User implements Executor, IPlayer public void writeTags(TagObject tag) { if(!this.characters.isEmpty()) { - tag.setInt("selected", this.selected); + tag.setInt("selected", this.lastSelected >= 0 ? this.lastSelected : this.selected); List list = Lists.newArrayList(); for(TagObject etag : this.characters) { list.add(etag); } + if(this.lastSelected >= 0) + list.removeLast(); tag.setList("characters", list); } } @@ -653,14 +682,17 @@ public class Player extends User implements Executor, IPlayer public void travelToDimension(Dimension dimensionId, BlockPos pos, float yaw, float pitch, PortalType portal) { + if(this.camera != null) + return; this.server.transferToDimension(this.entity, dimensionId, pos, yaw, pitch, portal); this.lastExperience = -1; this.lastHealth = -1.0F; } public void teleport(double x, double y, double z, float yaw, float pitch, Dimension dimension) { + if(this.camera != null) + this.unsetCamera(); this.teleportPos = this.entity.getPos(); - this.removeCamera(); x = ExtMath.clampd(x, -World.MAX_SIZE + 1, World.MAX_SIZE - 1); z = ExtMath.clampd(z, -World.MAX_SIZE + 1, World.MAX_SIZE - 1); // this.setLastTeleport(this.getLocation()); @@ -2036,8 +2068,14 @@ public class Player extends User implements Executor, IPlayer if(this.camera != null) { this.camera.setPositionClamped(packetIn.getPositionX(), packetIn.getPositionY(), packetIn.getPositionZ()); this.camera.setRotationClamped(packetIn.getYaw(), packetIn.getPitch()); - if(!this.camera.fixed && packetIn.isOnGround()) - this.removeCamera(); + if(!this.camera.fixed && packetIn.isOnGround()) { + this.unsetCamera(); + } + else { + this.setPlayerLocation(this.camera.posX, this.camera.posY, this.camera.posZ, this.camera.rotYaw, this.camera.rotPitch); + this.entity.setRotationYawHead(this.camera.rotYaw); + this.getEntityWorld().updateMountedMovingPlayer(this.entity); + } } return; } @@ -2274,7 +2312,7 @@ public class Player extends User implements Executor, IPlayer public void processBreak(CPacketBreak packetIn) { NetHandler.checkThread(packetIn, this, this.server); - if(this.charEditor) + if(this.charEditor || this.entity instanceof EntityCameraHolder) return; WorldServer worldserver = this.getEntityWorld(); // this.serverController.getWorld(this.playerEntity.dimension); BlockPos blockpos = packetIn.getPosition(); @@ -2360,7 +2398,7 @@ public class Player extends User implements Executor, IPlayer public void processPlace(CPacketPlace packetIn) { NetHandler.checkThread(packetIn, this, this.server); - if(this.charEditor) + if(this.charEditor || this.entity instanceof EntityCameraHolder) return; WorldServer worldserver = this.getEntityWorld(); // this.serverController.getWorld(this.playerEntity.dimension); ItemStack itemstack = this.entity.getHeldItem(); @@ -2466,7 +2504,7 @@ public class Player extends User implements Executor, IPlayer NetHandler.checkThread(packetIn, this, this.server); CPacketAction.Action action = packetIn.getAction(); - if(this.charEditor != (action == Action.SET_ALIGN || action == Action.SET_SPECIES || action == Action.SET_CLASS || action == Action.SET_HEIGHT || action == Action.CLOSE_EDITOR || action == Action.CANCEL_EDITOR)) // { + if((this.charEditor != (action == Action.SET_ALIGN || action == Action.SET_SPECIES || action == Action.SET_CLASS || action == Action.SET_HEIGHT || action == Action.CLOSE_EDITOR || action == Action.CANCEL_EDITOR)) || (this.entity instanceof EntityCameraHolder && action != Action.WARP_MODE && action != Action.PERF && action != Action.START_PROFILING && action != Action.STOP_PROFILING)) // { // if(this.local && action == Action.CLOSE_EDITOR) // this.server.setDone(); return; @@ -2484,7 +2522,6 @@ public class Player extends User implements Executor, IPlayer int last = this.selected; this.selected = -1; this.teleportPos = this.deathPos = null; - this.removeCamera(); this.sendPacket(!this.characters.isEmpty() && last >= 0 ? new SPacketCharacterList(this.selected, last, this.getCharacterInfo(tag)) : new SPacketCharacterList(this.selected)); break; } @@ -2500,7 +2537,6 @@ public class Player extends User implements Executor, IPlayer Position pos = this.server.getRandomSpawnPosition(origin); this.entity.teleport(pos); this.teleportPos = this.deathPos = null; - this.removeCamera(); this.sendPacket(new SPacketCharacterList(this.selected, this.selected, new PlayerCharacter(this.entity.getCustomNameTag(), this.entity.getDescription(), this.entity.getAlignment(), this.entity.worldObj.dimension.getDisplay(), this.entity.getPosition(), EntityRegistry.getEntityName(EntityRegistry.getEntityString(this.entity)), this.entity.experienceLevel, world.dimension == Space.INSTANCE ? null : world.dimension.getDisplay()))); // if(this.local) // this.server.setDone(); @@ -2515,7 +2551,6 @@ public class Player extends User implements Executor, IPlayer this.server.swapPlayer(this, this.characters.get(index), null); this.selected = index; this.teleportPos = this.deathPos = null; - this.removeCamera(); this.sendPacket(new SPacketCharacterList(this.selected)); break; } @@ -2530,7 +2565,6 @@ public class Player extends User implements Executor, IPlayer int last = this.selected; this.selected = index; this.teleportPos = this.deathPos = null; - this.removeCamera(); this.sendPacket(!this.characters.isEmpty() && last >= 0 ? new SPacketCharacterList(this.selected, last, this.getCharacterInfo(etag)) : new SPacketCharacterList(this.selected)); break; } @@ -2802,7 +2836,7 @@ public class Player extends User implements Executor, IPlayer case SET_SPECIES: Class clazz = EntityRegistry.getEntityClass(packetIn.getAuxData()); - if(EntityNPC.class.isAssignableFrom(clazz)) + if(EntityNPC.class.isAssignableFrom(clazz) && clazz != EntityCameraHolder.class) this.server.swapPlayer(this, null, (Class)clazz); // Log.CONSOLE.info("" + this.entity.height + "(" + this.entity.getHeight() + ")"); break; @@ -2867,7 +2901,7 @@ public class Player extends User implements Executor, IPlayer public void processClick(CPacketClick packetIn) { NetHandler.checkThread(packetIn, this, this.server); - if(this.charEditor) + if(this.charEditor || this.entity instanceof EntityCameraHolder) return; if (this.entity.openContainer.windowId == packetIn.getWindowId() && this.entity.openContainer.getCanCraft(this.entity)) @@ -2916,7 +2950,7 @@ public class Player extends User implements Executor, IPlayer public void processCheat(CPacketCheat packet) { NetHandler.checkThread(packet, this, this.server); - if(this.charEditor || !this.isAdmin()) + if(this.charEditor || !this.isAdmin() || this.entity instanceof EntityCameraHolder) return; Item item = packet.getItem(); if(item == null) @@ -2978,7 +3012,7 @@ public class Player extends User implements Executor, IPlayer public void processSign(CPacketSign packetIn) { NetHandler.checkThread(packetIn, this, this.server); - if(this.charEditor) + if(this.charEditor || this.entity instanceof EntityCameraHolder) return; WorldServer worldserver = this.getEntityWorld(); // this.serverController.getWorld(this.playerEntity.dimension);