2014-11-14 12:02:52 +01:00
/ *
* This file is part of Applied Energistics 2 .
2015-05-18 00:02:28 +02:00
* Copyright ( c ) 2013 - 2015 , AlgorithmX2 , All rights reserved .
2014-11-14 12:02:52 +01:00
*
* Applied Energistics 2 is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Applied Energistics 2 is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2 . If not , see < http : //www.gnu.org/licenses/lgpl>.
* /
2013-12-27 23:59:59 +01:00
package appeng.spatial ;
2015-04-03 08:54:31 +02:00
2014-03-05 08:27:42 +01:00
import java.lang.reflect.Method ;
2013-12-27 23:59:59 +01:00
import java.util.List ;
import net.minecraft.block.Block ;
2015-06-16 02:44:59 +02:00
import net.minecraft.block.state.IBlockState ;
2013-12-27 23:59:59 +01:00
import net.minecraft.entity.Entity ;
2014-07-26 04:35:48 +02:00
import net.minecraft.entity.EntityHanging ;
2013-12-27 23:59:59 +01:00
import net.minecraft.entity.EntityList ;
import net.minecraft.entity.player.EntityPlayerMP ;
import net.minecraft.util.AxisAlignedBB ;
2015-06-16 02:44:59 +02:00
import net.minecraft.util.BlockPos ;
2013-12-27 23:59:59 +01:00
import net.minecraft.util.MathHelper ;
import net.minecraft.world.Teleporter ;
import net.minecraft.world.World ;
import net.minecraft.world.WorldServer ;
import appeng.api.AEApi ;
import appeng.api.util.WorldCoord ;
2014-08-31 10:06:06 +02:00
import appeng.core.stats.Achievements ;
2014-02-09 02:34:52 +01:00
import appeng.util.Platform ;
2013-12-27 23:59:59 +01:00
2015-04-03 08:54:31 +02:00
2013-12-27 23:59:59 +01:00
public class StorageHelper
{
private static StorageHelper instance ;
2015-04-03 08:54:31 +02:00
Method onEntityRemoved ;
2013-12-27 23:59:59 +01:00
public static StorageHelper getInstance ( )
{
2015-04-03 08:54:31 +02:00
if ( instance = = null )
2015-04-29 02:30:53 +02:00
{
2013-12-27 23:59:59 +01:00
instance = new StorageHelper ( ) ;
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
return instance ;
}
/ * *
2014-09-21 01:37:12 +02:00
* Mostly from dimensional doors . . which mostly got it form X - Comp .
2015-02-03 12:04:13 +01:00
*
2014-09-27 23:17:47 +02:00
* @param entity to be teleported entity
2015-04-03 08:54:31 +02:00
* @param link destination
*
2014-09-27 23:17:47 +02:00
* @return teleported entity
2013-12-27 23:59:59 +01:00
* /
2015-09-30 14:24:40 +02:00
public Entity teleportEntity ( Entity entity , final TelDestination link )
2013-12-27 23:59:59 +01:00
{
2015-09-30 14:24:40 +02:00
final WorldServer oldWorld ;
final WorldServer newWorld ;
final EntityPlayerMP player ;
2013-12-27 23:59:59 +01:00
try
{
oldWorld = ( WorldServer ) entity . worldObj ;
newWorld = ( WorldServer ) link . dim ;
2015-04-03 08:54:31 +02:00
player = ( entity instanceof EntityPlayerMP ) ? ( EntityPlayerMP ) entity : null ;
2013-12-27 23:59:59 +01:00
}
2015-09-30 14:24:40 +02:00
catch ( final Throwable e )
2013-12-27 23:59:59 +01:00
{
return entity ;
}
2015-04-03 08:54:31 +02:00
if ( oldWorld = = null )
2015-04-29 02:30:53 +02:00
{
2013-12-27 23:59:59 +01:00
return entity ;
2015-04-29 02:30:53 +02:00
}
2015-04-03 08:54:31 +02:00
if ( newWorld = = null )
2015-04-29 02:30:53 +02:00
{
2013-12-27 23:59:59 +01:00
return entity ;
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
// Is something riding? Handle it first.
2015-04-03 08:54:31 +02:00
if ( entity . riddenByEntity ! = null )
2013-12-27 23:59:59 +01:00
{
2014-12-29 15:13:47 +01:00
return this . teleportEntity ( entity . riddenByEntity , link ) ;
2013-12-27 23:59:59 +01:00
}
// Are we riding something? Dismount and tell the mount to go first.
Entity cart = entity . ridingEntity ;
2015-04-03 08:54:31 +02:00
if ( cart ! = null )
2013-12-27 23:59:59 +01:00
{
entity . mountEntity ( null ) ;
2014-12-29 15:13:47 +01:00
cart = this . teleportEntity ( cart , link ) ;
2013-12-27 23:59:59 +01:00
// We keep track of both so we can remount them on the other side.
}
2014-07-26 04:35:48 +02:00
// load the chunk!
2015-06-16 02:44:59 +02:00
WorldServer . class . cast ( newWorld ) . getChunkProvider ( ) . provideChunk ( MathHelper . floor_double ( link . x ) > > 4 , MathHelper . floor_double ( link . z ) > > 4 ) ;
2014-07-26 04:35:48 +02:00
2015-09-30 14:24:40 +02:00
final boolean diffDestination = newWorld ! = oldWorld ;
2015-04-03 08:54:31 +02:00
if ( diffDestination )
2013-12-27 23:59:59 +01:00
{
2015-04-03 08:54:31 +02:00
if ( player ! = null )
2013-12-27 23:59:59 +01:00
{
2015-04-03 08:54:31 +02:00
if ( link . dim . provider instanceof StorageWorldProvider )
2015-04-29 02:30:53 +02:00
{
2014-09-20 23:20:43 +02:00
Achievements . SpatialIOExplorer . addToPlayer ( player ) ;
2015-04-29 02:30:53 +02:00
}
2014-08-31 10:06:06 +02:00
2015-06-16 02:44:59 +02:00
player . mcServer . getConfigurationManager ( ) . transferPlayerToDimension ( player , link . dim . provider . getDimensionId ( ) , new METeleporter ( newWorld , link ) ) ;
2013-12-27 23:59:59 +01:00
}
else
{
2015-09-30 14:24:40 +02:00
final int entX = entity . chunkCoordX ;
final int entZ = entity . chunkCoordZ ;
2014-07-26 04:35:48 +02:00
2015-04-03 08:54:31 +02:00
if ( ( entity . addedToChunk ) & & ( oldWorld . getChunkProvider ( ) . chunkExists ( entX , entZ ) ) )
2013-12-27 23:59:59 +01:00
{
oldWorld . getChunkFromChunkCoords ( entX , entZ ) . removeEntity ( entity ) ;
2015-06-16 02:44:59 +02:00
oldWorld . getChunkFromChunkCoords ( entX , entZ ) . setModified ( true ) ;
2013-12-27 23:59:59 +01:00
}
2015-09-30 14:24:40 +02:00
final Entity newEntity = EntityList . createEntityByName ( EntityList . getEntityString ( entity ) , newWorld ) ;
2015-04-03 08:54:31 +02:00
if ( newEntity ! = null )
2014-03-05 08:27:42 +01:00
{
2014-07-26 04:35:48 +02:00
entity . lastTickPosX = entity . prevPosX = entity . posX = link . x ;
entity . lastTickPosY = entity . prevPosY = entity . posY = link . y ;
entity . lastTickPosZ = entity . prevPosZ = entity . posZ = link . z ;
2014-03-05 08:27:42 +01:00
2015-04-03 08:54:31 +02:00
if ( entity instanceof EntityHanging )
2014-03-05 08:27:42 +01:00
{
2015-09-30 14:24:40 +02:00
final EntityHanging h = ( EntityHanging ) entity ;
2015-06-16 02:44:59 +02:00
h . setPosition ( link . x , link . y , link . z ) ; // TODO: VERIFIY THIS WORKS
2014-03-05 08:27:42 +01:00
}
2013-12-27 23:59:59 +01:00
2015-06-16 02:44:59 +02:00
newEntity . copyDataFromOld ( entity ) ;
newEntity . dimension = newWorld . provider . getDimensionId ( ) ;
2014-07-26 04:35:48 +02:00
newEntity . forceSpawn = true ;
2013-12-27 23:59:59 +01:00
entity . isDead = true ;
2014-07-26 04:35:48 +02:00
entity = newEntity ;
2013-12-27 23:59:59 +01:00
}
2014-07-26 04:35:48 +02:00
else
2015-04-29 02:30:53 +02:00
{
2014-07-26 04:35:48 +02:00
return null ;
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
2014-07-26 04:35:48 +02:00
// myChunk.addEntity( entity );
// newWorld.loadedEntityList.add( entity );
// newWorld.onEntityAdded( entity );
2013-12-27 23:59:59 +01:00
newWorld . spawnEntityInWorld ( entity ) ;
}
}
entity . worldObj . updateEntityWithOptionalForce ( entity , false ) ;
2015-04-03 08:54:31 +02:00
if ( cart ! = null )
2013-12-27 23:59:59 +01:00
{
2015-04-03 08:54:31 +02:00
if ( player ! = null )
2015-04-29 02:30:53 +02:00
{
2013-12-27 23:59:59 +01:00
entity . worldObj . updateEntityWithOptionalForce ( entity , true ) ;
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
entity . mountEntity ( cart ) ;
}
return entity ;
}
2015-09-30 14:24:40 +02:00
public void transverseEdges ( final int minX , final int minY , final int minZ , final int maxX , final int maxY , final int maxZ , final ISpatialVisitor visitor )
2013-12-27 23:59:59 +01:00
{
2015-04-03 08:54:31 +02:00
for ( int y = minY ; y < maxY ; y + + )
2015-04-29 02:30:53 +02:00
{
2015-04-03 08:54:31 +02:00
for ( int z = minZ ; z < maxZ ; z + + )
2013-12-27 23:59:59 +01:00
{
2015-06-16 02:44:59 +02:00
visitor . visit ( new BlockPos ( minX , y , z ) ) ;
visitor . visit ( new BlockPos ( maxX , y , z ) ) ;
2013-12-27 23:59:59 +01:00
}
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
2015-04-03 08:54:31 +02:00
for ( int x = minX ; x < maxX ; x + + )
2015-04-29 02:30:53 +02:00
{
2015-04-03 08:54:31 +02:00
for ( int z = minZ ; z < maxZ ; z + + )
2013-12-27 23:59:59 +01:00
{
2015-06-16 02:44:59 +02:00
visitor . visit ( new BlockPos ( x , minY , z ) ) ;
visitor . visit ( new BlockPos ( x , maxY , z ) ) ;
2013-12-27 23:59:59 +01:00
}
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
2015-04-03 08:54:31 +02:00
for ( int x = minX ; x < maxX ; x + + )
2015-04-29 02:30:53 +02:00
{
2015-04-03 08:54:31 +02:00
for ( int y = minY ; y < maxY ; y + + )
2013-12-27 23:59:59 +01:00
{
2015-06-16 02:44:59 +02:00
visitor . visit ( new BlockPos ( x , y , minZ ) ) ;
visitor . visit ( new BlockPos ( x , y , maxZ ) ) ;
2013-12-27 23:59:59 +01:00
}
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
}
2015-09-30 14:24:40 +02:00
public void swapRegions ( final World src /** over world **/ , final World dst /** storage cell **/ , final int x , final int y , final int z , final int i , final int j , final int k , final int scaleX , final int scaleY , final int scaleZ )
2013-12-27 23:59:59 +01:00
{
2015-09-30 14:24:40 +02:00
for ( final Block matrixFrameBlock : AEApi . instance ( ) . definitions ( ) . blocks ( ) . matrixFrame ( ) . maybeBlock ( ) . asSet ( ) )
2015-01-03 02:53:14 +01:00
{
2015-06-16 02:44:59 +02:00
this . transverseEdges ( i - 1 , j - 1 , k - 1 , i + scaleX + 1 , j + scaleY + 1 , k + scaleZ + 1 , new WrapInMatrixFrame ( matrixFrameBlock . getDefaultState ( ) , dst ) ) ;
2015-01-03 02:53:14 +01:00
}
2013-12-27 23:59:59 +01:00
2015-09-30 14:24:40 +02:00
final AxisAlignedBB srcBox = AxisAlignedBB . fromBounds ( x , y , z , x + scaleX + 1 , y + scaleY + 1 , z + scaleZ + 1 ) ;
2013-12-27 23:59:59 +01:00
2015-09-30 14:24:40 +02:00
final AxisAlignedBB dstBox = AxisAlignedBB . fromBounds ( i , j , k , i + scaleX + 1 , j + scaleY + 1 , k + scaleZ + 1 ) ;
2013-12-27 23:59:59 +01:00
2015-09-30 14:24:40 +02:00
final CachedPlane cDst = new CachedPlane ( dst , i , j , k , i + scaleX , j + scaleY , k + scaleZ ) ;
final CachedPlane cSrc = new CachedPlane ( src , x , y , z , x + scaleX , y + scaleY , z + scaleZ ) ;
2013-12-27 23:59:59 +01:00
// do nearly all the work... swaps blocks, tiles, and block ticks
2015-05-18 00:02:28 +02:00
cSrc . swap ( cDst ) ;
2013-12-27 23:59:59 +01:00
2015-09-30 14:24:40 +02:00
final List < Entity > srcE = src . getEntitiesWithinAABB ( Entity . class , srcBox ) ;
final List < Entity > dstE = dst . getEntitiesWithinAABB ( Entity . class , dstBox ) ;
2013-12-27 23:59:59 +01:00
2015-09-30 14:24:40 +02:00
for ( final Entity e : dstE )
2013-12-27 23:59:59 +01:00
{
2014-12-29 15:13:47 +01:00
this . teleportEntity ( e , new TelDestination ( src , srcBox , e . posX , e . posY , e . posZ , - i + x , - j + y , - k + z ) ) ;
2013-12-27 23:59:59 +01:00
}
2015-09-30 14:24:40 +02:00
for ( final Entity e : srcE )
2013-12-27 23:59:59 +01:00
{
2014-12-29 15:13:47 +01:00
this . teleportEntity ( e , new TelDestination ( dst , dstBox , e . posX , e . posY , e . posZ , - x + i , - y + j , - z + k ) ) ;
2013-12-27 23:59:59 +01:00
}
2015-09-30 14:24:40 +02:00
for ( final WorldCoord wc : cDst . updates )
2015-04-29 02:30:53 +02:00
{
2015-06-16 02:44:59 +02:00
cSrc . world . notifyBlockOfStateChange ( wc . getPos ( ) , Platform . AIR_BLOCK ) ;
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
2015-09-30 14:24:40 +02:00
for ( final WorldCoord wc : cSrc . updates )
2015-04-29 02:30:53 +02:00
{
2015-06-16 02:44:59 +02:00
cSrc . world . notifyBlockOfStateChange ( wc . getPos ( ) , Platform . AIR_BLOCK ) ;
2015-04-29 02:30:53 +02:00
}
2013-12-27 23:59:59 +01:00
2014-12-29 15:13:47 +01:00
this . transverseEdges ( x - 1 , y - 1 , z - 1 , x + scaleX + 1 , y + scaleY + 1 , z + scaleZ + 1 , new TriggerUpdates ( src ) ) ;
this . transverseEdges ( i - 1 , j - 1 , k - 1 , i + scaleX + 1 , j + scaleY + 1 , k + scaleZ + 1 , new TriggerUpdates ( dst ) ) ;
2013-12-27 23:59:59 +01:00
2014-12-29 15:13:47 +01:00
this . transverseEdges ( x , y , z , x + scaleX , y + scaleY , z + scaleZ , new TriggerUpdates ( src ) ) ;
this . transverseEdges ( i , j , k , i + scaleX , j + scaleY , k + scaleZ , new TriggerUpdates ( dst ) ) ;
2013-12-27 23:59:59 +01:00
/ *
2014-11-04 12:32:33 +01:00
* IChunkProvider cp = destination . getChunkProvider ( ) ; if ( cp instanceof ChunkProviderServer ) { ChunkProviderServer
2014-02-09 02:34:52 +01:00
* srv = ( ChunkProviderServer ) cp ; srv . unloadAllChunks ( ) ; }
2015-02-03 12:04:13 +01:00
*
2013-12-27 23:59:59 +01:00
* cp . unloadQueuedChunks ( ) ;
* /
}
2015-04-03 08:54:31 +02:00
static class TriggerUpdates implements ISpatialVisitor
{
final World dst ;
2015-09-30 14:24:40 +02:00
public TriggerUpdates ( final World dst2 )
2015-04-03 08:54:31 +02:00
{
this . dst = dst2 ;
}
@Override
2015-09-30 14:24:40 +02:00
public void visit ( final BlockPos pos )
2015-04-03 08:54:31 +02:00
{
2015-09-30 14:24:40 +02:00
final Block blk = this . dst . getBlockState ( pos ) . getBlock ( ) ;
2015-06-16 02:44:59 +02:00
blk . onNeighborBlockChange ( this . dst , pos , Platform . AIR_BLOCK . getDefaultState ( ) , Platform . AIR_BLOCK ) ;
2015-04-03 08:54:31 +02:00
}
}
static class WrapInMatrixFrame implements ISpatialVisitor
{
final World dst ;
2015-06-16 02:44:59 +02:00
final IBlockState state ;
2015-04-03 08:54:31 +02:00
2015-09-30 14:24:40 +02:00
public WrapInMatrixFrame ( final IBlockState state , final World dst2 )
2015-04-03 08:54:31 +02:00
{
this . dst = dst2 ;
2015-06-16 02:44:59 +02:00
this . state = state ;
2015-04-03 08:54:31 +02:00
}
@Override
2015-09-30 14:24:40 +02:00
public void visit ( final BlockPos pos )
2015-04-03 08:54:31 +02:00
{
2015-09-30 14:26:54 +02:00
this . dst . setBlockState ( pos , this . state ) ;
2015-04-03 08:54:31 +02:00
}
}
static class TelDestination
{
final World dim ;
final double x ;
final double y ;
final double z ;
final int xOff ;
final int yOff ;
final int zOff ;
2015-09-30 14:24:40 +02:00
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 )
2015-04-03 08:54:31 +02:00
{
2015-05-08 23:25:19 +02:00
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 ) ) ;
2015-04-03 08:54:31 +02:00
this . xOff = tileX ;
this . yOff = tileY ;
this . zOff = tileZ ;
}
}
static class METeleporter extends Teleporter
{
final TelDestination destination ;
2015-09-30 14:24:40 +02:00
public METeleporter ( final WorldServer par1WorldServer , final TelDestination d )
2015-04-03 08:54:31 +02:00
{
super ( par1WorldServer ) ;
this . destination = d ;
}
@Override
2015-06-16 02:44:59 +02:00
public void placeInPortal (
2015-09-30 14:24:40 +02:00
final Entity par1Entity ,
final float rotationYaw )
2015-04-03 08:54:31 +02:00
{
par1Entity . setLocationAndAngles ( this . destination . x , this . destination . y , this . destination . z , par1Entity . rotationYaw , 0 . 0F ) ;
par1Entity . motionX = par1Entity . motionY = par1Entity . motionZ = 0 . 0D ;
}
@Override
2015-06-16 02:44:59 +02:00
public boolean placeInExistingPortal (
2015-09-30 14:24:40 +02:00
final Entity entityIn ,
final float p_180620_2_ )
2015-04-03 08:54:31 +02:00
{
return false ;
}
@Override
2015-09-30 14:24:40 +02:00
public boolean makePortal ( final Entity par1Entity )
2015-04-03 08:54:31 +02:00
{
return false ;
}
@Override
2015-09-30 14:24:40 +02:00
public void removeStalePortalLocations ( final long par1 )
2015-04-03 08:54:31 +02:00
{
}
}
2013-12-27 23:59:59 +01:00
}