Solved Changing player dimension to the nether

Discussion in 'Plugin Development' started by SaxSalute, May 23, 2015.

Thread Status:
Not open for further replies.
  1. Offline

    SaxSalute

    I'm working on something where I need to be able to make a player have the nether skybox in an overworld location. I know for a fact that it's possible, at least in 1.7, but the 1.7 code doesn't translate to 1.8 directly. I've been working on reverse engineering this from a decompiled server jar, and this is what I have. It works if called in the PlayerJoinEvent, but at any other point it will cause the player to only see red, as in none of the blocks will be rendered, though the outlines are shown. There's probably quite a bit of fluff, but it's definitely a work in progress. Anybody have an idea?

    Code:
            int netherId = -1;
          
            Location l = p.getLocation();
            final double oX = l.getX(), oY = l.getY(), oZ = l.getZ();
            final float oYaw = l.getYaw(), oPitch = l.getPitch();
    
            CraftPlayer cp = (CraftPlayer) p;
            EntityPlayer ep = cp.getHandle();
            WorldServer ws = ((CraftWorld) p.getWorld()).getHandle();
    
            if (cp.getWorld().getEnvironment().getId() == netherId) {
                ep.playerConnection.sendPacket(new PacketPlayOutRespawn((byte)(cp.getWorld().getEnvironment().getId() >= 0 ? -1 : 0), ws.getDifficulty(), ws.getWorldData().getType(), ep.playerInteractManager.getGameMode()));
            }
            ep.playerConnection.sendPacket(new PacketPlayOutRespawn(netherId, ws.getDifficulty(), ws.getWorldData().getType(), ep.playerInteractManager.getGameMode()));
            ep.spawnIn(ws);
            ep.dead = false;
            ep.playerConnection.teleport(new Location(ws.getWorld(), ep.locX, ep.locY, ep.locZ, ep.yaw, ep.pitch));
            ep.setSneaking(false);
    
            //Fiddle?
            BlockPosition blockposition1 = ws.getSpawn();
    
            ep.playerConnection.sendPacket(new PacketPlayOutSpawnPosition(blockposition1));
            ep.playerConnection.sendPacket(new PacketPlayOutExperience(ep.exp, ep.expTotal, ep.expLevel));
    
            ep.updateInventory(ep.defaultContainer);
    
            ep.getBukkitEntity().updateScaledHealth();
            ep.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(ep.inventory.itemInHandIndex));
    
            cp.getHandle().playerConnection.sendPacket(new PacketPlayOutPosition(oX, oY, oZ, oYaw, oPitch, new HashSet<EnumPlayerTeleportFlags>()));
     
  2. Offline

    RingOfStorms

  3. Offline

    SaxSalute

  4. Offline

    RingOfStorms

    All I did was give you the method to show the blocks to the player, if you can't update NMS code yourself you shouldn't be using it, I'm not going to re-write the entire method for you in a new version (which really only requires updating imports).
     
  5. Offline

    SaxSalute

    No need to be so condescending about it. I know what you gave me, and I know that in theory it should only require updating imports to change versions. However, exact behavior changes slightly between versions, which is why I'm in the process of figuring this out again. The old version with updated imports no longer works.

    After some more investigation, I came up a solution. By decompiling the server jar and pulling out parts of the teleport method, I have come up with this completely functional solution. Some of it may be unnecessary in its new role, but is left in from the original teleport just to be safe.

    Code:
        public static void dupeNether(Player p) {
            CraftPlayer cp = (CraftPlayer) p;
            EntityPlayer entity = cp.getHandle();
    
            if ((cp.getHealth() == 0.0D) || (entity.dead) ||
                    (entity.playerConnection == null) || (entity.playerConnection.isDisconnected()) ||
                    entity.passenger != null) {
                return;
            }
    
            Location location = p.getLocation();
    
            WorldServer toWorld = ((CraftWorld)location.getWorld()).getHandle();
            if (entity.activeContainer != entity.defaultContainer) {
                entity.closeInventory();
            }
           
            //This is where the new method started
            boolean flag = true, avoidSuffocation = true;
            int i = toWorld.dimension;
           
            EntityPlayer entityplayer = cp.getHandle();
            CraftServer cserver = (CraftServer) cp.getServer();
            PlayerList fakeThis = (cserver).getHandle();
    
            entityplayer.u().getTracker().untrackPlayer(entityplayer);
    
            entityplayer.u().getPlayerChunkMap().removePlayer(entityplayer);
            fakeThis.players.remove(entityplayer);
            fakeThis.getServer().getWorldServer(entityplayer.dimension).removeEntity(entityplayer);
    
            EntityPlayer entityplayer1 = entityplayer;
            org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld();
            entityplayer.viewingCredits = false;
    
            entityplayer1.playerConnection = entityplayer.playerConnection;
            entityplayer1.copyTo(entityplayer, flag);
            entityplayer1.d(entityplayer.getId());
            entityplayer1.o(entityplayer);
    
            location.setWorld(fakeThis.getServer().getWorldServer(i).getWorld());
    
            WorldServer worldserver = ((CraftWorld)location.getWorld()).getHandle();
            entityplayer1.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
    
            worldserver.chunkProviderServer.getChunkAt((int)entityplayer1.locX >> 4, (int)entityplayer1.locZ >> 4);
            while ((avoidSuffocation) && (!worldserver.getCubes(entityplayer1, entityplayer1.getBoundingBox()).isEmpty()) && (entityplayer1.locY < 256.0D)) {
                entityplayer1.setPosition(entityplayer1.locX, entityplayer1.locY + 1.0D, entityplayer1.locZ);
            }
    
            byte actualDimension = -1;
    
            if (fromWorld.getEnvironment() == worldserver.getWorld().getEnvironment()) {
                entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn((byte)(actualDimension >= 0 ? -1 : 0), worldserver.getDifficulty(), worldserver.getWorldData().getType(), entityplayer.playerInteractManager.getGameMode()));
            }
            entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(actualDimension, worldserver.getDifficulty(), worldserver.getWorldData().getType(), entityplayer1.playerInteractManager.getGameMode()));
            entityplayer1.spawnIn(worldserver);
            entityplayer1.dead = false;
            entityplayer1.playerConnection.teleport(new Location(worldserver.getWorld(), entityplayer1.locX, entityplayer1.locY, entityplayer1.locZ, entityplayer1.yaw, entityplayer1.pitch));
            entityplayer1.setSneaking(false);
    
            entityplayer1.playerConnection.sendPacket(new PacketPlayOutExperience(entityplayer1.exp, entityplayer1.expTotal, entityplayer1.expLevel));
    
            WorldBorder worldborder = entityplayer.world.getWorldBorder();
    
            entityplayer.playerConnection.sendPacket(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE));
            entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateTime(worldserver.getTime(), worldserver.getDayTime(), worldserver.getGameRules().getBoolean("doDaylightCycle")));
    
            if (!entityplayer.playerConnection.isDisconnected())
            {
                worldserver.getPlayerChunkMap().addPlayer(entityplayer1);
                worldserver.addEntity(entityplayer1);
                fakeThis.players.add(entityplayer1);
            }
    
            entityplayer.updateInventory(entityplayer.defaultContainer);
            entityplayer.getBukkitEntity().updateScaledHealth();
            entityplayer.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex));
    
            entityplayer.updateAbilities();
    
            entityplayer1.setHealth(entityplayer1.getHealth());
        }
    <Edit by mrCookieSlime: Merged posts. Please don't double post. There is an Edit Button right next to the Date.>
     
    Last edited by a moderator: May 26, 2015
Thread Status:
Not open for further replies.

Share This Page