pick 97420a31d The big reformat of 2020
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
@@ -33,6 +32,9 @@ import net.minecraft.world.ITickList;
|
||||
import net.minecraft.world.NextTickListEntry;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerTickList;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.movable.IMovableHandler;
|
||||
@@ -42,425 +44,367 @@ import appeng.api.util.WorldCoord;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.worlddata.WorldData;
|
||||
import appeng.util.Platform;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerTickList;
|
||||
|
||||
|
||||
public class CachedPlane
|
||||
{
|
||||
private final int x_size;
|
||||
private final int z_size;
|
||||
private final int cx_size;
|
||||
private final int cz_size;
|
||||
private final int x_offset;
|
||||
private final int y_offset;
|
||||
private final int z_offset;
|
||||
private final int y_size;
|
||||
private final Chunk[][] myChunks;
|
||||
private final Column[][] myColumns;
|
||||
private final List<TileEntity> tiles = new ArrayList<>();
|
||||
private final List<NextTickListEntry<Block>> ticks = new ArrayList<>();
|
||||
private final World world;
|
||||
private final IMovableRegistry reg = AEApi.instance().registries().movable();
|
||||
private final List<WorldCoord> updates = new ArrayList<>();
|
||||
private int verticalBits;
|
||||
private final BlockState matrixBlockState;
|
||||
|
||||
public CachedPlane( final World w, final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ )
|
||||
{
|
||||
|
||||
Block matrixFrameBlock = AEApi.instance().definitions().blocks().matrixFrame().maybeBlock().orElse( null );
|
||||
if( matrixFrameBlock != null )
|
||||
{
|
||||
this.matrixBlockState = matrixFrameBlock.getDefaultState();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.matrixBlockState = null;
|
||||
}
|
||||
|
||||
this.world = w;
|
||||
|
||||
this.x_size = maxX - minX + 1;
|
||||
this.y_size = maxY - minY + 1;
|
||||
this.z_size = maxZ - minZ + 1;
|
||||
|
||||
this.x_offset = minX;
|
||||
this.y_offset = minY;
|
||||
this.z_offset = minZ;
|
||||
|
||||
final int minCX = minX >> 4;
|
||||
final int minCY = minY >> 4;
|
||||
final int minCZ = minZ >> 4;
|
||||
final int maxCX = maxX >> 4;
|
||||
final int maxCY = maxY >> 4;
|
||||
final int maxCZ = maxZ >> 4;
|
||||
|
||||
this.cx_size = maxCX - minCX + 1;
|
||||
final int cy_size = maxCY - minCY + 1;
|
||||
this.cz_size = maxCZ - minCZ + 1;
|
||||
|
||||
this.myChunks = new Chunk[this.cx_size][this.cz_size];
|
||||
this.myColumns = new Column[this.x_size][this.z_size];
|
||||
|
||||
this.verticalBits = 0;
|
||||
for( int cy = 0; cy < cy_size; cy++ )
|
||||
{
|
||||
this.verticalBits |= 1 << ( minCY + cy );
|
||||
}
|
||||
|
||||
for( int x = 0; x < this.x_size; x++ )
|
||||
{
|
||||
for( int z = 0; z < this.z_size; z++ )
|
||||
{
|
||||
this.myColumns[x][z] = new Column( w.getChunk( ( minX + x ) >> 4, ( minZ + z ) >> 4 ), ( minX + x ) & 0xF, ( minZ + z ) & 0xF, minCY, cy_size );
|
||||
}
|
||||
}
|
||||
|
||||
final IMovableRegistry mr = AEApi.instance().registries().movable();
|
||||
|
||||
for( int cx = 0; cx < this.cx_size; cx++ )
|
||||
{
|
||||
for( int cz = 0; cz < this.cz_size; cz++ )
|
||||
{
|
||||
final List<BlockPos> deadTiles = new ArrayList<>();
|
||||
|
||||
final Chunk c = w.getChunk( minCX + cx, minCZ + cz );
|
||||
this.myChunks[cx][cz] = c;
|
||||
|
||||
final List<Entry<BlockPos, TileEntity>> rawTiles = new ArrayList<>(c.getTileEntityMap().entrySet());
|
||||
for( final Entry<BlockPos, TileEntity> tx : rawTiles )
|
||||
{
|
||||
final BlockPos cp = tx.getKey();
|
||||
final TileEntity te = tx.getValue();
|
||||
|
||||
final BlockPos tePOS = te.getPos();
|
||||
if( tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY && tePOS.getZ() >= minZ && tePOS
|
||||
.getZ() <= maxZ )
|
||||
{
|
||||
if( mr.askToMove( te ) )
|
||||
{
|
||||
this.tiles.add( te );
|
||||
deadTiles.add( cp );
|
||||
}
|
||||
else
|
||||
{
|
||||
final BlockStorageData details = new BlockStorageData();
|
||||
this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].fillData( tePOS.getY(), details );
|
||||
|
||||
// don't skip air, just let the code replace it...
|
||||
if( details.state != null && details.state.getBlock() == Platform.AIR_BLOCK && details.state.getMaterial().isReplaceable() )
|
||||
{
|
||||
w.removeBlock( tePOS, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].setSkip( tePOS.getY() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( final BlockPos cp : deadTiles )
|
||||
{
|
||||
c.getTileEntityMap().remove( cp );
|
||||
}
|
||||
|
||||
final long gameTime = this.getWorld().getGameTime();
|
||||
final ITickList<Block> pendingBlockTicks = this.getWorld().getPendingBlockTicks();
|
||||
if (pendingBlockTicks instanceof ServerTickList) {
|
||||
List<NextTickListEntry<Block>> pending = ((ServerTickList<Block>) pendingBlockTicks).getPending(c.getPos(), false, true);
|
||||
for (final NextTickListEntry<Block> entry : pending) {
|
||||
final BlockPos tePOS = entry.position;
|
||||
if (tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY && tePOS.getZ() >= minZ && tePOS
|
||||
.getZ() <= maxZ) {
|
||||
this.ticks.add(new NextTickListEntry<>(tePOS, entry.getTarget(), entry.scheduledTime - gameTime, entry.priority));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( final TileEntity te : this.tiles )
|
||||
{
|
||||
try
|
||||
{
|
||||
this.getWorld().loadedTileEntityList.remove( te );
|
||||
if( te instanceof ITickableTileEntity)
|
||||
{
|
||||
this.getWorld().tickableTileEntities.remove( te );
|
||||
}
|
||||
}
|
||||
catch( final Exception e )
|
||||
{
|
||||
AELog.debug( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IMovableHandler getHandler( final TileEntity te )
|
||||
{
|
||||
final IMovableRegistry mr = AEApi.instance().registries().movable();
|
||||
return mr.getHandler( te );
|
||||
}
|
||||
|
||||
void swap( final CachedPlane dst )
|
||||
{
|
||||
final IMovableRegistry mr = AEApi.instance().registries().movable();
|
||||
|
||||
if( dst.x_size == this.x_size && dst.y_size == this.y_size && dst.z_size == this.z_size )
|
||||
{
|
||||
AELog.info( "Block Copy Scale: " + this.x_size + ", " + this.y_size + ", " + this.z_size );
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
final BlockStorageData aD = new BlockStorageData();
|
||||
final BlockStorageData bD = new BlockStorageData();
|
||||
|
||||
for( int x = 0; x < this.x_size; x++ )
|
||||
{
|
||||
for( int z = 0; z < this.z_size; z++ )
|
||||
{
|
||||
final Column a = this.myColumns[x][z];
|
||||
final Column b = dst.myColumns[x][z];
|
||||
|
||||
for( int y = 0; y < this.y_size; y++ )
|
||||
{
|
||||
final int src_y = y + this.y_offset;
|
||||
final int dst_y = y + dst.y_offset;
|
||||
|
||||
if( a.doNotSkip( src_y ) && b.doNotSkip( dst_y ) )
|
||||
{
|
||||
a.fillData( src_y, aD );
|
||||
b.fillData( dst_y, bD );
|
||||
|
||||
a.setBlockState( src_y, bD );
|
||||
b.setBlockState( dst_y, aD );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.markForUpdate( x + this.x_offset, src_y, z + this.z_offset );
|
||||
dst.markForUpdate( x + dst.x_offset, dst_y, z + dst.z_offset );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long endTime = System.nanoTime();
|
||||
long duration = endTime - startTime;
|
||||
AELog.info( "Block Copy Time: " + duration );
|
||||
|
||||
for( final TileEntity te : this.tiles )
|
||||
{
|
||||
final BlockPos tePOS = te.getPos();
|
||||
dst.addTile( tePOS.getX() - this.x_offset, tePOS.getY() - this.y_offset, tePOS.getZ() - this.z_offset, te, this, mr );
|
||||
}
|
||||
|
||||
for( final TileEntity te : dst.tiles )
|
||||
{
|
||||
final BlockPos tePOS = te.getPos();
|
||||
this.addTile( tePOS.getX() - dst.x_offset, tePOS.getY() - dst.y_offset, tePOS.getZ() - dst.z_offset, te, dst, mr );
|
||||
}
|
||||
|
||||
for( final NextTickListEntry<Block> entry : this.ticks )
|
||||
{
|
||||
final BlockPos tePOS = entry.position;
|
||||
dst.addTick( tePOS.getX() - this.x_offset, tePOS.getY() - this.y_offset, tePOS.getZ() - this.z_offset, entry );
|
||||
}
|
||||
|
||||
for( final NextTickListEntry<Block> entry : dst.ticks )
|
||||
{
|
||||
final BlockPos tePOS = entry.position;
|
||||
this.addTick( tePOS.getX() - dst.x_offset, tePOS.getY() - dst.y_offset, tePOS.getZ() - dst.z_offset, entry );
|
||||
}
|
||||
|
||||
startTime = System.nanoTime();
|
||||
this.updateChunks();
|
||||
dst.updateChunks();
|
||||
endTime = System.nanoTime();
|
||||
|
||||
duration = endTime - startTime;
|
||||
AELog.info( "Update Time: " + duration );
|
||||
}
|
||||
}
|
||||
|
||||
private void markForUpdate( final int x, final int y, final int z )
|
||||
{
|
||||
this.updates.add( new WorldCoord( x, y, z ) );
|
||||
for( final AEPartLocation d : AEPartLocation.SIDE_LOCATIONS )
|
||||
{
|
||||
this.updates.add( new WorldCoord( x + d.xOffset, y + d.yOffset, z + d.zOffset ) );
|
||||
}
|
||||
}
|
||||
|
||||
private void addTick( final int x, final int y, final int z, final NextTickListEntry<Block> entry )
|
||||
{
|
||||
BlockPos where = new BlockPos(x + this.x_offset, y + this.y_offset, z + this.z_offset);
|
||||
this.world.getPendingBlockTicks().scheduleTick(where, entry.getTarget(), (int) entry.scheduledTime, entry.priority);
|
||||
}
|
||||
|
||||
private void addTile( final int x, final int y, final int z, final TileEntity te, final CachedPlane alternateDestination, final IMovableRegistry mr )
|
||||
{
|
||||
try
|
||||
{
|
||||
final Column c = this.myColumns[x][z];
|
||||
|
||||
if( c.doNotSkip( y + this.y_offset ) || alternateDestination == null )
|
||||
{
|
||||
final IMovableHandler handler = this.getHandler( te );
|
||||
|
||||
try
|
||||
{
|
||||
handler.moveTile( te, this.world, new BlockPos( x + this.x_offset, y + this.y_offset, z + this.z_offset ) );
|
||||
}
|
||||
catch( final Throwable e )
|
||||
{
|
||||
AELog.debug( e );
|
||||
|
||||
final BlockPos pos = new BlockPos( x, y, z );
|
||||
|
||||
// attempt recovery...
|
||||
c.c.addTileEntity(te);
|
||||
|
||||
this.world.notifyBlockUpdate( pos, this.world.getBlockState( pos ), this.world.getBlockState( pos ), z );
|
||||
}
|
||||
|
||||
mr.doneMoving( te );
|
||||
}
|
||||
else
|
||||
{
|
||||
alternateDestination.addTile( x, y, z, te, null, mr );
|
||||
}
|
||||
}
|
||||
catch( final Throwable e )
|
||||
{
|
||||
AELog.debug( e );
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChunks()
|
||||
{
|
||||
|
||||
// update shit..
|
||||
for( int x = 0; x < this.cx_size; x++ )
|
||||
{
|
||||
for( int z = 0; z < this.cz_size; z++ )
|
||||
{
|
||||
final Chunk c = this.myChunks[x][z];
|
||||
// FIXME: Light shit
|
||||
c.markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// send shit...
|
||||
for( int x = 0; x < this.cx_size; x++ )
|
||||
{
|
||||
for( int z = 0; z < this.cz_size; z++ )
|
||||
{
|
||||
|
||||
final Chunk c = this.myChunks[x][z];
|
||||
|
||||
for( int y = 1; y < 255; y += 32 )
|
||||
{
|
||||
WorldData.instance().compassData().service().updateArea( this.getWorld(), c.getPos().x << 4, y, c.getPos().z << 4 );
|
||||
}
|
||||
|
||||
// FIXME this was sending chunks to players...
|
||||
SChunkDataPacket cdp = new SChunkDataPacket(c, verticalBits);
|
||||
((ServerChunkProvider) world.getChunkProvider()).chunkManager.getTrackingPlayers(c.getPos(), false)
|
||||
.forEach(spe -> spe.connection.sendPacket(cdp));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME check if this makes any sense at all to send changes to players asap
|
||||
ServerChunkProvider serverChunkProvider = (ServerChunkProvider) world.getChunkProvider();
|
||||
serverChunkProvider.tick(() -> false);
|
||||
}
|
||||
|
||||
List<WorldCoord> getUpdates()
|
||||
{
|
||||
return this.updates;
|
||||
}
|
||||
|
||||
World getWorld()
|
||||
{
|
||||
return this.world;
|
||||
}
|
||||
|
||||
private static class BlockStorageData
|
||||
{
|
||||
public BlockState state;
|
||||
public int light;
|
||||
}
|
||||
|
||||
private class Column
|
||||
{
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final Chunk c;
|
||||
private List<Integer> skipThese = null;
|
||||
|
||||
public Column( final Chunk chunk, final int x, final int z, final int chunkY, final int chunkHeight )
|
||||
{
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.c = chunk;
|
||||
|
||||
final ChunkSection[] storage = this.c.getSections();
|
||||
|
||||
// make sure storage exists before hand...
|
||||
for( int ay = 0; ay < chunkHeight; ay++ )
|
||||
{
|
||||
final int by = ( ay + chunkY );
|
||||
ChunkSection extendedblockstorage = storage[by];
|
||||
if( extendedblockstorage == null )
|
||||
{
|
||||
extendedblockstorage = storage[by] = new ChunkSection( by << 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setBlockState(final int y, BlockStorageData data )
|
||||
{
|
||||
if( data.state == CachedPlane.this.matrixBlockState )
|
||||
{
|
||||
data.state = Platform.AIR_BLOCK.getDefaultState();
|
||||
}
|
||||
final ChunkSection[] storage = this.c.getSections();
|
||||
final ChunkSection extendedBlockStorage = storage[y >> 4];
|
||||
extendedBlockStorage.setBlockState( this.x, y & 15, this.z, data.state );
|
||||
// FIXME extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, data.light );
|
||||
}
|
||||
|
||||
private void fillData( final int y, BlockStorageData data )
|
||||
{
|
||||
final ChunkSection[] storage = this.c.getSections();
|
||||
final ChunkSection extendedblockstorage = storage[y >> 4];
|
||||
|
||||
data.state = extendedblockstorage.getBlockState( this.x, y & 15, this.z );
|
||||
// FIXME data.light = extendedblockstorage.getBlockLight( this.x, y & 15, this.z );
|
||||
}
|
||||
|
||||
private boolean doNotSkip( final int y )
|
||||
{
|
||||
final ChunkSection[] storage = this.c.getSections();
|
||||
final ChunkSection extendedblockstorage = storage[y >> 4];
|
||||
if( CachedPlane.this.reg.isBlacklisted( extendedblockstorage.getBlockState( this.x, y & 15, this.z ).getBlock() ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.skipThese == null || !this.skipThese.contains( y );
|
||||
}
|
||||
|
||||
private void setSkip( final int yCoord )
|
||||
{
|
||||
if( this.skipThese == null )
|
||||
{
|
||||
this.skipThese = new ArrayList<>();
|
||||
}
|
||||
this.skipThese.add( yCoord );
|
||||
}
|
||||
}
|
||||
|
||||
public class CachedPlane {
|
||||
private final int x_size;
|
||||
private final int z_size;
|
||||
private final int cx_size;
|
||||
private final int cz_size;
|
||||
private final int x_offset;
|
||||
private final int y_offset;
|
||||
private final int z_offset;
|
||||
private final int y_size;
|
||||
private final Chunk[][] myChunks;
|
||||
private final Column[][] myColumns;
|
||||
private final List<TileEntity> tiles = new ArrayList<>();
|
||||
private final List<NextTickListEntry<Block>> ticks = new ArrayList<>();
|
||||
private final World world;
|
||||
private final IMovableRegistry reg = AEApi.instance().registries().movable();
|
||||
private final List<WorldCoord> updates = new ArrayList<>();
|
||||
private int verticalBits;
|
||||
private final BlockState matrixBlockState;
|
||||
|
||||
public CachedPlane(final World w, final int minX, final int minY, final int minZ, final int maxX, final int maxY,
|
||||
final int maxZ) {
|
||||
|
||||
Block matrixFrameBlock = AEApi.instance().definitions().blocks().matrixFrame().maybeBlock().orElse(null);
|
||||
if (matrixFrameBlock != null) {
|
||||
this.matrixBlockState = matrixFrameBlock.getDefaultState();
|
||||
} else {
|
||||
this.matrixBlockState = null;
|
||||
}
|
||||
|
||||
this.world = w;
|
||||
|
||||
this.x_size = maxX - minX + 1;
|
||||
this.y_size = maxY - minY + 1;
|
||||
this.z_size = maxZ - minZ + 1;
|
||||
|
||||
this.x_offset = minX;
|
||||
this.y_offset = minY;
|
||||
this.z_offset = minZ;
|
||||
|
||||
final int minCX = minX >> 4;
|
||||
final int minCY = minY >> 4;
|
||||
final int minCZ = minZ >> 4;
|
||||
final int maxCX = maxX >> 4;
|
||||
final int maxCY = maxY >> 4;
|
||||
final int maxCZ = maxZ >> 4;
|
||||
|
||||
this.cx_size = maxCX - minCX + 1;
|
||||
final int cy_size = maxCY - minCY + 1;
|
||||
this.cz_size = maxCZ - minCZ + 1;
|
||||
|
||||
this.myChunks = new Chunk[this.cx_size][this.cz_size];
|
||||
this.myColumns = new Column[this.x_size][this.z_size];
|
||||
|
||||
this.verticalBits = 0;
|
||||
for (int cy = 0; cy < cy_size; cy++) {
|
||||
this.verticalBits |= 1 << (minCY + cy);
|
||||
}
|
||||
|
||||
for (int x = 0; x < this.x_size; x++) {
|
||||
for (int z = 0; z < this.z_size; z++) {
|
||||
this.myColumns[x][z] = new Column(w.getChunk((minX + x) >> 4, (minZ + z) >> 4), (minX + x) & 0xF,
|
||||
(minZ + z) & 0xF, minCY, cy_size);
|
||||
}
|
||||
}
|
||||
|
||||
final IMovableRegistry mr = AEApi.instance().registries().movable();
|
||||
|
||||
for (int cx = 0; cx < this.cx_size; cx++) {
|
||||
for (int cz = 0; cz < this.cz_size; cz++) {
|
||||
final List<BlockPos> deadTiles = new ArrayList<>();
|
||||
|
||||
final Chunk c = w.getChunk(minCX + cx, minCZ + cz);
|
||||
this.myChunks[cx][cz] = c;
|
||||
|
||||
final List<Entry<BlockPos, TileEntity>> rawTiles = new ArrayList<>(c.getTileEntityMap().entrySet());
|
||||
for (final Entry<BlockPos, TileEntity> tx : rawTiles) {
|
||||
final BlockPos cp = tx.getKey();
|
||||
final TileEntity te = tx.getValue();
|
||||
|
||||
final BlockPos tePOS = te.getPos();
|
||||
if (tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY
|
||||
&& tePOS.getZ() >= minZ && tePOS.getZ() <= maxZ) {
|
||||
if (mr.askToMove(te)) {
|
||||
this.tiles.add(te);
|
||||
deadTiles.add(cp);
|
||||
} else {
|
||||
final BlockStorageData details = new BlockStorageData();
|
||||
this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].fillData(tePOS.getY(), details);
|
||||
|
||||
// don't skip air, just let the code replace it...
|
||||
if (details.state != null && details.state.getBlock() == Platform.AIR_BLOCK
|
||||
&& details.state.getMaterial().isReplaceable()) {
|
||||
w.removeBlock(tePOS, false);
|
||||
} else {
|
||||
this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].setSkip(tePOS.getY());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final BlockPos cp : deadTiles) {
|
||||
c.getTileEntityMap().remove(cp);
|
||||
}
|
||||
|
||||
final long gameTime = this.getWorld().getGameTime();
|
||||
final ITickList<Block> pendingBlockTicks = this.getWorld().getPendingBlockTicks();
|
||||
if (pendingBlockTicks instanceof ServerTickList) {
|
||||
List<NextTickListEntry<Block>> pending = ((ServerTickList<Block>) pendingBlockTicks)
|
||||
.getPending(c.getPos(), false, true);
|
||||
for (final NextTickListEntry<Block> entry : pending) {
|
||||
final BlockPos tePOS = entry.position;
|
||||
if (tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY
|
||||
&& tePOS.getZ() >= minZ && tePOS.getZ() <= maxZ) {
|
||||
this.ticks.add(new NextTickListEntry<>(tePOS, entry.getTarget(),
|
||||
entry.scheduledTime - gameTime, entry.priority));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final TileEntity te : this.tiles) {
|
||||
try {
|
||||
this.getWorld().loadedTileEntityList.remove(te);
|
||||
if (te instanceof ITickableTileEntity) {
|
||||
this.getWorld().tickableTileEntities.remove(te);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
AELog.debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IMovableHandler getHandler(final TileEntity te) {
|
||||
final IMovableRegistry mr = AEApi.instance().registries().movable();
|
||||
return mr.getHandler(te);
|
||||
}
|
||||
|
||||
void swap(final CachedPlane dst) {
|
||||
final IMovableRegistry mr = AEApi.instance().registries().movable();
|
||||
|
||||
if (dst.x_size == this.x_size && dst.y_size == this.y_size && dst.z_size == this.z_size) {
|
||||
AELog.info("Block Copy Scale: " + this.x_size + ", " + this.y_size + ", " + this.z_size);
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
final BlockStorageData aD = new BlockStorageData();
|
||||
final BlockStorageData bD = new BlockStorageData();
|
||||
|
||||
for (int x = 0; x < this.x_size; x++) {
|
||||
for (int z = 0; z < this.z_size; z++) {
|
||||
final Column a = this.myColumns[x][z];
|
||||
final Column b = dst.myColumns[x][z];
|
||||
|
||||
for (int y = 0; y < this.y_size; y++) {
|
||||
final int src_y = y + this.y_offset;
|
||||
final int dst_y = y + dst.y_offset;
|
||||
|
||||
if (a.doNotSkip(src_y) && b.doNotSkip(dst_y)) {
|
||||
a.fillData(src_y, aD);
|
||||
b.fillData(dst_y, bD);
|
||||
|
||||
a.setBlockState(src_y, bD);
|
||||
b.setBlockState(dst_y, aD);
|
||||
} else {
|
||||
this.markForUpdate(x + this.x_offset, src_y, z + this.z_offset);
|
||||
dst.markForUpdate(x + dst.x_offset, dst_y, z + dst.z_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long endTime = System.nanoTime();
|
||||
long duration = endTime - startTime;
|
||||
AELog.info("Block Copy Time: " + duration);
|
||||
|
||||
for (final TileEntity te : this.tiles) {
|
||||
final BlockPos tePOS = te.getPos();
|
||||
dst.addTile(tePOS.getX() - this.x_offset, tePOS.getY() - this.y_offset, tePOS.getZ() - this.z_offset,
|
||||
te, this, mr);
|
||||
}
|
||||
|
||||
for (final TileEntity te : dst.tiles) {
|
||||
final BlockPos tePOS = te.getPos();
|
||||
this.addTile(tePOS.getX() - dst.x_offset, tePOS.getY() - dst.y_offset, tePOS.getZ() - dst.z_offset, te,
|
||||
dst, mr);
|
||||
}
|
||||
|
||||
for (final NextTickListEntry<Block> entry : this.ticks) {
|
||||
final BlockPos tePOS = entry.position;
|
||||
dst.addTick(tePOS.getX() - this.x_offset, tePOS.getY() - this.y_offset, tePOS.getZ() - this.z_offset,
|
||||
entry);
|
||||
}
|
||||
|
||||
for (final NextTickListEntry<Block> entry : dst.ticks) {
|
||||
final BlockPos tePOS = entry.position;
|
||||
this.addTick(tePOS.getX() - dst.x_offset, tePOS.getY() - dst.y_offset, tePOS.getZ() - dst.z_offset,
|
||||
entry);
|
||||
}
|
||||
|
||||
startTime = System.nanoTime();
|
||||
this.updateChunks();
|
||||
dst.updateChunks();
|
||||
endTime = System.nanoTime();
|
||||
|
||||
duration = endTime - startTime;
|
||||
AELog.info("Update Time: " + duration);
|
||||
}
|
||||
}
|
||||
|
||||
private void markForUpdate(final int x, final int y, final int z) {
|
||||
this.updates.add(new WorldCoord(x, y, z));
|
||||
for (final AEPartLocation d : AEPartLocation.SIDE_LOCATIONS) {
|
||||
this.updates.add(new WorldCoord(x + d.xOffset, y + d.yOffset, z + d.zOffset));
|
||||
}
|
||||
}
|
||||
|
||||
private void addTick(final int x, final int y, final int z, final NextTickListEntry<Block> entry) {
|
||||
BlockPos where = new BlockPos(x + this.x_offset, y + this.y_offset, z + this.z_offset);
|
||||
this.world.getPendingBlockTicks().scheduleTick(where, entry.getTarget(), (int) entry.scheduledTime,
|
||||
entry.priority);
|
||||
}
|
||||
|
||||
private void addTile(final int x, final int y, final int z, final TileEntity te,
|
||||
final CachedPlane alternateDestination, final IMovableRegistry mr) {
|
||||
try {
|
||||
final Column c = this.myColumns[x][z];
|
||||
|
||||
if (c.doNotSkip(y + this.y_offset) || alternateDestination == null) {
|
||||
final IMovableHandler handler = this.getHandler(te);
|
||||
|
||||
try {
|
||||
handler.moveTile(te, this.world,
|
||||
new BlockPos(x + this.x_offset, y + this.y_offset, z + this.z_offset));
|
||||
} catch (final Throwable e) {
|
||||
AELog.debug(e);
|
||||
|
||||
final BlockPos pos = new BlockPos(x, y, z);
|
||||
|
||||
// attempt recovery...
|
||||
c.c.addTileEntity(te);
|
||||
|
||||
this.world.notifyBlockUpdate(pos, this.world.getBlockState(pos), this.world.getBlockState(pos), z);
|
||||
}
|
||||
|
||||
mr.doneMoving(te);
|
||||
} else {
|
||||
alternateDestination.addTile(x, y, z, te, null, mr);
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
AELog.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChunks() {
|
||||
|
||||
// update shit..
|
||||
for (int x = 0; x < this.cx_size; x++) {
|
||||
for (int z = 0; z < this.cz_size; z++) {
|
||||
final Chunk c = this.myChunks[x][z];
|
||||
// FIXME: Light shit
|
||||
c.markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// send shit...
|
||||
for (int x = 0; x < this.cx_size; x++) {
|
||||
for (int z = 0; z < this.cz_size; z++) {
|
||||
|
||||
final Chunk c = this.myChunks[x][z];
|
||||
|
||||
for (int y = 1; y < 255; y += 32) {
|
||||
WorldData.instance().compassData().service().updateArea(this.getWorld(), c.getPos().x << 4, y,
|
||||
c.getPos().z << 4);
|
||||
}
|
||||
|
||||
// FIXME this was sending chunks to players...
|
||||
SChunkDataPacket cdp = new SChunkDataPacket(c, verticalBits);
|
||||
((ServerChunkProvider) world.getChunkProvider()).chunkManager.getTrackingPlayers(c.getPos(), false)
|
||||
.forEach(spe -> spe.connection.sendPacket(cdp));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME check if this makes any sense at all to send changes to players asap
|
||||
ServerChunkProvider serverChunkProvider = (ServerChunkProvider) world.getChunkProvider();
|
||||
serverChunkProvider.tick(() -> false);
|
||||
}
|
||||
|
||||
List<WorldCoord> getUpdates() {
|
||||
return this.updates;
|
||||
}
|
||||
|
||||
World getWorld() {
|
||||
return this.world;
|
||||
}
|
||||
|
||||
private static class BlockStorageData {
|
||||
public BlockState state;
|
||||
public int light;
|
||||
}
|
||||
|
||||
private class Column {
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final Chunk c;
|
||||
private List<Integer> skipThese = null;
|
||||
|
||||
public Column(final Chunk chunk, final int x, final int z, final int chunkY, final int chunkHeight) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.c = chunk;
|
||||
|
||||
final ChunkSection[] storage = this.c.getSections();
|
||||
|
||||
// make sure storage exists before hand...
|
||||
for (int ay = 0; ay < chunkHeight; ay++) {
|
||||
final int by = (ay + chunkY);
|
||||
ChunkSection extendedblockstorage = storage[by];
|
||||
if (extendedblockstorage == null) {
|
||||
extendedblockstorage = storage[by] = new ChunkSection(by << 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setBlockState(final int y, BlockStorageData data) {
|
||||
if (data.state == CachedPlane.this.matrixBlockState) {
|
||||
data.state = Platform.AIR_BLOCK.getDefaultState();
|
||||
}
|
||||
final ChunkSection[] storage = this.c.getSections();
|
||||
final ChunkSection extendedBlockStorage = storage[y >> 4];
|
||||
extendedBlockStorage.setBlockState(this.x, y & 15, this.z, data.state);
|
||||
// FIXME extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, data.light
|
||||
// );
|
||||
}
|
||||
|
||||
private void fillData(final int y, BlockStorageData data) {
|
||||
final ChunkSection[] storage = this.c.getSections();
|
||||
final ChunkSection extendedblockstorage = storage[y >> 4];
|
||||
|
||||
data.state = extendedblockstorage.getBlockState(this.x, y & 15, this.z);
|
||||
// FIXME data.light = extendedblockstorage.getBlockLight( this.x, y & 15, this.z
|
||||
// );
|
||||
}
|
||||
|
||||
private boolean doNotSkip(final int y) {
|
||||
final ChunkSection[] storage = this.c.getSections();
|
||||
final ChunkSection extendedblockstorage = storage[y >> 4];
|
||||
if (CachedPlane.this.reg
|
||||
.isBlacklisted(extendedblockstorage.getBlockState(this.x, y & 15, this.z).getBlock())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.skipThese == null || !this.skipThese.contains(y);
|
||||
}
|
||||
|
||||
private void setSkip(final int yCoord) {
|
||||
if (this.skipThese == null) {
|
||||
this.skipThese = new ArrayList<>();
|
||||
}
|
||||
this.skipThese.add(yCoord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -27,36 +26,31 @@ import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import appeng.api.movable.IMovableHandler;
|
||||
|
||||
public class DefaultSpatialHandler implements IMovableHandler {
|
||||
|
||||
public class DefaultSpatialHandler implements IMovableHandler
|
||||
{
|
||||
/**
|
||||
* never called for the default.
|
||||
*
|
||||
* @param tile tile entity
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
@Override
|
||||
public boolean canHandle(final Class<? extends TileEntity> myClass, final TileEntity tile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* never called for the default.
|
||||
*
|
||||
* @param tile tile entity
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
@Override
|
||||
public boolean canHandle( final Class<? extends TileEntity> myClass, final TileEntity tile )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void moveTile(final TileEntity te, final World w, final BlockPos newPosition) {
|
||||
te.setWorldAndPos(w, newPosition);
|
||||
|
||||
@Override
|
||||
public void moveTile( final TileEntity te, final World w, final BlockPos newPosition )
|
||||
{
|
||||
te.setWorldAndPos( w, newPosition );
|
||||
final Chunk c = w.getChunkAt(newPosition);
|
||||
c.addTileEntity(newPosition, te);
|
||||
|
||||
final Chunk c = w.getChunkAt( newPosition );
|
||||
c.addTileEntity( newPosition, te );
|
||||
|
||||
if( w.getChunkProvider().isChunkLoaded(c.getPos()) )
|
||||
{
|
||||
final BlockState state = w.getBlockState( newPosition );
|
||||
w.addTileEntity( te );
|
||||
w.notifyBlockUpdate( newPosition, state, state, 1 );
|
||||
}
|
||||
}
|
||||
if (w.getChunkProvider().isChunkLoaded(c.getPos())) {
|
||||
final BlockState state = w.getBlockState(newPosition);
|
||||
w.addTileEntity(te);
|
||||
w.notifyBlockUpdate(newPosition, state, state, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,9 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public interface ISpatialVisitor {
|
||||
|
||||
public interface ISpatialVisitor
|
||||
{
|
||||
|
||||
void visit( BlockPos pos );
|
||||
void visit(BlockPos pos);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
package appeng.spatial;
|
||||
|
||||
import appeng.core.AELog;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import appeng.core.AELog;
|
||||
|
||||
/**
|
||||
* Helps with encoding and decoding the extra data we attach to the
|
||||
* spatial {@link net.minecraft.world.dimension.DimensionType} as "extra data".
|
||||
* Keep in mind this data will also be sent to the client unless
|
||||
* {@link net.minecraftforge.common.ModDimension#write(PacketBuffer, boolean)} is overridden.
|
||||
* Helps with encoding and decoding the extra data we attach to the spatial
|
||||
* {@link net.minecraft.world.dimension.DimensionType} as "extra data". Keep in
|
||||
* mind this data will also be sent to the client unless
|
||||
* {@link net.minecraftforge.common.ModDimension#write(PacketBuffer, boolean)}
|
||||
* is overridden.
|
||||
*/
|
||||
public final class SpatialDimensionExtraData {
|
||||
|
||||
@@ -19,8 +22,9 @@ public final class SpatialDimensionExtraData {
|
||||
private static final int CURRENT_FORMAT = 1;
|
||||
|
||||
/**
|
||||
* The storage size of this dimension. This is dicateted by the pylon structure size used to perform
|
||||
* the first transfer into this dimension. Once it's set, it cannot be changed anymore.
|
||||
* The storage size of this dimension. This is dicateted by the pylon structure
|
||||
* size used to perform the first transfer into this dimension. Once it's set,
|
||||
* it cannot be changed anymore.
|
||||
*/
|
||||
private final BlockPos size;
|
||||
|
||||
@@ -50,7 +54,8 @@ public final class SpatialDimensionExtraData {
|
||||
buf.readerIndex(0);
|
||||
byte version = buf.readByte();
|
||||
if (version != CURRENT_FORMAT) {
|
||||
// Currently no new format has been defined, as such anything but the current version is invalid
|
||||
// Currently no new format has been defined, as such anything but the current
|
||||
// version is invalid
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import appeng.api.storage.ISpatialDimension;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.localization.GuiText;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
@@ -33,144 +33,138 @@ import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import appeng.api.storage.ISpatialDimension;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.localization.GuiText;
|
||||
|
||||
public final class SpatialDimensionManager implements ISpatialDimension {
|
||||
|
||||
public final class SpatialDimensionManager implements ISpatialDimension
|
||||
{
|
||||
public static final ISpatialDimension INSTANCE = new SpatialDimensionManager();
|
||||
|
||||
public static final ISpatialDimension INSTANCE = new SpatialDimensionManager();
|
||||
private static final String DIM_ID_PREFIX = "spatial_";
|
||||
|
||||
private static final String DIM_ID_PREFIX = "spatial_";
|
||||
private SpatialDimensionManager() {
|
||||
}
|
||||
|
||||
private SpatialDimensionManager() {
|
||||
}
|
||||
@Override
|
||||
public ServerWorld getWorld(DimensionType cellDim) {
|
||||
return DimensionManager.getWorld(getServer(), cellDim, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld(DimensionType cellDim) {
|
||||
return DimensionManager.getWorld(getServer(), cellDim, true, true);
|
||||
}
|
||||
@Override
|
||||
public DimensionType createNewCellDimension(BlockPos size) {
|
||||
ResourceLocation dimKey = findFreeDimensionId();
|
||||
AELog.info("Allocating storage cell dimension '%s'", dimKey);
|
||||
|
||||
@Override
|
||||
public DimensionType createNewCellDimension(BlockPos size)
|
||||
{
|
||||
ResourceLocation dimKey = findFreeDimensionId();
|
||||
AELog.info("Allocating storage cell dimension '%s'", dimKey);
|
||||
PacketBuffer extraData = new SpatialDimensionExtraData(size).write();
|
||||
|
||||
PacketBuffer extraData = new SpatialDimensionExtraData(size).write();
|
||||
return DimensionManager.registerDimension(dimKey, StorageCellModDimension.INSTANCE, extraData, true);
|
||||
}
|
||||
|
||||
return DimensionManager.registerDimension(dimKey, StorageCellModDimension.INSTANCE, extraData, true);
|
||||
}
|
||||
/**
|
||||
* Tries finding the next free storage cell dimension ID based on the currently
|
||||
* registered storage cell dimensions.
|
||||
*/
|
||||
private ResourceLocation findFreeDimensionId() {
|
||||
int maxId = 0;
|
||||
for (DimensionType dimensionType : DimensionType.getAll()) {
|
||||
ResourceLocation regName = dimensionType.getRegistryName();
|
||||
if (regName == null || !AppEng.MOD_ID.equals(regName.getNamespace())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries finding the next free storage cell dimension ID based on the currently registered storage
|
||||
* cell dimensions.
|
||||
*/
|
||||
private ResourceLocation findFreeDimensionId() {
|
||||
int maxId = 0;
|
||||
for (DimensionType dimensionType : DimensionType.getAll()) {
|
||||
ResourceLocation regName = dimensionType.getRegistryName();
|
||||
if (regName == null || !AppEng.MOD_ID.equals(regName.getNamespace())) {
|
||||
continue;
|
||||
}
|
||||
String path = regName.getPath();
|
||||
if (!path.startsWith(DIM_ID_PREFIX)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String path = regName.getPath();
|
||||
if (!path.startsWith(DIM_ID_PREFIX)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
String numericIdPart = path.substring(DIM_ID_PREFIX.length());
|
||||
maxId = Math.max(Integer.parseUnsignedInt(numericIdPart), maxId);
|
||||
} catch (NumberFormatException e) {
|
||||
AELog.warn("Unparsable storage cell dimension id '%s'", path, e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String numericIdPart = path.substring(DIM_ID_PREFIX.length());
|
||||
maxId = Math.max(Integer.parseUnsignedInt(numericIdPart), maxId);
|
||||
} catch (NumberFormatException e) {
|
||||
AELog.warn("Unparsable storage cell dimension id '%s'", path, e);
|
||||
}
|
||||
}
|
||||
++maxId;
|
||||
|
||||
++maxId;
|
||||
return new ResourceLocation(AppEng.MOD_ID, DIM_ID_PREFIX + maxId);
|
||||
}
|
||||
|
||||
return new ResourceLocation(AppEng.MOD_ID, DIM_ID_PREFIX + maxId);
|
||||
}
|
||||
@Override
|
||||
public void deleteCellDimension(DimensionType cellDim) {
|
||||
AELog.info("Unregistering storage cell dimension %s", cellDim.getRegistryName());
|
||||
MinecraftServer server = getServer();
|
||||
ServerWorld world = DimensionManager.getWorld(server, cellDim, false, false);
|
||||
if (world != null) {
|
||||
DimensionManager.unloadWorld(world);
|
||||
}
|
||||
DimensionManager.unloadWorlds(server, true);
|
||||
DimensionManager.unregisterDimension(cellDim.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCellDimension( DimensionType cellDim )
|
||||
{
|
||||
AELog.info("Unregistering storage cell dimension %s", cellDim.getRegistryName());
|
||||
MinecraftServer server = getServer();
|
||||
ServerWorld world = DimensionManager.getWorld(server, cellDim, false, false);
|
||||
if (world != null) {
|
||||
DimensionManager.unloadWorld(world);
|
||||
}
|
||||
DimensionManager.unloadWorlds(server, true);
|
||||
DimensionManager.unregisterDimension(cellDim.getId());
|
||||
}
|
||||
@Override
|
||||
public boolean isCellDimension(DimensionType cellDim) {
|
||||
// Check if the cell dimension type is even registered
|
||||
if (cellDim.getRegistryName() == null || !cellDim.getRegistryName().equals(DimensionType.getKey(cellDim))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellDimension( DimensionType cellDim )
|
||||
{
|
||||
// Check if the cell dimension type is even registered
|
||||
if (cellDim.getRegistryName() == null || !cellDim.getRegistryName().equals(DimensionType.getKey(cellDim))) {
|
||||
return false;
|
||||
}
|
||||
return cellDim.getModType() instanceof StorageCellModDimension;
|
||||
}
|
||||
|
||||
return cellDim.getModType() instanceof StorageCellModDimension;
|
||||
}
|
||||
@Override
|
||||
public BlockPos getCellDimensionOrigin(DimensionType cellDim) {
|
||||
return StorageCellDimension.REGION_CENTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getCellDimensionOrigin( DimensionType cellDim )
|
||||
{
|
||||
return StorageCellDimension.REGION_CENTER;
|
||||
}
|
||||
@Override
|
||||
public BlockPos getCellDimensionSize(DimensionType cellDim) {
|
||||
SpatialDimensionExtraData extraData = getExtraData(cellDim);
|
||||
return extraData != null ? extraData.getSize() : BlockPos.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getCellDimensionSize(DimensionType cellDim )
|
||||
{
|
||||
SpatialDimensionExtraData extraData = getExtraData(cellDim);
|
||||
return extraData != null ? extraData.getSize() : BlockPos.ZERO;
|
||||
}
|
||||
@Override
|
||||
public void addCellDimensionTooltip(DimensionType cellDim, List<ITextComponent> lines) {
|
||||
// Check if the cell dimension type is even registered
|
||||
ResourceLocation registryName = cellDim.getRegistryName();
|
||||
if (registryName == null || !AppEng.MOD_ID.equals(registryName.getNamespace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCellDimensionTooltip(DimensionType cellDim, List<ITextComponent> lines) {
|
||||
// Check if the cell dimension type is even registered
|
||||
ResourceLocation registryName = cellDim.getRegistryName();
|
||||
if (registryName == null || !AppEng.MOD_ID.equals(registryName.getNamespace())) {
|
||||
return;
|
||||
}
|
||||
if (!registryName.getPath().startsWith(DIM_ID_PREFIX)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!registryName.getPath().startsWith(DIM_ID_PREFIX)) {
|
||||
return;
|
||||
}
|
||||
// Add the actual stored size
|
||||
BlockPos size = SpatialDimensionManager.INSTANCE.getCellDimensionSize(cellDim);
|
||||
lines.add(GuiText.StoredSize.textComponent(size.getX(), size.getY(), size.getZ()));
|
||||
|
||||
// Add the actual stored size
|
||||
BlockPos size = SpatialDimensionManager.INSTANCE.getCellDimensionSize(cellDim);
|
||||
lines.add( GuiText.StoredSize.textComponent(size.getX(), size.getY(), size.getZ()));
|
||||
// Add a serial number to allows players to keep different cells apart
|
||||
int dimId;
|
||||
try {
|
||||
String numericIdPart = registryName.getPath().substring(DIM_ID_PREFIX.length());
|
||||
dimId = Integer.parseUnsignedInt(numericIdPart);
|
||||
} catch (NumberFormatException ignored) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a serial number to allows players to keep different cells apart
|
||||
int dimId;
|
||||
try {
|
||||
String numericIdPart = registryName.getPath().substring(DIM_ID_PREFIX.length());
|
||||
dimId = Integer.parseUnsignedInt(numericIdPart);
|
||||
} catch (NumberFormatException ignored) {
|
||||
return;
|
||||
}
|
||||
// Try to make this a little more flavorful.
|
||||
String serialNumber = String.format(Locale.ROOT, "SP-%04d", dimId);
|
||||
lines.add(GuiText.SerialNumber.textComponent(serialNumber));
|
||||
}
|
||||
|
||||
// Try to make this a little more flavorful.
|
||||
String serialNumber = String.format(Locale.ROOT, "SP-%04d", dimId);
|
||||
lines.add(GuiText.SerialNumber.textComponent(serialNumber));
|
||||
}
|
||||
@Nullable
|
||||
private SpatialDimensionExtraData getExtraData(DimensionType cellDim) {
|
||||
if (!(cellDim.getModType() instanceof StorageCellModDimension)) {
|
||||
return null;
|
||||
}
|
||||
return SpatialDimensionExtraData.read(cellDim.getData());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private SpatialDimensionExtraData getExtraData( DimensionType cellDim) {
|
||||
if (!(cellDim.getModType() instanceof StorageCellModDimension)) {
|
||||
return null;
|
||||
}
|
||||
return SpatialDimensionExtraData.read(cellDim.getData());
|
||||
}
|
||||
|
||||
private static MinecraftServer getServer() {
|
||||
return ServerLifecycleHooks.getCurrentServer();
|
||||
}
|
||||
private static MinecraftServer getServer() {
|
||||
return ServerLifecycleHooks.getCurrentServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
@@ -26,30 +25,19 @@ import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class StorageCellBiome extends Biome {
|
||||
|
||||
public class StorageCellBiome extends Biome
|
||||
{
|
||||
public static final StorageCellBiome INSTANCE = new StorageCellBiome();
|
||||
|
||||
public static final StorageCellBiome INSTANCE = new StorageCellBiome();
|
||||
static {
|
||||
INSTANCE.setRegistryName("appliedenergistics2:storage");
|
||||
}
|
||||
|
||||
static {
|
||||
INSTANCE.setRegistryName("appliedenergistics2:storage");
|
||||
}
|
||||
|
||||
public StorageCellBiome()
|
||||
{
|
||||
super( new Biome.Builder()
|
||||
.surfaceBuilder(SurfaceBuilder.NOPE, SurfaceBuilder.STONE_STONE_GRAVEL_CONFIG)
|
||||
.precipitation(RainType.NONE)
|
||||
.category(Category.NONE)
|
||||
.depth(0)
|
||||
.scale(1)
|
||||
// Copied from the vanilla void biome
|
||||
.temperature(0.5F)
|
||||
.downfall(0.5F)
|
||||
.waterColor(4159204)
|
||||
.waterFogColor(329011)
|
||||
.parent(null) );
|
||||
public StorageCellBiome() {
|
||||
super(new Biome.Builder().surfaceBuilder(SurfaceBuilder.NOPE, SurfaceBuilder.STONE_STONE_GRAVEL_CONFIG)
|
||||
.precipitation(RainType.NONE).category(Category.NONE).depth(0).scale(1)
|
||||
// Copied from the vanilla void biome
|
||||
.temperature(0.5F).downfall(0.5F).waterColor(4159204).waterFogColor(329011).parent(null));
|
||||
// FIXME this.decorator.treesPerChunk = 0;
|
||||
// FIXME this.decorator.flowersPerChunk = 0;
|
||||
// FIXME this.decorator.grassPerChunk = 0;
|
||||
@@ -58,26 +46,26 @@ public class StorageCellBiome extends Biome
|
||||
// FIXME this.spawnableCreatureList.clear();
|
||||
// FIXME this.spawnableWaterCreatureList.clear();
|
||||
// FIXME this.spawnableCaveCreatureList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public int getSkyColor() {
|
||||
return 0x111111;
|
||||
}
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public int getSkyColor() {
|
||||
return 0x111111;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesWaterFreeze(IWorldReader worldIn, BlockPos pos) {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean doesWaterFreeze(IWorldReader worldIn, BlockPos pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesWaterFreeze(IWorldReader worldIn, BlockPos water, boolean mustBeAtEdge) {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean doesWaterFreeze(IWorldReader worldIn, BlockPos water, boolean mustBeAtEdge) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesSnowGenerate(IWorldReader worldIn, BlockPos pos) {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean doesSnowGenerate(IWorldReader worldIn, BlockPos pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
@@ -28,123 +29,107 @@ import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.dimension.Dimension;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
import net.minecraftforge.client.IRenderHandler;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.IRenderHandler;
|
||||
|
||||
import appeng.client.render.SpatialSkyRender;
|
||||
import appeng.core.AppEng;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
public class StorageCellDimension extends Dimension {
|
||||
|
||||
public class StorageCellDimension extends Dimension
|
||||
{
|
||||
// A region file is 512x512 blocks (32x32 chunks),
|
||||
// to avoid creating the 4 regions around 0,0,0,
|
||||
// we move the origin to the middle of region 0,0
|
||||
public static final BlockPos REGION_CENTER = new BlockPos(512 / 2, 64, 512 / 2);
|
||||
|
||||
// A region file is 512x512 blocks (32x32 chunks),
|
||||
// to avoid creating the 4 regions around 0,0,0,
|
||||
// we move the origin to the middle of region 0,0
|
||||
public static final BlockPos REGION_CENTER = new BlockPos(512 / 2, 64, 512 / 2);
|
||||
public StorageCellDimension(World world, DimensionType dimensionType) {
|
||||
// FIXME: check light value
|
||||
super(world, dimensionType, 1.0f);
|
||||
}
|
||||
|
||||
public StorageCellDimension(World world, DimensionType dimensionType) {
|
||||
// FIXME: check light value
|
||||
super(world, dimensionType, 1.0f);
|
||||
}
|
||||
@Override
|
||||
public ChunkGenerator createChunkGenerator() {
|
||||
return new StorageChunkGenerator(this.world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator createChunkGenerator()
|
||||
{
|
||||
return new StorageChunkGenerator( this.world );
|
||||
}
|
||||
@Override
|
||||
public float calculateCelestialAngle(final long par1, final float par3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float calculateCelestialAngle( final long par1, final float par3 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public boolean isSurfaceWorld() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSurfaceWorld()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public float[] calcSunriseSunsetColors(final float celestialAngle, final float partialTicks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn( Dist.CLIENT )
|
||||
public float[] calcSunriseSunsetColors( final float celestialAngle, final float partialTicks )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Vec3d getFogColor(final float par1, final float par2) {
|
||||
return new Vec3d(0.07, 0.07, 0.07);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3d getFogColor( final float par1, final float par2 )
|
||||
{
|
||||
return new Vec3d( 0.07, 0.07, 0.07 );
|
||||
}
|
||||
@Override
|
||||
public boolean canRespawnHere() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRespawnHere()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public boolean isSkyColored() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn( Dist.CLIENT )
|
||||
public boolean isSkyColored()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean doesXZShowFog(final int par1, final int par2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesXZShowFog( final int par1, final int par2 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public IRenderHandler getSkyRenderer() {
|
||||
return SpatialSkyRender.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRenderHandler getSkyRenderer()
|
||||
{
|
||||
return SpatialSkyRender.getInstance();
|
||||
}
|
||||
@Override
|
||||
public boolean isDaytime() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDaytime()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public BlockPos getSpawnCoordinate() {
|
||||
return REGION_CENTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getSpawnCoordinate()
|
||||
{
|
||||
return REGION_CENTER;
|
||||
}
|
||||
@Override
|
||||
public boolean isHighHumidity(final BlockPos pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHighHumidity( final BlockPos pos )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canDoLightning(final Chunk chunk) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDoLightning( final Chunk chunk )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canDoRainSnowIce(Chunk chunk) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDoRainSnowIce(Chunk chunk) {
|
||||
return false;
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockPos findSpawn(ChunkPos chunkPosIn, boolean checkValid) {
|
||||
return getSpawnCoordinate();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockPos findSpawn(ChunkPos chunkPosIn, boolean checkValid) {
|
||||
return getSpawnCoordinate();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockPos findSpawn(int posX, int posZ, boolean checkValid) {
|
||||
return getSpawnCoordinate();
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockPos findSpawn(int posX, int posZ, boolean checkValid) {
|
||||
return getSpawnCoordinate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,27 +18,26 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.dimension.Dimension;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraftforge.common.ModDimension;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import appeng.core.AppEng;
|
||||
|
||||
public class StorageCellModDimension extends ModDimension
|
||||
{
|
||||
public class StorageCellModDimension extends ModDimension {
|
||||
|
||||
public static final StorageCellModDimension INSTANCE = new StorageCellModDimension();
|
||||
public static final StorageCellModDimension INSTANCE = new StorageCellModDimension();
|
||||
|
||||
static {
|
||||
INSTANCE.setRegistryName(AppEng.MOD_ID, "storage_cell");
|
||||
}
|
||||
static {
|
||||
INSTANCE.setRegistryName(AppEng.MOD_ID, "storage_cell");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<World, DimensionType, ? extends Dimension> getFactory() {
|
||||
return StorageCellDimension::new;
|
||||
}
|
||||
@Override
|
||||
public BiFunction<World, DimensionType, ? extends Dimension> getFactory() {
|
||||
return StorageCellDimension::new;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorld;
|
||||
@@ -29,76 +27,70 @@ import net.minecraft.world.biome.provider.SingleBiomeProvider;
|
||||
import net.minecraft.world.biome.provider.SingleBiomeProviderSettings;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import net.minecraft.world.gen.GenerationSettings;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.gen.WorldGenRegion;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
|
||||
public class StorageChunkGenerator extends ChunkGenerator<GenerationSettings>
|
||||
{
|
||||
public class StorageChunkGenerator extends ChunkGenerator<GenerationSettings> {
|
||||
|
||||
private final BlockState defaultBlockState;
|
||||
private final BlockState defaultBlockState;
|
||||
|
||||
public StorageChunkGenerator(final World world )
|
||||
{
|
||||
super( world, createBiomeProvider(), createSettings() );
|
||||
this.defaultBlockState = AEApi.instance().definitions().blocks().matrixFrame().block().getDefaultState();
|
||||
}
|
||||
public StorageChunkGenerator(final World world) {
|
||||
super(world, createBiomeProvider(), createSettings());
|
||||
this.defaultBlockState = AEApi.instance().definitions().blocks().matrixFrame().block().getDefaultState();
|
||||
}
|
||||
|
||||
private static BiomeProvider createBiomeProvider() {
|
||||
SingleBiomeProviderSettings biomeSettings = new SingleBiomeProviderSettings(null);
|
||||
biomeSettings.setBiome(StorageCellBiome.INSTANCE);
|
||||
return new SingleBiomeProvider(biomeSettings);
|
||||
}
|
||||
private static BiomeProvider createBiomeProvider() {
|
||||
SingleBiomeProviderSettings biomeSettings = new SingleBiomeProviderSettings(null);
|
||||
biomeSettings.setBiome(StorageCellBiome.INSTANCE);
|
||||
return new SingleBiomeProvider(biomeSettings);
|
||||
}
|
||||
|
||||
private static GenerationSettings createSettings() {
|
||||
return new GenerationSettings();
|
||||
}
|
||||
private static GenerationSettings createSettings() {
|
||||
return new GenerationSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateSurface(WorldGenRegion region, IChunk chunk) {
|
||||
this.fillChunk( chunk );
|
||||
chunk.setModified( false );
|
||||
}
|
||||
@Override
|
||||
public void generateSurface(WorldGenRegion region, IChunk chunk) {
|
||||
this.fillChunk(chunk);
|
||||
chunk.setModified(false);
|
||||
}
|
||||
|
||||
private void fillChunk( IChunk chunk )
|
||||
{
|
||||
BlockPos.Mutable mutPos = new BlockPos.Mutable();
|
||||
for( int cx = 0; cx < 16; cx++ )
|
||||
{
|
||||
mutPos.setX(cx);
|
||||
for( int cz = 0; cz < 16; cz++ )
|
||||
{
|
||||
// FIXME: It's likely a bad idea to fill Y in the inner-loop given the storage layout of chunks
|
||||
mutPos.setZ(cz);
|
||||
for( int cy = 0; cy < 256; cy++ )
|
||||
{
|
||||
mutPos.setY(cy);
|
||||
chunk.setBlockState(mutPos, defaultBlockState, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void fillChunk(IChunk chunk) {
|
||||
BlockPos.Mutable mutPos = new BlockPos.Mutable();
|
||||
for (int cx = 0; cx < 16; cx++) {
|
||||
mutPos.setX(cx);
|
||||
for (int cz = 0; cz < 16; cz++) {
|
||||
// FIXME: It's likely a bad idea to fill Y in the inner-loop given the storage
|
||||
// layout of chunks
|
||||
mutPos.setZ(cz);
|
||||
for (int cy = 0; cy < 256; cy++) {
|
||||
mutPos.setY(cy);
|
||||
chunk.setBlockState(mutPos, defaultBlockState, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroundHeight() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getGroundHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeBase(IWorld worldIn, IChunk chunkIn) {
|
||||
}
|
||||
@Override
|
||||
public void makeBase(IWorld worldIn, IChunk chunkIn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int func_222529_a(int p_222529_1_, int p_222529_2_, Heightmap.Type heightmapType) {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int func_222529_a(int p_222529_1_, int p_222529_2_, Heightmap.Type heightmapType) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decorate(WorldGenRegion region) {
|
||||
// Do not decorate chunks at all
|
||||
}
|
||||
@Override
|
||||
public void decorate(WorldGenRegion region) {
|
||||
// Do not decorate chunks at all
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.spatial;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
@@ -40,245 +39,219 @@ import appeng.api.util.WorldCoord;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class StorageHelper {
|
||||
|
||||
public class StorageHelper
|
||||
{
|
||||
private static StorageHelper instance;
|
||||
|
||||
private static StorageHelper instance;
|
||||
public static StorageHelper getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new StorageHelper();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static StorageHelper getInstance()
|
||||
{
|
||||
if( instance == null )
|
||||
{
|
||||
instance = new StorageHelper();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
/**
|
||||
* Mostly from dimensional doors.. which mostly got it form X-Comp.
|
||||
*
|
||||
* @param entity to be teleported entity
|
||||
* @param link destination
|
||||
*
|
||||
* @return teleported entity
|
||||
*/
|
||||
private Entity teleportEntity(Entity entity, final TelDestination link) {
|
||||
final ServerWorld oldWorld;
|
||||
final ServerWorld newWorld;
|
||||
|
||||
/**
|
||||
* Mostly from dimensional doors.. which mostly got it form X-Comp.
|
||||
*
|
||||
* @param entity to be teleported entity
|
||||
* @param link destination
|
||||
*
|
||||
* @return teleported entity
|
||||
*/
|
||||
private Entity teleportEntity( Entity entity, final TelDestination link )
|
||||
{
|
||||
final ServerWorld oldWorld;
|
||||
final ServerWorld newWorld;
|
||||
try {
|
||||
oldWorld = (ServerWorld) entity.world;
|
||||
newWorld = (ServerWorld) link.dim;
|
||||
} catch (final Throwable e) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
oldWorld = (ServerWorld) entity.world;
|
||||
newWorld = (ServerWorld) link.dim;
|
||||
}
|
||||
catch( final Throwable e )
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
if (oldWorld == null) {
|
||||
return entity;
|
||||
}
|
||||
if (newWorld == null) {
|
||||
return entity;
|
||||
}
|
||||
if (newWorld == oldWorld) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
if( oldWorld == null )
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
if( newWorld == null )
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
if( newWorld == oldWorld )
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
// Are we riding something? Teleport it instead.
|
||||
if (entity.isPassenger()) {
|
||||
return this.teleportEntity(entity.getRidingEntity(), link);
|
||||
}
|
||||
|
||||
// Are we riding something? Teleport it instead.
|
||||
if( entity.isPassenger() )
|
||||
{
|
||||
return this.teleportEntity( entity.getRidingEntity(), link );
|
||||
}
|
||||
// Is something riding us? Handle it first.
|
||||
final List<Entity> passengers = entity.getPassengers();
|
||||
final List<Entity> passengersOnOtherSide = new ArrayList<>(passengers.size());
|
||||
for (Entity passenger : passengers) {
|
||||
passenger.stopRiding();
|
||||
passengersOnOtherSide.add(this.teleportEntity(passenger, link));
|
||||
}
|
||||
// We keep track of all so we can remount them on the other side.
|
||||
|
||||
// Is something riding us? Handle it first.
|
||||
final List<Entity> passengers = entity.getPassengers();
|
||||
final List<Entity> passengersOnOtherSide = new ArrayList<>(passengers.size());
|
||||
for( Entity passenger : passengers )
|
||||
{
|
||||
passenger.stopRiding();
|
||||
passengersOnOtherSide.add( this.teleportEntity( passenger, link ) );
|
||||
}
|
||||
// We keep track of all so we can remount them on the other side.
|
||||
// load the chunk!
|
||||
newWorld.getChunkProvider().getChunk(MathHelper.floor(link.x) >> 4, MathHelper.floor(link.z) >> 4,
|
||||
ChunkStatus.FULL, true);
|
||||
|
||||
// load the chunk!
|
||||
newWorld.getChunkProvider().getChunk( MathHelper.floor( link.x ) >> 4, MathHelper.floor( link.z ) >> 4, ChunkStatus.FULL, true );
|
||||
if (entity instanceof ServerPlayerEntity && link.dim.getDimension() instanceof StorageCellDimension) {
|
||||
AppEng.instance().getAdvancementTriggers().getSpatialExplorer().trigger((ServerPlayerEntity) entity);
|
||||
}
|
||||
|
||||
if( entity instanceof ServerPlayerEntity && link.dim.getDimension() instanceof StorageCellDimension)
|
||||
{
|
||||
AppEng.instance().getAdvancementTriggers().getSpatialExplorer().trigger( (ServerPlayerEntity) entity );
|
||||
}
|
||||
entity.changeDimension(link.dim.getDimension().getType(), new METeleporter(link));
|
||||
|
||||
entity.changeDimension( link.dim.getDimension().getType(), new METeleporter( link ) );
|
||||
if (!passengersOnOtherSide.isEmpty()) {
|
||||
for (Entity passanger : passengersOnOtherSide) {
|
||||
passanger.startRiding(entity, true);
|
||||
}
|
||||
}
|
||||
|
||||
if( !passengersOnOtherSide.isEmpty() )
|
||||
{
|
||||
for( Entity passanger : passengersOnOtherSide )
|
||||
{
|
||||
passanger.startRiding( entity, true );
|
||||
}
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
private void transverseEdges(final int minX, final int minY, final int minZ, final int maxX, final int maxY,
|
||||
final int maxZ, final ISpatialVisitor visitor) {
|
||||
for (int y = minY; y < maxY; y++) {
|
||||
for (int z = minZ; z < maxZ; z++) {
|
||||
visitor.visit(new BlockPos(minX, y, z));
|
||||
visitor.visit(new BlockPos(maxX, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
private void transverseEdges( final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ, final ISpatialVisitor visitor )
|
||||
{
|
||||
for( int y = minY; y < maxY; y++ )
|
||||
{
|
||||
for( int z = minZ; z < maxZ; z++ )
|
||||
{
|
||||
visitor.visit( new BlockPos( minX, y, z ) );
|
||||
visitor.visit( new BlockPos( maxX, y, z ) );
|
||||
}
|
||||
}
|
||||
for (int x = minX; x < maxX; x++) {
|
||||
for (int z = minZ; z < maxZ; z++) {
|
||||
visitor.visit(new BlockPos(x, minY, z));
|
||||
visitor.visit(new BlockPos(x, maxY, z));
|
||||
}
|
||||
}
|
||||
|
||||
for( int x = minX; x < maxX; x++ )
|
||||
{
|
||||
for( int z = minZ; z < maxZ; z++ )
|
||||
{
|
||||
visitor.visit( new BlockPos( x, minY, z ) );
|
||||
visitor.visit( new BlockPos( x, maxY, z ) );
|
||||
}
|
||||
}
|
||||
for (int x = minX; x < maxX; x++) {
|
||||
for (int y = minY; y < maxY; y++) {
|
||||
visitor.visit(new BlockPos(x, y, minZ));
|
||||
visitor.visit(new BlockPos(x, y, maxZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( int x = minX; x < maxX; x++ )
|
||||
{
|
||||
for( int y = minY; y < maxY; y++ )
|
||||
{
|
||||
visitor.visit( new BlockPos( x, y, minZ ) );
|
||||
visitor.visit( new BlockPos( x, y, maxZ ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
public void swapRegions(final World srcWorld, final int srcX, final int srcY, final int srcZ, final World dstWorld,
|
||||
final int dstX, final int dstY, final int dstZ, final int scaleX, final int scaleY, final int scaleZ) {
|
||||
AEApi.instance().definitions().blocks().matrixFrame().maybeBlock()
|
||||
.ifPresent(matrixFrameBlock -> this.transverseEdges(dstX - 1, dstY - 1, dstZ - 1, dstX + scaleX + 1,
|
||||
dstY + scaleY + 1, dstZ + scaleZ + 1,
|
||||
new WrapInMatrixFrame(matrixFrameBlock.getDefaultState(), dstWorld)));
|
||||
|
||||
public void swapRegions( final World srcWorld, final int srcX, final int srcY, final int srcZ, final World dstWorld, final int dstX, final int dstY, final int dstZ, final int scaleX, final int scaleY, final int scaleZ )
|
||||
{
|
||||
AEApi.instance()
|
||||
.definitions()
|
||||
.blocks()
|
||||
.matrixFrame()
|
||||
.maybeBlock()
|
||||
.ifPresent( matrixFrameBlock -> this.transverseEdges( dstX - 1, dstY - 1, dstZ - 1,
|
||||
dstX + scaleX + 1, dstY + scaleY + 1, dstZ + scaleZ + 1, new WrapInMatrixFrame( matrixFrameBlock.getDefaultState(), dstWorld ) ) );
|
||||
final AxisAlignedBB srcBox = new AxisAlignedBB(srcX, srcY, srcZ, srcX + scaleX + 1, srcY + scaleY + 1,
|
||||
srcZ + scaleZ + 1);
|
||||
|
||||
final AxisAlignedBB srcBox = new AxisAlignedBB( srcX, srcY, srcZ, srcX + scaleX + 1, srcY + scaleY + 1, srcZ + scaleZ + 1 );
|
||||
final AxisAlignedBB dstBox = new AxisAlignedBB(dstX, dstY, dstZ, dstX + scaleX + 1, dstY + scaleY + 1,
|
||||
dstZ + scaleZ + 1);
|
||||
|
||||
final AxisAlignedBB dstBox = new AxisAlignedBB( dstX, dstY, dstZ, dstX + scaleX + 1, dstY + scaleY + 1, dstZ + scaleZ + 1 );
|
||||
final CachedPlane cDst = new CachedPlane(dstWorld, dstX, dstY, dstZ, dstX + scaleX, dstY + scaleY,
|
||||
dstZ + scaleZ);
|
||||
final CachedPlane cSrc = new CachedPlane(srcWorld, srcX, srcY, srcZ, srcX + scaleX, srcY + scaleY,
|
||||
srcZ + scaleZ);
|
||||
|
||||
final CachedPlane cDst = new CachedPlane( dstWorld, dstX, dstY, dstZ, dstX + scaleX, dstY + scaleY, dstZ + scaleZ );
|
||||
final CachedPlane cSrc = new CachedPlane( srcWorld, srcX, srcY, srcZ, srcX + scaleX, srcY + scaleY, srcZ + scaleZ );
|
||||
// do nearly all the work... swaps blocks, tiles, and block ticks
|
||||
cSrc.swap(cDst);
|
||||
|
||||
// do nearly all the work... swaps blocks, tiles, and block ticks
|
||||
cSrc.swap( cDst );
|
||||
final List<Entity> srcE = srcWorld.getEntitiesWithinAABB(Entity.class, srcBox);
|
||||
final List<Entity> dstE = dstWorld.getEntitiesWithinAABB(Entity.class, dstBox);
|
||||
|
||||
final List<Entity> srcE = srcWorld.getEntitiesWithinAABB( Entity.class, srcBox );
|
||||
final List<Entity> dstE = dstWorld.getEntitiesWithinAABB( Entity.class, dstBox );
|
||||
for (final Entity e : dstE) {
|
||||
this.teleportEntity(e, new TelDestination(srcWorld, srcBox, e.getPosX(), e.getPosY(), e.getPosZ(),
|
||||
-dstX + srcX, -dstY + srcY, -dstZ + srcZ));
|
||||
}
|
||||
|
||||
for( final Entity e : dstE )
|
||||
{
|
||||
this.teleportEntity( e, new TelDestination( srcWorld, srcBox, e.getPosX(), e.getPosY(), e.getPosZ(), -dstX + srcX, -dstY + srcY, -dstZ + srcZ ) );
|
||||
}
|
||||
for (final Entity e : srcE) {
|
||||
this.teleportEntity(e, new TelDestination(dstWorld, dstBox, e.getPosX(), e.getPosY(), e.getPosZ(),
|
||||
-srcX + dstX, -srcY + dstY, -srcZ + dstZ));
|
||||
}
|
||||
|
||||
for( final Entity e : srcE )
|
||||
{
|
||||
this.teleportEntity( e, new TelDestination( dstWorld, dstBox, e.getPosX(), e.getPosY(), e.getPosZ(), -srcX + dstX, -srcY + dstY, -srcZ + dstZ ) );
|
||||
}
|
||||
for (final WorldCoord wc : cDst.getUpdates()) {
|
||||
cSrc.getWorld().notifyNeighborsOfStateChange(wc.getPos(), Platform.AIR_BLOCK);
|
||||
}
|
||||
|
||||
for( final WorldCoord wc : cDst.getUpdates() )
|
||||
{
|
||||
cSrc.getWorld().notifyNeighborsOfStateChange( wc.getPos(), Platform.AIR_BLOCK );
|
||||
}
|
||||
for (final WorldCoord wc : cSrc.getUpdates()) {
|
||||
cSrc.getWorld().notifyNeighborsOfStateChange(wc.getPos(), Platform.AIR_BLOCK);
|
||||
}
|
||||
|
||||
for( final WorldCoord wc : cSrc.getUpdates() )
|
||||
{
|
||||
cSrc.getWorld().notifyNeighborsOfStateChange( wc.getPos(), Platform.AIR_BLOCK );
|
||||
}
|
||||
this.transverseEdges(srcX - 1, srcY - 1, srcZ - 1, srcX + scaleX + 1, srcY + scaleY + 1, srcZ + scaleZ + 1,
|
||||
new TriggerUpdates(srcWorld));
|
||||
this.transverseEdges(dstX - 1, dstY - 1, dstZ - 1, dstX + scaleX + 1, dstY + scaleY + 1, dstZ + scaleZ + 1,
|
||||
new TriggerUpdates(dstWorld));
|
||||
|
||||
this.transverseEdges( srcX - 1, srcY - 1, srcZ - 1, srcX + scaleX + 1, srcY + scaleY + 1, srcZ + scaleZ + 1, new TriggerUpdates( srcWorld ) );
|
||||
this.transverseEdges( dstX - 1, dstY - 1, dstZ - 1, dstX + scaleX + 1, dstY + scaleY + 1, dstZ + scaleZ + 1, new TriggerUpdates( dstWorld ) );
|
||||
this.transverseEdges(srcX, srcY, srcZ, srcX + scaleX, srcY + scaleY, srcZ + scaleZ,
|
||||
new TriggerUpdates(srcWorld));
|
||||
this.transverseEdges(dstX, dstY, dstZ, dstX + scaleX, dstY + scaleY, dstZ + scaleZ,
|
||||
new TriggerUpdates(dstWorld));
|
||||
}
|
||||
|
||||
this.transverseEdges( srcX, srcY, srcZ, srcX + scaleX, srcY + scaleY, srcZ + scaleZ, new TriggerUpdates( srcWorld ) );
|
||||
this.transverseEdges( dstX, dstY, dstZ, dstX + scaleX, dstY + scaleY, dstZ + scaleZ, new TriggerUpdates( dstWorld ) );
|
||||
}
|
||||
private static class TriggerUpdates implements ISpatialVisitor {
|
||||
|
||||
private static class TriggerUpdates implements ISpatialVisitor
|
||||
{
|
||||
private final World dst;
|
||||
|
||||
private final World dst;
|
||||
public TriggerUpdates(final World dst2) {
|
||||
this.dst = dst2;
|
||||
}
|
||||
|
||||
public TriggerUpdates( final World dst2 )
|
||||
{
|
||||
this.dst = dst2;
|
||||
}
|
||||
@Override
|
||||
public void visit(final BlockPos pos) {
|
||||
final BlockState state = this.dst.getBlockState(pos);
|
||||
final Block blk = state.getBlock();
|
||||
blk.neighborChanged(state, this.dst, pos, blk, pos, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit( final BlockPos pos )
|
||||
{
|
||||
final BlockState state = this.dst.getBlockState( pos );
|
||||
final Block blk = state.getBlock();
|
||||
blk.neighborChanged( state, this.dst, pos, blk, pos, false );
|
||||
}
|
||||
}
|
||||
private static class WrapInMatrixFrame implements ISpatialVisitor {
|
||||
|
||||
private static class WrapInMatrixFrame implements ISpatialVisitor
|
||||
{
|
||||
private final World dst;
|
||||
private final BlockState state;
|
||||
|
||||
private final World dst;
|
||||
private final BlockState state;
|
||||
public WrapInMatrixFrame(final BlockState state, final World dst2) {
|
||||
this.dst = dst2;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public WrapInMatrixFrame( final BlockState state, final World dst2 )
|
||||
{
|
||||
this.dst = dst2;
|
||||
this.state = state;
|
||||
}
|
||||
@Override
|
||||
public void visit(final BlockPos pos) {
|
||||
this.dst.setBlockState(pos, this.state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit( final BlockPos pos )
|
||||
{
|
||||
this.dst.setBlockState( pos, this.state );
|
||||
}
|
||||
}
|
||||
private static class TelDestination {
|
||||
private final World dim;
|
||||
private final double x;
|
||||
private final double y;
|
||||
private final double z;
|
||||
|
||||
private static class TelDestination
|
||||
{
|
||||
private final World dim;
|
||||
private final double x;
|
||||
private final double y;
|
||||
private final double z;
|
||||
TelDestination(final World dimension, final AxisAlignedBB srcBox, final double x, final double y,
|
||||
final double z, final int tileX, final int tileY, final int tileZ) {
|
||||
this.dim = dimension;
|
||||
this.x = Math.min(srcBox.maxX - 0.5, Math.max(srcBox.minX + 0.5, x + tileX));
|
||||
this.y = Math.min(srcBox.maxY - 0.5, Math.max(srcBox.minY + 0.5, y + tileY));
|
||||
this.z = Math.min(srcBox.maxZ - 0.5, Math.max(srcBox.minZ + 0.5, z + tileZ));
|
||||
}
|
||||
}
|
||||
|
||||
TelDestination( final World dimension, final AxisAlignedBB srcBox, final double x, final double y, final double z, final int tileX, final int tileY, final int tileZ )
|
||||
{
|
||||
this.dim = dimension;
|
||||
this.x = Math.min( srcBox.maxX - 0.5, Math.max( srcBox.minX + 0.5, x + tileX ) );
|
||||
this.y = Math.min( srcBox.maxY - 0.5, Math.max( srcBox.minY + 0.5, y + tileY ) );
|
||||
this.z = Math.min( srcBox.maxZ - 0.5, Math.max( srcBox.minZ + 0.5, z + tileZ ) );
|
||||
}
|
||||
}
|
||||
private static class METeleporter implements ITeleporter {
|
||||
|
||||
private static class METeleporter implements ITeleporter
|
||||
{
|
||||
private final TelDestination destination;
|
||||
|
||||
private final TelDestination destination;
|
||||
METeleporter(final TelDestination d) {
|
||||
this.destination = d;
|
||||
}
|
||||
|
||||
METeleporter( final TelDestination d )
|
||||
{
|
||||
this.destination = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity placeEntity(Entity entity, ServerWorld currentWorld, ServerWorld destWorld, float yaw, Function<Boolean, Entity> repositionEntity) {
|
||||
Entity newEntity = repositionEntity.apply(false);
|
||||
newEntity.rotationYaw = yaw;
|
||||
newEntity.setPositionAndUpdate( this.destination.x, this.destination.y, this.destination.z );
|
||||
newEntity.setMotion(0, 0, 0);
|
||||
return newEntity;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Entity placeEntity(Entity entity, ServerWorld currentWorld, ServerWorld destWorld, float yaw,
|
||||
Function<Boolean, Entity> repositionEntity) {
|
||||
Entity newEntity = repositionEntity.apply(false);
|
||||
newEntity.rotationYaw = yaw;
|
||||
newEntity.setPositionAndUpdate(this.destination.x, this.destination.y, this.destination.z);
|
||||
newEntity.setMotion(0, 0, 0);
|
||||
return newEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user