SHARE
TWEET

1_13_R2 WorldHandler

a guest Oct 15th, 2019 69 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package net.countercraft.movecraft.compat.v1_13_R2;
  2.  
  3. import net.countercraft.movecraft.MovecraftLocation;
  4. import net.countercraft.movecraft.Rotation;
  5. import net.countercraft.movecraft.WorldHandler;
  6. import net.countercraft.movecraft.config.Settings;
  7. import net.countercraft.movecraft.craft.Craft;
  8. import net.countercraft.movecraft.utils.CollectionUtils;
  9. import net.countercraft.movecraft.utils.MathUtils;
  10. import net.minecraft.server.v1_13_R2.*;
  11. import org.bukkit.Bukkit;
  12. import org.bukkit.Location;
  13. import org.bukkit.Material;
  14. import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer;
  15. import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
  16. import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlockState;
  17. import org.bukkit.craftbukkit.v1_13_R2.util.CraftMagicNumbers;
  18. import org.bukkit.entity.Player;
  19. import org.bukkit.event.player.PlayerMoveEvent;
  20. import org.jetbrains.annotations.NotNull;
  21. import org.jetbrains.annotations.Nullable;
  22.  
  23. import java.lang.invoke.MethodHandle;
  24. import java.lang.invoke.MethodHandles;
  25. import java.lang.reflect.Field;
  26. import java.lang.reflect.Method;
  27. import java.util.*;
  28.  
  29. public class IWorldHandler extends WorldHandler{
  30.     private static final EnumBlockRotation ROTATION[];
  31.     static {
  32.         ROTATION = new EnumBlockRotation[3];
  33.         ROTATION[Rotation.NONE.ordinal()] = EnumBlockRotation.NONE;
  34.         ROTATION[Rotation.CLOCKWISE.ordinal()] = EnumBlockRotation.CLOCKWISE_90;
  35.         ROTATION[Rotation.ANTICLOCKWISE.ordinal()] = EnumBlockRotation.COUNTERCLOCKWISE_90;
  36.     }
  37.     private final NextTickProvider tickProvider = new NextTickProvider();
  38.     private final HashMap<World,List<TileEntity>> bMap = new HashMap<>();
  39.     private MethodHandle internalTeleportMH;
  40.  
  41.     public IWorldHandler() {
  42.         MethodHandles.Lookup lookup = MethodHandles.lookup();
  43.         Method teleport = null;
  44.         try {
  45.             teleport = PlayerConnection.class.getDeclaredMethod("internalTeleport", double.class, double.class, double.class, float.class, float.class, Set.class);
  46.             teleport.setAccessible(true);
  47.             internalTeleportMH = lookup.unreflect(teleport);
  48.  
  49.         } catch (NoSuchMethodException | IllegalAccessException e) {
  50.             e.printStackTrace();
  51.         }
  52.     }
  53.  
  54.     @Override
  55.     public void rotateCraft(@NotNull Craft craft, @NotNull MovecraftLocation originPoint, @NotNull Rotation rotation) {
  56.         //*******************************************
  57.         //*      Step one: Convert to Positions     *
  58.         //*******************************************
  59.         HashMap<BlockPosition,BlockPosition> rotatedPositions = new HashMap<>();
  60.         Rotation counterRotation = rotation == Rotation.CLOCKWISE ? Rotation.ANTICLOCKWISE : Rotation.CLOCKWISE;
  61.         for(MovecraftLocation newLocation : craft.getHitBox()){
  62.             rotatedPositions.put(locationToPosition(MathUtils.rotateVec(counterRotation, newLocation.subtract(originPoint)).add(originPoint)),locationToPosition(newLocation));
  63.         }
  64.         //*******************************************
  65.         //*         Step two: Get the tiles         *
  66.         //*******************************************
  67.         World nativeWorld = ((CraftWorld) craft.getW()).getHandle();
  68.         List<TileHolder> tiles = new ArrayList<>();
  69.         //get the tiles
  70.         for(BlockPosition position : rotatedPositions.keySet()){
  71.             //TileEntity tile = nativeWorld.removeTileEntity(position);
  72.             TileEntity tile = removeTileEntity(nativeWorld,position);
  73.             if(tile == null)
  74.                 continue;
  75.             tile.a(ROTATION[rotation.ordinal()]);
  76.             //get the nextTick to move with the tile
  77.             tiles.add(new TileHolder(tile, tickProvider.getNextTick((WorldServer)nativeWorld,position), position));
  78.         }
  79.  
  80.         //*******************************************
  81.         //*   Step three: Translate all the blocks  *
  82.         //*******************************************
  83.         // blockedByWater=false means an ocean-going vessel
  84.         //TODO: Simplify
  85.         //TODO: go by chunks
  86.         //TODO: Don't move unnecessary blocks
  87.         //get the blocks and rotate them
  88.         HashMap<BlockPosition,IBlockData> blockData = new HashMap<>();
  89.         for(BlockPosition position : rotatedPositions.keySet()){
  90.             blockData.put(position,nativeWorld.getType(position).a(ROTATION[rotation.ordinal()]));
  91.         }
  92.         //create the new block
  93.         for(Map.Entry<BlockPosition,IBlockData> entry : blockData.entrySet()) {
  94.             setBlockFast(nativeWorld, rotatedPositions.get(entry.getKey()), entry.getValue());
  95.         }
  96.  
  97.  
  98.         //*******************************************
  99.         //*    Step four: replace all the tiles     *
  100.         //*******************************************
  101.         //TODO: go by chunks
  102.         for(TileHolder tileHolder : tiles){
  103.             moveTileEntity(nativeWorld, rotatedPositions.get(tileHolder.getTilePosition()),tileHolder.getTile());
  104.             if(tileHolder.getNextTick()==null)
  105.                 continue;
  106.             final long currentTime = nativeWorld.worldData.getTime();
  107.             //nativeWorld.b(rotatedPositions.get(tileHolder.getNextTick().a), tileHolder.getNextTick().a(), (int) (tileHolder.getNextTick().b - currentTime), tileHolder.getNextTick().c);
  108.             //BlockPosition, Object, int, TickListPriority
  109.             nativeWorld.b(rotatedPositions.get(tileHolder.getNextTick().a), tileHolder.getTile());
  110.         }
  111.  
  112.         //*******************************************
  113.         //*   Step five: Destroy the leftovers      *
  114.         //*******************************************
  115.         //TODO: add support for pass-through
  116.         Collection<BlockPosition> deletePositions =  CollectionUtils.filter(rotatedPositions.keySet(),rotatedPositions.values());
  117.         for(BlockPosition position : deletePositions){
  118.             setBlockFast(nativeWorld, position, Blocks.AIR.getBlockData());
  119.         }
  120.  
  121.         //*******************************************
  122.         //*       Step six: Update the blocks       *
  123.         //*******************************************
  124.         for(BlockPosition newPosition : rotatedPositions.values()) {
  125.            // CraftBlockState.getBlockState(nativeWorld,newPosition.getX(), newPosition.getY(), newPosition.getZ()).update(false,false);
  126.             CraftBlockState.getBlockState(nativeWorld, newPosition, 3).update(false, false);
  127.         }
  128.         for(BlockPosition deletedPosition : deletePositions){
  129.            // CraftBlockState.getBlockState(nativeWorld,deletedPosition.getX(), deletedPosition.getY(), deletedPosition.getZ()).update(false,false);
  130.             CraftBlockState.getBlockState(nativeWorld, deletedPosition, 3).update(false, false);
  131.         }
  132.         //*******************************************
  133.         //*       Step seven: Send to players       *
  134.         //*******************************************
  135.         List<Chunk> chunks = new ArrayList<>();
  136.         for(BlockPosition position : rotatedPositions.values()){
  137.             Chunk chunk = nativeWorld.getChunkAtWorldCoords(position);
  138.             if(!chunks.contains(chunk)){
  139.                 chunks.add(chunk);
  140.             }
  141.         }
  142.         for(BlockPosition position : deletePositions){
  143.             Chunk chunk = nativeWorld.getChunkAtWorldCoords(position);
  144.             if(!chunks.contains(chunk)){
  145.                 chunks.add(chunk);
  146.             }
  147.         }
  148.     }
  149.  
  150.     @Override
  151.     public void translateCraft(@NotNull Craft craft, @NotNull MovecraftLocation displacement) {
  152.         //TODO: Add supourt for rotations
  153.         //A craftTranslateCommand should only occur if the craft is moving to a valid position
  154.         //*******************************************
  155.         //*      Step one: Convert to Positions     *
  156.         //*******************************************
  157.         BlockPosition translateVector = locationToPosition(displacement);
  158.         List<BlockPosition> positions = new ArrayList<>();
  159.         for(MovecraftLocation movecraftLocation : craft.getHitBox()) {
  160.             positions.add(locationToPosition((movecraftLocation)).b(translateVector));
  161.  
  162.         }
  163.         //*******************************************
  164.         //*         Step two: Get the tiles         *
  165.         //*******************************************
  166.         World nativeWorld = ((CraftWorld) craft.getW()).getHandle();
  167.         List<TileHolder> tiles = new ArrayList<>();
  168.         //get the tiles
  169.         for(BlockPosition position : positions){
  170.             if(nativeWorld.getType(position) == Blocks.AIR.getBlockData())
  171.                 continue;
  172.             //TileEntity tile = nativeWorld.removeTileEntity(position);
  173.             TileEntity tile = removeTileEntity(nativeWorld,position);
  174.             if(tile == null)
  175.                 continue;
  176.             //get the nextTick to move with the tile
  177.  
  178.             //nativeWorld.capturedTileEntities.remove(position);
  179.             //nativeWorld.getChunkAtWorldCoords(position).getTileEntities().remove(position);
  180.             tiles.add(new TileHolder(tile, tickProvider.getNextTick((WorldServer)nativeWorld,position), position));
  181.  
  182.         }
  183.         //*******************************************
  184.         //*   Step three: Translate all the blocks  *
  185.         //*******************************************
  186.         // blockedByWater=false means an ocean-going vessel
  187.         //TODO: Simplify
  188.         //TODO: go by chunks
  189.         //TODO: Don't move unnecessary blocks
  190.         //get the blocks
  191.         List<IBlockData> blockData = new ArrayList<>();
  192.         for(BlockPosition position : positions){
  193.             blockData.add(nativeWorld.getType(position));
  194.         }
  195.         //translate the positions
  196.         List<BlockPosition> newPositions = new ArrayList<>();
  197.         for(BlockPosition position : positions){
  198.             newPositions.add(position.a(translateVector));
  199.         }
  200.         //create the new block
  201.         for(int i = 0; i<newPositions.size(); i++) {
  202.             setBlockFast(nativeWorld, newPositions.get(i), blockData.get(i));
  203.         }
  204.         //*******************************************
  205.         //*    Step four: replace all the tiles     *
  206.         //*******************************************
  207.         //TODO: go by chunks
  208.         for(TileHolder tileHolder : tiles){
  209.             moveTileEntity(nativeWorld, tileHolder.getTilePosition().a(translateVector),tileHolder.getTile());
  210.             if(tileHolder.getNextTick()==null)
  211.                 continue;
  212.             final long currentTime = nativeWorld.worldData.getTime();
  213.             //nativeWorld.b(tileHolder.getNextTick().a.a(translateVector), tileHolder.getNextTick().a(), (int) (tileHolder.getNextTick().b - currentTime), tileHolder.getNextTick().c);
  214.             nativeWorld.b(tileHolder.getNextTick().a.a(translateVector), tileHolder.getTile());
  215.         }
  216.         //*******************************************
  217.         //*   Step five: Destroy the leftovers      *
  218.         //*******************************************
  219.         Collection<BlockPosition> deletePositions =  CollectionUtils.filter(positions,newPositions);
  220.         for(BlockPosition position : deletePositions){
  221.             setBlockFast(nativeWorld, position, Blocks.AIR.getBlockData());
  222.         }
  223.  
  224.         //*******************************************
  225.         //*       Step six: Update the blocks       *
  226.         //*******************************************
  227.         for(BlockPosition newPosition : newPositions) {
  228.             CraftBlockState.getBlockState(nativeWorld, newPosition, 3).update(false,false);
  229.         }
  230.         for(BlockPosition deletedPosition : deletePositions){
  231.             CraftBlockState.getBlockState(nativeWorld, deletedPosition, 3).update(false,false);
  232.         }
  233.         //*******************************************
  234.         //*       Step seven: Send to players       *
  235.         //*******************************************
  236.         List<Chunk> chunks = new ArrayList<>();
  237.         for(BlockPosition position : newPositions){
  238.             Chunk chunk = nativeWorld.getChunkAtWorldCoords(position);
  239.             if(!chunks.contains(chunk)){
  240.                 chunks.add(chunk);
  241.             }
  242.         }
  243.         for(BlockPosition position : deletePositions){
  244.             Chunk chunk = nativeWorld.getChunkAtWorldCoords(position);
  245.             if(!chunks.contains(chunk)){
  246.                 chunks.add(chunk);
  247.             }
  248.         }
  249.         //sendToPlayers(chunks.toArray(new Chunk[0]));
  250.     }
  251.  
  252.     @Override
  253.     public void addPlayerLocation(Player player, double x, double y, double z, float yaw, float pitch){
  254.         EntityPlayer ePlayer = ((CraftPlayer) player).getHandle();
  255.         if(internalTeleportMH == null) {
  256.             //something went wrong
  257.             super.addPlayerLocation(player, x, y, z, yaw, pitch);
  258.             return;
  259.         }
  260.         try {
  261.             final Location oldLoc = player.getLocation().clone();
  262.             final Location newLoc = player.getLocation().add(x,y,z);
  263.             internalTeleportMH.invoke(ePlayer.playerConnection, x + player.getLocation().getX(), y + player.getLocation().getY(), z + player.getLocation().getZ(), yaw, pitch, EnumSet.allOf(PacketPlayOutPosition.EnumPlayerTeleportFlags.class));
  264.             Bukkit.getServer().getPluginManager().callEvent(new PlayerMoveEvent(player,oldLoc,newLoc));
  265.         } catch (Throwable throwable) {
  266.             throwable.printStackTrace();
  267.         }
  268.     }
  269.  
  270.     @Nullable
  271.     private TileEntity removeTileEntity(@NotNull World world, @NotNull BlockPosition position){
  272.         TileEntity tile = world.getTileEntity(position);
  273.         if(tile == null)
  274.             return null;
  275.         //cleanup
  276.         world.capturedTileEntities.remove(position);
  277.         world.getChunkAtWorldCoords(position).getTileEntities().remove(position);
  278.         if(!Settings.IsPaper)
  279.             world.tileEntityList.remove(tile);
  280.         world.tileEntityListTick.remove(tile);
  281.         if(!bMap.containsKey(world)){
  282.             try {
  283.                 Field bField = World.class.getDeclaredField("c");
  284.                 bField.setAccessible(true);
  285.                 bMap.put(world, (List<TileEntity>) bField.get(world));//TODO bug fix
  286.             } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException e1) {
  287.                 e1.printStackTrace();
  288.             }
  289.         }
  290.         bMap.get(world).remove(tile);
  291.         return tile;
  292.     }
  293.  
  294.     @NotNull
  295.     private BlockPosition locationToPosition(@NotNull MovecraftLocation loc) {
  296.         return new BlockPosition(loc.getX(), loc.getY(), loc.getZ());
  297.     }
  298.  
  299.     private void setBlockFast(@NotNull World world, @NotNull BlockPosition position,@NotNull IBlockData data) {
  300.         Chunk chunk = world.getChunkAtWorldCoords(position);
  301.         ChunkSection chunkSection = chunk.getSections()[position.getY()>>4];
  302.         if (chunkSection == null) {
  303.             // Put a GLASS block to initialize the section. It will be replaced next with the real block.
  304.             chunk.setType(position, Blocks.GLASS.getBlockData(), true);
  305.             chunkSection = chunk.getSections()[position.getY() >> 4];
  306.  
  307.         }
  308.  
  309.         chunkSection.setType(position.getX()&15, position.getY()&15, position.getZ()&15, data);
  310.     }
  311.  
  312.     @Override
  313.     public void setBlockFast(@NotNull Location location, @NotNull Material material, byte data){
  314.         setBlockFast(location, Rotation.NONE, material, data);
  315.     }
  316.  
  317.     @Override
  318.     public void setBlockFast(@NotNull Location location, @NotNull Rotation rotation, @NotNull Material material, byte data) {
  319.         IBlockData blockData =  CraftMagicNumbers.getBlock(material).getBlockData();
  320.         blockData = blockData.a(ROTATION[rotation.ordinal()]);
  321.         World world = ((CraftWorld)(location.getWorld())).getHandle();
  322.         BlockPosition blockPosition = locationToPosition(bukkit2MovecraftLoc(location));
  323.         setBlockFast(world,blockPosition,blockData);
  324.     }
  325.  
  326.     @Override
  327.     public void disableShadow(@NotNull Material type) {
  328.         Method method;
  329.         //try {
  330.         Item item = CraftMagicNumbers.getItem(type);
  331.             //method = Block.class.getDeclaredMethod("d", int.class);
  332.             //method.setAccessible(true);
  333.             //method.invoke(tempBlock, 0);
  334.         //} catch (NoSuchMethodException | InvocationTargetException | IllegalArgumentException | IllegalAccessException | SecurityException e1) {
  335.             // TODO Auto-generated catch block
  336.         //    e1.printStackTrace();
  337.         //}
  338.     }
  339.  
  340.     private static MovecraftLocation bukkit2MovecraftLoc(Location l) {
  341.         return new MovecraftLocation(l.getBlockX(), l.getBlockY(), l.getBlockZ());
  342.     }
  343.  
  344.     private void moveTileEntity(@NotNull World nativeWorld, @NotNull BlockPosition newPosition, @NotNull TileEntity tile){
  345.         Chunk chunk = nativeWorld.getChunkAtWorldCoords(newPosition);
  346.         tile.invalidateBlockCache();
  347.         if(nativeWorld.captureBlockStates) {
  348.             tile.setWorld(nativeWorld);            
  349.             tile.setPosition(newPosition);
  350.             nativeWorld.capturedTileEntities.put(newPosition, tile);
  351.             return;
  352.         }
  353.         tile.setPosition(newPosition);
  354.         chunk.tileEntities.put(newPosition, tile);
  355.     }
  356.  
  357.     private class TileHolder{
  358.         @NotNull private final TileEntity tile;
  359.         @Nullable
  360.         private final NextTickListEntry nextTick;
  361.         @NotNull private final BlockPosition tilePosition;
  362.  
  363.         public TileHolder(@NotNull TileEntity tile, @Nullable NextTickListEntry nextTick, @NotNull BlockPosition tilePosition){
  364.             this.tile = tile;
  365.             this.nextTick = nextTick;
  366.             this.tilePosition = tilePosition;
  367.         }
  368.  
  369.  
  370.         @NotNull
  371.         public TileEntity getTile() {
  372.             return tile;
  373.         }
  374.  
  375.         @Nullable
  376.         public NextTickListEntry getNextTick() {
  377.             return nextTick;
  378.         }
  379.  
  380.         @NotNull
  381.         public BlockPosition getTilePosition() {
  382.             return tilePosition;
  383.         }
  384.     }
  385. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top