Spatial rework (#3048)

* Moved all spatial cells into a single dimension instead of one dimension per cell

Each cell will now be backed by a single region file each. So  backups and restores can still be done on a per cell level.

Old cells will not be migrated.

* Moved custom cell tracking to a capability based one on the world

The size and owner of a cell is now stored inside the capabilities of the world/dimension not a custom system and we can rely on forge handling the persistence of it.

* Added the cell id to the actual item tooltip, as this is now a real identifier and not an arbitrary dimension id.

* Added vanilla banners to the whitelist

* Added unittests to the dimension manager to ensure the algorithm mapping to the correct region file

* Updated the API to conform with the new dimenion/types/biomes registration and mappings

* Fixed a couple of bugs related to world/dimension/biome registration 

* Fixed a bug when transfering certain blocks due to passing missing/incorrect blockstate
This commit is contained in:
fscan
2017-08-24 11:24:33 +02:00
committed by yueh
parent 1513ba3f6a
commit bbf4d4a9ce
21 changed files with 615 additions and 427 deletions
@@ -29,6 +29,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.world.World; import net.minecraft.world.World;
import appeng.api.implementations.TransitionResult; import appeng.api.implementations.TransitionResult;
import appeng.api.storage.ISpatialDimension;
import appeng.api.util.WorldCoord; import appeng.api.util.WorldCoord;
@@ -57,7 +58,7 @@ public interface ISpatialStorageCell
* *
* @return the world for this cell * @return the world for this cell
*/ */
World getWorld( ItemStack is ); ISpatialDimension getSpatialDimension();
/** /**
* get the currently stored size. * get the currently stored size.
@@ -69,22 +70,13 @@ public interface ISpatialStorageCell
WorldCoord getStoredSize( ItemStack is ); WorldCoord getStoredSize( ItemStack is );
/** /**
* Minimum coordinates in its world for the storage cell. * get the currently stored Dimension id.
* *
* @param is spatial storage cell * @param is spatial storage cell
* *
* @return minimum coordinate of dimension * @return dimension id or -1
*/ */
WorldCoord getMin( ItemStack is ); int getStoredDimensionID( ItemStack is );
/**
* Maximum coordinates in its world for the storage cell.
*
* @param is spatial storage cell
*
* @return maximum coordinate of dimension
*/
WorldCoord getMax( ItemStack is );
/** /**
* Perform a spatial swap with the contents of the cell, and the world. * Perform a spatial swap with the contents of the cell, and the world.
@@ -93,9 +85,9 @@ public interface ISpatialStorageCell
* @param w world of spatial * @param w world of spatial
* @param min min coord * @param min min coord
* @param max max coord * @param max max coord
* @param doTransition transition * @param playerId owner of current grid or -1
* *
* @return result of transition * @return result of transition
*/ */
TransitionResult doSpatialTransition( ItemStack is, World w, WorldCoord min, WorldCoord max, boolean doTransition ); TransitionResult doSpatialTransition( ItemStack is, World w, WorldCoord min, WorldCoord max, int playerId );
} }
@@ -0,0 +1,41 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* 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>.
*/
package appeng.api.storage;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public interface ISpatialDimension
{
World getWorld();
int createNewCellDimension( BlockPos contentSize, int playerId );
void deleteCellDimension( int cellDimId );
boolean isCellDimension( int cellDimID );
int getCellDimensionOwner( int cellDimId );
BlockPos getCellDimensionOrigin( int cellDimId );
BlockPos getCellContentSize( int cellDimId );
}
@@ -28,6 +28,7 @@ import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.energy.IEnergyStorage;
import appeng.api.storage.ISpatialDimension;
import appeng.api.storage.IStorageMonitorableAccessor; import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.integration.IntegrationRegistry; import appeng.integration.IntegrationRegistry;
import appeng.integration.IntegrationType; import appeng.integration.IntegrationType;
@@ -45,6 +46,8 @@ public final class Capabilities
public static Capability<IStorageMonitorableAccessor> STORAGE_MONITORABLE_ACCESSOR; public static Capability<IStorageMonitorableAccessor> STORAGE_MONITORABLE_ACCESSOR;
public static Capability<ISpatialDimension> SPATIAL_DIMENSION;
public static Capability<ITeslaConsumer> TESLA_CONSUMER; public static Capability<ITeslaConsumer> TESLA_CONSUMER;
public static Capability<ITeslaHolder> TESLA_HOLDER; public static Capability<ITeslaHolder> TESLA_HOLDER;
@@ -57,6 +60,7 @@ public final class Capabilities
public static void register() public static void register()
{ {
CapabilityManager.INSTANCE.register( IStorageMonitorableAccessor.class, createNullStorage(), NullMENetworkAccessor::new ); CapabilityManager.INSTANCE.register( IStorageMonitorableAccessor.class, createNullStorage(), NullMENetworkAccessor::new );
CapabilityManager.INSTANCE.register( ISpatialDimension.class, createNullStorage(), NullSpatialDimension::new );
} }
@CapabilityInject( IStorageMonitorableAccessor.class ) @CapabilityInject( IStorageMonitorableAccessor.class )
@@ -65,6 +69,12 @@ public final class Capabilities
STORAGE_MONITORABLE_ACCESSOR = cap; STORAGE_MONITORABLE_ACCESSOR = cap;
} }
@CapabilityInject( ISpatialDimension.class )
private static void capISpatialDimensionRegistered( Capability<ISpatialDimension> cap )
{
SPATIAL_DIMENSION = cap;
}
@CapabilityInject( ITeslaConsumer.class ) @CapabilityInject( ITeslaConsumer.class )
private static void capITeslaConsumerRegistered( Capability<ITeslaConsumer> cap ) private static void capITeslaConsumerRegistered( Capability<ITeslaConsumer> cap )
{ {
@@ -0,0 +1,70 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* 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>.
*/
package appeng.capabilities;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.storage.ISpatialDimension;
class NullSpatialDimension implements ISpatialDimension
{
@Override
public int createNewCellDimension( BlockPos size, int owner )
{
return -1;
}
@Override
public void deleteCellDimension( int cellStorageId )
{
}
@Override
public int getCellDimensionOwner( int cellStorageId )
{
return -1;
}
@Override
public BlockPos getCellDimensionOrigin( int cellStorageId )
{
return null;
}
@Override
public World getWorld()
{
return null;
}
@Override
public boolean isCellDimension( int cellDimID )
{
return false;
}
@Override
public BlockPos getCellContentSize( int cellDimId )
{
return null;
}
}
+13 -13
View File
@@ -95,8 +95,8 @@ public final class AEConfig extends Configuration implements IConfigurableObject
private final int[] levelByStacks = { 1, 10, 100, 1000 }; private final int[] levelByStacks = { 1, 10, 100, 1000 };
// Spatial IO/Dimension // Spatial IO/Dimension
private int storageBiomeID = -1;
private int storageProviderID = -1; private int storageProviderID = -1;
private int storageDimensionID = -1;
private double spatialPowerExponent = 1.35; private double spatialPowerExponent = 1.35;
private double spatialPowerMultiplier = 1250.0; private double spatialPowerMultiplier = 1250.0;
@@ -251,8 +251,8 @@ public final class AEConfig extends Configuration implements IConfigurableObject
if( this.isFeatureEnabled( AEFeature.SPATIAL_IO ) ) if( this.isFeatureEnabled( AEFeature.SPATIAL_IO ) )
{ {
this.storageBiomeID = this.get( "spatialio", "storageBiomeID", this.storageBiomeID ).getInt( this.storageBiomeID );
this.storageProviderID = this.get( "spatialio", "storageProviderID", this.storageProviderID ).getInt( this.storageProviderID ); this.storageProviderID = this.get( "spatialio", "storageProviderID", this.storageProviderID ).getInt( this.storageProviderID );
this.storageDimensionID = this.get( "spatialio", "storageDimensionID", this.storageDimensionID ).getInt( this.storageDimensionID );
this.spatialPowerMultiplier = this.get( "spatialio", "spatialPowerMultiplier", this.spatialPowerMultiplier ).getDouble( this.spatialPowerMultiplier = this.get( "spatialio", "spatialPowerMultiplier", this.spatialPowerMultiplier ).getDouble(
this.spatialPowerMultiplier ); this.spatialPowerMultiplier );
this.spatialPowerExponent = this.get( "spatialio", "spatialPowerExponent", this.spatialPowerExponent ).getDouble( this.spatialPowerExponent ); this.spatialPowerExponent = this.get( "spatialio", "spatialPowerExponent", this.spatialPowerExponent ).getDouble( this.spatialPowerExponent );
@@ -397,8 +397,8 @@ public final class AEConfig extends Configuration implements IConfigurableObject
{ {
if( this.isFeatureEnabled( AEFeature.SPATIAL_IO ) ) if( this.isFeatureEnabled( AEFeature.SPATIAL_IO ) )
{ {
this.get( "spatialio", "storageBiomeID", this.storageBiomeID ).set( this.storageBiomeID );
this.get( "spatialio", "storageProviderID", this.storageProviderID ).set( this.storageProviderID ); this.get( "spatialio", "storageProviderID", this.storageProviderID ).set( this.storageProviderID );
this.get( "spatialio", "storageDimensionID", this.storageDimensionID ).set( this.storageDimensionID );
} }
this.get( "Client", "PowerUnit", this.selectedPowerUnit.name(), this.getListComment( this.selectedPowerUnit ) ).set( this.selectedPowerUnit.name() ); this.get( "Client", "PowerUnit", this.selectedPowerUnit.name(), this.getListComment( this.selectedPowerUnit ) ).set( this.selectedPowerUnit.name() );
@@ -619,16 +619,16 @@ public final class AEConfig extends Configuration implements IConfigurableObject
return this.levelByStacks; return this.levelByStacks;
} }
public int getStorageBiomeID()
{
return this.storageBiomeID;
}
public int getStorageProviderID() public int getStorageProviderID()
{ {
return this.storageProviderID; return this.storageProviderID;
} }
public int getStorageDimensionID()
{
return this.storageDimensionID;
}
public double getSpatialPowerExponent() public double getSpatialPowerExponent()
{ {
return this.spatialPowerExponent; return this.spatialPowerExponent;
@@ -766,13 +766,13 @@ public final class AEConfig extends Configuration implements IConfigurableObject
// Setters keep visibility as low as possible. // Setters keep visibility as low as possible.
void setStorageBiomeID( int id )
{
this.storageBiomeID = id;
}
void setStorageProviderID( int id ) void setStorageProviderID( int id )
{ {
this.storageProviderID = id; this.storageProviderID = id;
} }
void setStorageDimensionID( int id )
{
this.storageDimensionID = id;
}
} }
+5
View File
@@ -136,6 +136,11 @@ public final class AppEng
return this.registration.storageDimensionType; return this.registration.storageDimensionType;
} }
public int getStorageDimensionID()
{
return this.registration.storageDimensionID;
}
@EventHandler @EventHandler
private void preInit( final FMLPreInitializationEvent event ) private void preInit( final FMLPreInitializationEvent event )
{ {
+48 -24
View File
@@ -35,10 +35,13 @@ import net.minecraft.item.Item;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.DimensionType; import net.minecraft.world.DimensionType;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLInitializationEvent;
@@ -86,10 +89,8 @@ import appeng.core.features.registries.cell.CreativeCellHandler;
import appeng.core.localization.GuiText; import appeng.core.localization.GuiText;
import appeng.core.localization.PlayerMessages; import appeng.core.localization.PlayerMessages;
import appeng.core.stats.PlayerStatsRegistration; import appeng.core.stats.PlayerStatsRegistration;
import appeng.core.worlddata.SpatialDimensionManager;
import appeng.hooks.TickHandler; import appeng.hooks.TickHandler;
import appeng.integration.IntegrationRegistry;
import appeng.integration.IntegrationType;
import appeng.integration.Integrations;
import appeng.items.materials.ItemMaterial; import appeng.items.materials.ItemMaterial;
import appeng.items.parts.ItemFacade; import appeng.items.parts.ItemFacade;
import appeng.loot.ChestLoot; import appeng.loot.ChestLoot;
@@ -128,6 +129,7 @@ import appeng.worldgen.QuartzWorldGen;
final class Registration final class Registration
{ {
DimensionType storageDimensionType; DimensionType storageDimensionType;
int storageDimensionID;
Biome storageBiome; Biome storageBiome;
private File recipeDirectory; private File recipeDirectory;
@@ -159,28 +161,29 @@ final class Registration
definitions.getRegistry().getBootstrapComponents( IPreInitComponent.class ).forEachRemaining( b -> b.preInitialize( event.getSide() ) ); definitions.getRegistry().getBootstrapComponents( IPreInitComponent.class ).forEachRemaining( b -> b.preInitialize( event.getSide() ) );
} }
private void registerSpatial( final boolean force, IForgeRegistry<Biome> registry ) private void registerSpatialBiome( IForgeRegistry<Biome> registry )
{ {
if( !AEConfig.instance().isFeatureEnabled( AEFeature.SPATIAL_IO ) ) if( !AEConfig.instance().isFeatureEnabled( AEFeature.SPATIAL_IO ) )
{ {
return; return;
} }
final AEConfig config = AEConfig.instance();
if( this.storageBiome == null ) if( this.storageBiome == null )
{ {
this.storageBiome = new BiomeGenStorage(); this.storageBiome = new BiomeGenStorage();
} }
registry.register( this.storageBiome.setRegistryName( "appliedenergistics2:storage_biome" ) ); registry.register( this.storageBiome.setRegistryName( "appliedenergistics2:storage_biome" ) );
}
if( config.getStorageProviderID() != -1 ) private void registerSpatialDimension()
{
final AEConfig config = AEConfig.instance();
if( !config.isFeatureEnabled( AEFeature.SPATIAL_IO ) )
{ {
this.storageDimensionType = DimensionType.register( "Storage Cell", "_cell", config.getStorageProviderID(), StorageWorldProvider.class, false ); return;
} }
if( config.getStorageProviderID() == -1 && force ) if( config.getStorageProviderID() == -1 )
{ {
final Set<Integer> ids = new HashSet<>(); final Set<Integer> ids = new HashSet<>();
for( DimensionType type : DimensionType.values() ) for( DimensionType type : DimensionType.values() )
@@ -188,17 +191,25 @@ final class Registration
ids.add( type.getId() ); ids.add( type.getId() );
} }
config.setStorageProviderID( -11 ); int newId = -11;
while( ids.contains( newId ) )
while( ids.contains( config.getStorageProviderID() ) )
{ {
config.setStorageProviderID( config.getStorageProviderID() - 1 ); --newId;
} }
config.setStorageProviderID( newId );
this.storageDimensionType = DimensionType.register( "Storage Cell", "_cell", config.getStorageProviderID(), StorageWorldProvider.class, false );
config.save(); config.save();
} }
this.storageDimensionType = DimensionType.register( "Storage Cell", "_cell", config.getStorageProviderID(), StorageWorldProvider.class, true );
if( config.getStorageDimensionID() == -1 )
{
config.setStorageDimensionID( DimensionManager.getNextFreeDimId() );
config.save();
}
this.storageDimensionID = config.getStorageDimensionID();
DimensionManager.registerDimension( this.storageDimensionID, this.storageDimensionType );
} }
private void registerCraftHandlers( final IRecipeHandlerRegistry registry ) private void registerCraftHandlers( final IRecipeHandlerRegistry registry )
@@ -284,7 +295,7 @@ final class Registration
public void registerBiomes( RegistryEvent.Register<Biome> event ) public void registerBiomes( RegistryEvent.Register<Biome> event )
{ {
final IForgeRegistry<Biome> registry = event.getRegistry(); final IForgeRegistry<Biome> registry = event.getRegistry();
this.registerSpatial( false, registry ); this.registerSpatialBiome( registry );
} }
@SubscribeEvent @SubscribeEvent
@@ -355,6 +366,16 @@ final class Registration
recipeHandler.injectRecipes(); recipeHandler.injectRecipes();
} }
@SubscribeEvent
public void attachSpatialDimensionManager( AttachCapabilitiesEvent<World> event )
{
if( AEConfig.instance()
.isFeatureEnabled( AEFeature.SPATIAL_IO ) && event.getObject() == DimensionManager.getWorld( AEConfig.instance().getStorageDimensionID() ) )
{
event.addCapability( new ResourceLocation( "appliedenergistics2:spatial_dimension_manager" ), new SpatialDimensionManager( event.getObject() ) );
}
}
void postInit( final FMLPostInitializationEvent event ) void postInit( final FMLPostInitializationEvent event )
{ {
final IRegistryContainer registries = Api.INSTANCE.registries(); final IRegistryContainer registries = Api.INSTANCE.registries();
@@ -363,6 +384,8 @@ final class Registration
final IBlocks blocks = definitions.blocks(); final IBlocks blocks = definitions.blocks();
final IItems items = definitions.items(); final IItems items = definitions.items();
registerSpatialDimension();
// default settings.. // default settings..
( (P2PTunnelRegistry) registries.p2pTunnel() ).configure(); ( (P2PTunnelRegistry) registries.p2pTunnel() ).configure();
@@ -469,6 +492,7 @@ final class Registration
/* /*
* White List Vanilla... * White List Vanilla...
*/ */
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityBanner.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityBeacon.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityBeacon.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityBrewingStand.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityBrewingStand.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityChest.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityChest.class );
@@ -480,15 +504,15 @@ final class Registration
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityEnchantmentTable.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityEnchantmentTable.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityEnderChest.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityEnderChest.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityEndPortal.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityEndPortal.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntitySkull.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityFurnace.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityMobSpawner.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntitySign.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityPiston.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityFlowerPot.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityFlowerPot.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityNote.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityFurnace.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityHopper.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityHopper.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityMobSpawner.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityNote.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityPiston.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityShulkerBox.class ); mr.whiteListTileEntity( net.minecraft.tileentity.TileEntityShulkerBox.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntitySign.class );
mr.whiteListTileEntity( net.minecraft.tileentity.TileEntitySkull.class );
/* /*
* Whitelist AE2 * Whitelist AE2
@@ -92,7 +92,10 @@ public enum GuiText
FETunnel, FETunnel,
PressureTunnel, PressureTunnel,
// spatial
StoredSize, StoredSize,
CellId,
CopyMode, CopyMode,
CopyModeDesc, CopyModeDesc,
PatternTerminal, PatternTerminal,
@@ -39,7 +39,6 @@ import appeng.core.sync.packets.PacketLightning;
import appeng.core.sync.packets.PacketMEInventoryUpdate; import appeng.core.sync.packets.PacketMEInventoryUpdate;
import appeng.core.sync.packets.PacketMatterCannon; import appeng.core.sync.packets.PacketMatterCannon;
import appeng.core.sync.packets.PacketMockExplosion; import appeng.core.sync.packets.PacketMockExplosion;
import appeng.core.sync.packets.PacketNewStorageDimension;
import appeng.core.sync.packets.PacketPaintedEntity; import appeng.core.sync.packets.PacketPaintedEntity;
import appeng.core.sync.packets.PacketPartPlacement; import appeng.core.sync.packets.PacketPartPlacement;
import appeng.core.sync.packets.PacketPartialItem; import appeng.core.sync.packets.PacketPartialItem;
@@ -83,8 +82,6 @@ public class AppEngPacketHandlerBase
PACKET_CLICK( PacketClick.class ), PACKET_CLICK( PacketClick.class ),
PACKET_NEW_STORAGE_DIMENSION( PacketNewStorageDimension.class ),
PACKET_SWITCH_GUIS( PacketSwitchGuis.class ), PACKET_SWITCH_GUIS( PacketSwitchGuis.class ),
PACKET_SWAP_SLOTS( PacketSwapSlots.class ), PACKET_SWAP_SLOTS( PacketSwapSlots.class ),
@@ -24,15 +24,12 @@ import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.ThreadQuickExitException; import net.minecraft.network.ThreadQuickExitException;
import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
import net.minecraftforge.fml.common.network.FMLEventChannel; import net.minecraftforge.fml.common.network.FMLEventChannel;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerConnectionFromClientEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.network.NetworkRegistry;
import appeng.core.sync.AppEngPacket; import appeng.core.sync.AppEngPacket;
import appeng.core.worlddata.WorldData;
public class NetworkHandler public class NetworkHandler
@@ -89,21 +86,6 @@ public class NetworkHandler
} }
} }
@SubscribeEvent
public void newConnection( final ServerConnectionFromClientEvent ev )
{
WorldData.instance().dimensionData().sendToPlayer( ev.getManager() );
}
@SubscribeEvent
public void newConnection( final PlayerLoggedInEvent loginEvent )
{
if( loginEvent.player instanceof EntityPlayerMP )
{
WorldData.instance().dimensionData().sendToPlayer( null );
}
}
@SubscribeEvent @SubscribeEvent
public void serverPacket( final ServerCustomPacketEvent ev ) public void serverPacket( final ServerCustomPacketEvent ev )
{ {
@@ -1,72 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* 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>.
*/
package appeng.core.sync.packets;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import appeng.core.AppEng;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
public class PacketNewStorageDimension extends AppEngPacket
{
private final int newDim;
// automatic.
public PacketNewStorageDimension( final ByteBuf stream )
{
this.newDim = stream.readInt();
}
// api
public PacketNewStorageDimension( final int newDim )
{
this.newDim = newDim;
final ByteBuf data = Unpooled.buffer();
data.writeInt( this.getPacketID() );
data.writeInt( newDim );
this.configureWrite( data );
}
@Override
@SideOnly( Side.CLIENT )
public void clientPacketData( final INetworkInfo network, final AppEngPacket packet, final EntityPlayer player )
{
try
{
DimensionManager.registerDimension( this.newDim, AppEng.instance().getStorageDimensionType() );
}
catch( final IllegalArgumentException iae )
{
// ok!
}
}
}
@@ -1,171 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* 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>.
*/
package appeng.core.worlddata;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import net.minecraft.network.NetworkManager;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import appeng.api.util.WorldCoord;
import appeng.core.AppEng;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketNewStorageDimension;
import appeng.hooks.TickHandler;
/**
* @author thatsIch
* @version rv3 - 30.05.2015
* @since rv3 30.05.2015
*/
final class DimensionData implements IWorldDimensionData, IOnWorldStartable, IOnWorldStoppable
{
private static final String CONFIG_CATEGORY = "DimensionManager";
private static final String CONFIG_KEY = "StorageCells";
private static final int[] STORAGE_CELLS_DEFAULT = new int[0];
private static final String STORAGE_CELL_CATEGORY = "StorageCell";
private static final String STORAGE_CELL_SCALE_X_KEY = "scaleX";
private static final String STORAGE_CELL_SCALE_Y_KEY = "scaleY";
private static final String STORAGE_CELL_SCALE_Z_KEY = "scaleZ";
private static final String PACKAGE_DEST_CATEGORY = "DimensionManager";
private static final String PACKAGE_KEY_CATEGORY = "StorageCells";
private static final int[] PACKAGE_DEF_CATEGORY = new int[0];
private final Configuration config;
private final List<Integer> storageCellDimensionIDs;
DimensionData( @Nonnull final Configuration parentFile )
{
Preconditions.checkNotNull( parentFile );
this.config = parentFile;
final int[] storageCellIDs = this.storageCellIDsProperty().getIntList();
this.storageCellDimensionIDs = Lists.newArrayList();
for( final int storageCellID : storageCellIDs )
{
this.storageCellDimensionIDs.add( storageCellID );
}
}
private Property storageCellIDsProperty()
{
return this.config.get( CONFIG_CATEGORY, CONFIG_KEY, STORAGE_CELLS_DEFAULT );
}
@Override
public void onWorldStart()
{
for( final Integer storageCellDimID : this.storageCellDimensionIDs )
{
DimensionManager.registerDimension( storageCellDimID, AppEng.instance().getStorageDimensionType() );
}
this.config.save();
}
@Override
public void onWorldStop()
{
this.config.save();
for( final Integer storageCellDimID : this.storageCellDimensionIDs )
{
DimensionManager.unregisterDimension( storageCellDimID );
}
this.storageCellDimensionIDs.clear();
}
@Override
public void addStorageCell( final int newStorageCellID )
{
this.storageCellDimensionIDs.add( newStorageCellID );
DimensionManager.registerDimension( newStorageCellID, AppEng.instance().getStorageDimensionType() );
NetworkHandler.instance().sendToAll( new PacketNewStorageDimension( newStorageCellID ) );
final String[] values = new String[this.storageCellDimensionIDs.size()];
for( int x = 0; x < values.length; x++ )
{
values[x] = String.valueOf( this.storageCellDimensionIDs.get( x ) );
}
this.storageCellIDsProperty().set( values );
this.config.save();
}
@Override
public WorldCoord getStoredSize( final int dim )
{
final String category = STORAGE_CELL_CATEGORY + dim;
final int x = this.config.get( category, STORAGE_CELL_SCALE_X_KEY, 0 ).getInt();
final int y = this.config.get( category, STORAGE_CELL_SCALE_Y_KEY, 0 ).getInt();
final int z = this.config.get( category, STORAGE_CELL_SCALE_Z_KEY, 0 ).getInt();
return new WorldCoord( x, y, z );
}
@Override
public void setStoredSize( final int dim, final int targetX, final int targetY, final int targetZ )
{
final String category = STORAGE_CELL_CATEGORY + dim;
this.config.get( category, STORAGE_CELL_SCALE_X_KEY, 0 ).set( targetX );
this.config.get( category, STORAGE_CELL_SCALE_Y_KEY, 0 ).set( targetY );
this.config.get( category, STORAGE_CELL_SCALE_Z_KEY, 0 ).set( targetZ );
this.config.save();
}
@Override
public void sendToPlayer( @Nullable final NetworkManager manager )
{
if( manager != null )
{
for( final int newDim : this.config.get( PACKAGE_DEST_CATEGORY, PACKAGE_KEY_CATEGORY, PACKAGE_DEF_CATEGORY ).getIntList() )
{
manager.sendPacket( ( new PacketNewStorageDimension( newDim ) ).getProxy() );
}
}
else
{
for( final TickHandler.PlayerColor pc : TickHandler.INSTANCE.getPlayerColors().values() )
{
NetworkHandler.instance().sendToAll( pc.getPacket() );
}
}
}
}
@@ -39,9 +39,6 @@ public interface IWorldData
@Nonnull @Nonnull
IWorldPlayerData playerData(); IWorldPlayerData playerData();
@Nonnull
IWorldDimensionData dimensionData();
@Nonnull @Nonnull
IWorldCompassData compassData(); IWorldCompassData compassData();
@@ -0,0 +1,245 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* 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>.
*/
package appeng.core.worlddata;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.INBTSerializable;
import appeng.api.storage.ISpatialDimension;
import appeng.capabilities.Capabilities;
public class SpatialDimensionManager implements ISpatialDimension, ICapabilitySerializable<NBTTagCompound>
{
private static final String NBT_SPATIAL_DATA_KEY = "spatial_data";
private static final String NBT_SPATIAL_ID_KEY = "id";
private World world;
private Map<Integer, StorageCellData> spatialData = new HashMap<>();
private static final int MAX_CELL_DIMENSION = 512;
public SpatialDimensionManager( World world )
{
this.world = world;
}
@Override
public World getWorld()
{
return this.world;
}
@Override
public int createNewCellDimension( BlockPos contentSize, int owner )
{
int newId = this.getNextId();
StorageCellData data = new StorageCellData();
data.contentDimension = contentSize;
data.owner = owner;
this.spatialData.put( newId, data );
return newId;
}
@Override
public void deleteCellDimension( int cellStorageId )
{
StorageCellData removed = spatialData.remove( cellStorageId );
if( removed != null )
{
this.clearCellArea( cellStorageId, removed );
}
}
@Override
public boolean isCellDimension( int cellStorageId )
{
return this.spatialData.containsKey( cellStorageId );
}
@Override
public int getCellDimensionOwner( int cellStorageId )
{
StorageCellData cell = this.spatialData.get( cellStorageId );
if( cell != null )
{
return cell.owner;
}
return -1;
}
@Override
public BlockPos getCellDimensionOrigin( int cellStorageId )
{
if( this.isCellDimension( cellStorageId ) )
{
return getBlockPosFromId( cellStorageId );
}
return null;
}
@Override
public BlockPos getCellContentSize( int cellStorageId )
{
StorageCellData cell = this.spatialData.get( cellStorageId );
if( cell != null )
{
return cell.contentDimension;
}
return null;
}
@Override
public boolean hasCapability( Capability<?> capability, EnumFacing facing )
{
return capability == Capabilities.SPATIAL_DIMENSION;
}
@Override
public <T> T getCapability( Capability<T> capability, EnumFacing facing )
{
if( capability == Capabilities.SPATIAL_DIMENSION )
{
return (T) this;
}
return null;
}
@Override
public NBTTagCompound serializeNBT()
{
final NBTTagCompound ret = new NBTTagCompound();
final NBTTagList list = new NBTTagList();
for( Map.Entry<Integer, StorageCellData> entry : this.spatialData.entrySet() )
{
final NBTTagCompound nbt = entry.getValue().serializeNBT();
nbt.setInteger( NBT_SPATIAL_ID_KEY, entry.getKey() );
list.appendTag( nbt );
}
ret.setTag( NBT_SPATIAL_DATA_KEY, list );
return ret;
}
@Override
public void deserializeNBT( NBTTagCompound nbt )
{
if( nbt.hasKey( NBT_SPATIAL_DATA_KEY ) )
{
final NBTTagList list = (NBTTagList) nbt.getTag( NBT_SPATIAL_DATA_KEY );
this.spatialData.clear();
for( int i = 0; i < list.tagCount(); ++i )
{
final NBTTagCompound entry = list.getCompoundTagAt( i );
final StorageCellData data = new StorageCellData();
final int id = entry.getInteger( NBT_SPATIAL_ID_KEY );
data.deserializeNBT( entry );
this.spatialData.put( id, data );
}
}
}
private int getNextId()
{
return this.spatialData.keySet().stream().max( Integer::compare ).orElse( -1 ) + 1;
}
private BlockPos getBlockPosFromId( int id )
{
int signBits = id & 0b11;
int offsetBits = id >> 2;
int offsetScale = 1;
int posx = MAX_CELL_DIMENSION / 2;
int posz = MAX_CELL_DIMENSION / 2;
// find quadrant
while( offsetBits != 0 )
{
posx += MAX_CELL_DIMENSION * offsetScale * ( offsetBits & 0b01 );
posz += MAX_CELL_DIMENSION * offsetScale * ( offsetBits >> 1 & 0b01 );
offsetBits >>= 2;
offsetScale <<= 1;
}
// mirror in one of 4 directions
if( ( signBits & 0b01 ) == 0 )
{
posx *= -1;
}
if( ( signBits & 0b10 ) == 0 )
{
posz *= -1;
}
// offset from cell center
posx -= 64;
posz -= 64;
return new BlockPos( posx, 64, posz );
}
private void clearCellArea( int cellId, StorageCellData cell )
{
// TODO reset chunks?
}
private static class StorageCellData implements INBTSerializable<NBTTagCompound>
{
private static final String NBT_OWNER_KEY = "owner";
private static final String NBT_DIM_X_KEY = "dim_x";
private static final String NBT_DIM_Y_KEY = "dim_y";
private static final String NBT_DIM_Z_KEY = "dim_z";
public BlockPos contentDimension;
public int owner;
@Override
public NBTTagCompound serializeNBT()
{
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger( NBT_DIM_X_KEY, contentDimension.getX() );
nbt.setInteger( NBT_DIM_Y_KEY, contentDimension.getY() );
nbt.setInteger( NBT_DIM_Z_KEY, contentDimension.getZ() );
nbt.setInteger( NBT_OWNER_KEY, owner );
return nbt;
}
@Override
public void deserializeNBT( NBTTagCompound nbt )
{
contentDimension = new BlockPos( nbt.getInteger( NBT_DIM_X_KEY ), nbt.getInteger( NBT_DIM_Y_KEY ), nbt.getInteger( NBT_DIM_Z_KEY ) );
owner = nbt.getInteger( NBT_OWNER_KEY );
}
}
}
@@ -60,7 +60,6 @@ public final class WorldData implements IWorldData
private static IWorldData instance; private static IWorldData instance;
private final IWorldPlayerData playerData; private final IWorldPlayerData playerData;
private final IWorldDimensionData dimensionData;
private final IWorldGridStorageData storageData; private final IWorldGridStorageData storageData;
private final IWorldCompassData compassData; private final IWorldCompassData compassData;
private final IWorldSpawnData spawnData; private final IWorldSpawnData spawnData;
@@ -87,7 +86,6 @@ public final class WorldData implements IWorldData
this.sharedConfig = new Configuration( settingsFile, AEConfig.VERSION ); this.sharedConfig = new Configuration( settingsFile, AEConfig.VERSION );
final PlayerData playerData = new PlayerData( this.sharedConfig ); final PlayerData playerData = new PlayerData( this.sharedConfig );
final DimensionData dimensionData = new DimensionData( this.sharedConfig );
final StorageData storageData = new StorageData( this.sharedConfig ); final StorageData storageData = new StorageData( this.sharedConfig );
final ThreadFactory compassThreadFactory = new CompassThreadFactory(); final ThreadFactory compassThreadFactory = new CompassThreadFactory();
@@ -97,13 +95,12 @@ public final class WorldData implements IWorldData
final IWorldSpawnData spawnData = new SpawnData( this.spawnDirectory ); final IWorldSpawnData spawnData = new SpawnData( this.spawnDirectory );
this.playerData = playerData; this.playerData = playerData;
this.dimensionData = dimensionData;
this.storageData = storageData; this.storageData = storageData;
this.compassData = compassData; this.compassData = compassData;
this.spawnData = spawnData; this.spawnData = spawnData;
this.startables = Lists.<IOnWorldStartable>newArrayList( playerData, dimensionData, storageData ); this.startables = Lists.<IOnWorldStartable>newArrayList( playerData, storageData );
this.stoppables = Lists.<IOnWorldStoppable>newArrayList( playerData, dimensionData, storageData, compassData ); this.stoppables = Lists.<IOnWorldStoppable>newArrayList( playerData, storageData, compassData );
} }
/** /**
@@ -198,13 +195,6 @@ public final class WorldData implements IWorldData
return this.playerData; return this.playerData;
} }
@Nonnull
@Override
public IWorldDimensionData dimensionData()
{
return this.dimensionData;
}
@Nonnull @Nonnull
@Override @Override
public IWorldCompassData compassData() public IWorldCompassData compassData()
@@ -24,6 +24,7 @@ import java.util.List;
import net.minecraft.client.util.ITooltipFlag; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
@@ -31,17 +32,23 @@ import net.minecraftforge.fml.relauncher.SideOnly;
import appeng.api.implementations.TransitionResult; import appeng.api.implementations.TransitionResult;
import appeng.api.implementations.items.ISpatialStorageCell; import appeng.api.implementations.items.ISpatialStorageCell;
import appeng.api.storage.ISpatialDimension;
import appeng.api.util.WorldCoord; import appeng.api.util.WorldCoord;
import appeng.capabilities.Capabilities;
import appeng.core.AppEng;
import appeng.core.localization.GuiText; import appeng.core.localization.GuiText;
import appeng.core.worlddata.WorldData;
import appeng.items.AEBaseItem; import appeng.items.AEBaseItem;
import appeng.spatial.StorageHelper; import appeng.spatial.StorageHelper;
import appeng.spatial.StorageWorldProvider;
import appeng.util.Platform; import appeng.util.Platform;
public class ItemSpatialStorageCell extends AEBaseItem implements ISpatialStorageCell public class ItemSpatialStorageCell extends AEBaseItem implements ISpatialStorageCell
{ {
private static final String NBT_CELL_ID_KEY = "StorageCellID";
private static final String NBT_SIZE_X_KEY = "sizeX";
private static final String NBT_SIZE_Y_KEY = "sizeY";
private static final String NBT_SIZE_Z_KEY = "sizeZ";
private final int maxRegion; private final int maxRegion;
public ItemSpatialStorageCell( final int spatialScale ) public ItemSpatialStorageCell( final int spatialScale )
@@ -54,6 +61,12 @@ public class ItemSpatialStorageCell extends AEBaseItem implements ISpatialStorag
@Override @Override
public void addCheckedInformation( final ItemStack stack, final World world, final List<String> lines, final ITooltipFlag advancedTooltips ) public void addCheckedInformation( final ItemStack stack, final World world, final List<String> lines, final ITooltipFlag advancedTooltips )
{ {
final int id = this.getStoredDimensionID( stack );
if( id >= 0 )
{
lines.add( GuiText.CellId.getLocal() + ": " + id );
}
final WorldCoord wc = this.getStoredSize( stack ); final WorldCoord wc = this.getStoredSize( stack );
if( wc.x > 0 ) if( wc.x > 0 )
{ {
@@ -74,26 +87,19 @@ public class ItemSpatialStorageCell extends AEBaseItem implements ISpatialStorag
} }
@Override @Override
public World getWorld( final ItemStack is ) public ISpatialDimension getSpatialDimension()
{ {
if( is.hasTagCompound() ) final int id = AppEng.instance().getStorageDimensionID();
World w = DimensionManager.getWorld( id );
if( w == null )
{ {
final NBTTagCompound c = is.getTagCompound(); DimensionManager.initDimension( id );
final int dim = c.getInteger( "StorageDim" ); w = DimensionManager.getWorld( id );
World w = DimensionManager.getWorld( dim ); }
if( w == null )
{
DimensionManager.initDimension( dim );
w = DimensionManager.getWorld( dim );
}
if( w != null ) if( w != null && w.hasCapability( Capabilities.SPATIAL_DIMENSION, null ) )
{ {
if( w.provider instanceof StorageWorldProvider ) return w.getCapability( Capabilities.SPATIAL_DIMENSION, null );
{
return w;
}
}
} }
return null; return null;
} }
@@ -104,102 +110,80 @@ public class ItemSpatialStorageCell extends AEBaseItem implements ISpatialStorag
if( is.hasTagCompound() ) if( is.hasTagCompound() )
{ {
final NBTTagCompound c = is.getTagCompound(); final NBTTagCompound c = is.getTagCompound();
if( Platform.isServer() ) return new WorldCoord( c.getInteger( NBT_SIZE_X_KEY ), c.getInteger( NBT_SIZE_Y_KEY ), c.getInteger( NBT_SIZE_Z_KEY ) );
{
final int dim = c.getInteger( "StorageDim" );
return WorldData.instance().dimensionData().getStoredSize( dim );
}
else
{
return new WorldCoord( c.getInteger( "sizeX" ), c.getInteger( "sizeY" ), c.getInteger( "sizeZ" ) );
}
} }
return new WorldCoord( 0, 0, 0 ); return new WorldCoord( 0, 0, 0 );
} }
@Override @Override
public WorldCoord getMin( final ItemStack is ) public int getStoredDimensionID( final ItemStack is )
{ {
final World w = this.getWorld( is ); if( is.hasTagCompound() )
if( w != null )
{ {
final NBTTagCompound info = (NBTTagCompound) w.getWorldInfo().getAdditionalProperty( "storageCell" ); final NBTTagCompound c = is.getTagCompound();
if( info != null ) return c.getInteger( NBT_CELL_ID_KEY );
{
return new WorldCoord( info.getInteger( "minX" ), info.getInteger( "minY" ), info.getInteger( "minZ" ) );
}
} }
return new WorldCoord( 0, 0, 0 ); return -1;
} }
@Override @Override
public WorldCoord getMax( final ItemStack is ) public TransitionResult doSpatialTransition( final ItemStack is, final World w, final WorldCoord min, final WorldCoord max, int playerId )
{ {
final World w = this.getWorld( is );
if( w != null )
{
final NBTTagCompound info = (NBTTagCompound) w.getWorldInfo().getAdditionalProperty( "storageCell" );
if( info != null )
{
return new WorldCoord( info.getInteger( "maxX" ), info.getInteger( "maxY" ), info.getInteger( "maxZ" ) );
}
}
return new WorldCoord( 0, 0, 0 );
}
@Override
public TransitionResult doSpatialTransition( final ItemStack is, final World w, final WorldCoord min, final WorldCoord max, final boolean doTransition )
{
final WorldCoord scale = this.getStoredSize( is );
final int targetX = max.x - min.x - 1; final int targetX = max.x - min.x - 1;
final int targetY = max.y - min.y - 1; final int targetY = max.y - min.y - 1;
final int targetZ = max.z - min.z - 1; final int targetZ = max.z - min.z - 1;
final int maxSize = this.getMaxStoredDim( is ); final int maxSize = this.getMaxStoredDim( is );
World destination = this.getWorld( is ); final BlockPos targetSize = new BlockPos( targetX, targetY, targetZ );
if( ( scale.x == 0 && scale.y == 0 && scale.z == 0 ) || ( scale.x == targetX && scale.y == targetY && scale.z == targetZ ) ) ISpatialDimension manager = this.getSpatialDimension();
int cellid = this.getStoredDimensionID( is );
if( cellid < 0 )
{ {
if( targetX <= maxSize && targetY <= maxSize && targetZ <= maxSize ) cellid = manager.createNewCellDimension( targetSize, playerId );
}
try
{
if( manager.isCellDimension( cellid ) )
{ {
if( destination == null ) BlockPos scale = manager.getCellContentSize( cellid );
if( scale.equals( targetSize ) )
{ {
destination = this.createNewWorld( is ); if( targetX <= maxSize && targetY <= maxSize && targetZ <= maxSize )
{
BlockPos offset = manager.getCellDimensionOrigin( cellid );
this.setStorageCell( is, cellid, targetSize );
StorageHelper.getInstance().swapRegions( w, min.x + 1, min.y + 1, min.z + 1, manager.getWorld(), offset.getX(), offset.getY(),
offset.getZ(), targetX - 1, targetY - 1,
targetZ - 1 );
return new TransitionResult( true, 0 );
}
} }
}
final int floorBuffer = 64; return new TransitionResult( false, 0 );
StorageHelper.getInstance().swapRegions( w, min.x + 1, min.y + 1, min.z + 1, destination, 0, floorBuffer, 0, targetX - 1, targetY - 1, }
targetZ - 1 ); finally
this.setStoredSize( is, targetX, targetY, targetZ ); {
// clean up newly created dimensions that failed transfer
return new TransitionResult( true, 0 ); if( manager.isCellDimension( cellid ) && this.getStoredDimensionID( is ) < 0 )
{
manager.deleteCellDimension( cellid );
} }
} }
return new TransitionResult( false, 0 );
} }
private World createNewWorld( final ItemStack is ) private void setStorageCell( final ItemStack is, int id, BlockPos size )
{ {
final NBTTagCompound c = Platform.openNbtData( is ); final NBTTagCompound c = Platform.openNbtData( is );
final int newDim = DimensionManager.getNextFreeDimId();
c.setInteger( "StorageDim", newDim );
WorldData.instance().dimensionData().addStorageCell( newDim );
DimensionManager.initDimension( newDim );
return DimensionManager.getWorld( newDim );
}
private void setStoredSize( final ItemStack is, final int targetX, final int targetY, final int targetZ ) c.setInteger( NBT_CELL_ID_KEY, id );
{ c.setInteger( NBT_SIZE_X_KEY, size.getX() );
if( is.hasTagCompound() ) c.setInteger( NBT_SIZE_Y_KEY, size.getY() );
{ c.setInteger( NBT_SIZE_Z_KEY, size.getZ() );
final NBTTagCompound c = is.getTagCompound();
final int dim = c.getInteger( "StorageDim" );
c.setInteger( "sizeX", targetX );
c.setInteger( "sizeY", targetY );
c.setInteger( "sizeZ", targetZ );
WorldData.instance().dimensionData().setStoredSize( dim, targetX, targetY, targetZ );
}
} }
} }
@@ -147,13 +147,12 @@ public class CachedPlane
else else
{ {
final Object[] details = this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].getDetails( tePOS.getY() ); final Object[] details = this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].getDetails( tePOS.getY() );
final Block blk = (Block) details[0]; final IBlockState blkState = (IBlockState) details[0];
// don't skip air, just let the code replace it... // don't skip air, just let the code replace it...
if( blk != null && blk.isAir( c.getWorld().getBlockState( tePOS ), c.getWorld(), tePOS ) && blk.isReplaceable( c.getWorld(), if( blkState != null && blkState.getBlock() == Platform.AIR_BLOCK && blkState.getMaterial().isReplaceable() )
tePOS ) )
{ {
c.getWorld().setBlockToAir( tePOS ); w.setBlockToAir( tePOS );
} }
else else
{ {
@@ -241,8 +241,9 @@ public class StorageHelper
@Override @Override
public void visit( final BlockPos pos ) public void visit( final BlockPos pos )
{ {
final Block blk = this.dst.getBlockState( pos ).getBlock(); final IBlockState state = this.dst.getBlockState( pos );
blk.neighborChanged( Platform.AIR_BLOCK.getDefaultState(), this.dst, pos, Platform.AIR_BLOCK, pos ); final Block blk = state.getBlock();
blk.neighborChanged( state, this.dst, pos, blk, pos );
} }
} }
@@ -19,8 +19,11 @@
package appeng.tile.spatial; package appeng.tile.spatial;
import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@@ -47,6 +50,7 @@ import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.IWorldCallable; import appeng.util.IWorldCallable;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.inv.InvOperation; import appeng.util.inv.InvOperation;
import appeng.util.inv.WrapperFilteredItemHandler;
import appeng.util.inv.filter.IAEItemFilter; import appeng.util.inv.filter.IAEItemFilter;
@@ -54,12 +58,12 @@ public class TileSpatialIOPort extends AENetworkInvTile implements IWorldCallabl
{ {
private final AppEngInternalInventory inv = new AppEngInternalInventory( this, 2 ); private final AppEngInternalInventory inv = new AppEngInternalInventory( this, 2 );
private final IItemHandler invExt = new WrapperFilteredItemHandler( inv, new SpatialIOFilter() );
private YesNo lastRedstoneState = YesNo.UNDECIDED; private YesNo lastRedstoneState = YesNo.UNDECIDED;
public TileSpatialIOPort() public TileSpatialIOPort()
{ {
this.getProxy().setFlags( GridFlags.REQUIRE_CHANNEL ); this.getProxy().setFlags( GridFlags.REQUIRE_CHANNEL );
this.inv.setFilter( new SpatialIOFilter() );
} }
@TileEvent( TileEventType.WORLD_NBT_WRITE ) @TileEvent( TileEventType.WORLD_NBT_WRITE )
@@ -143,7 +147,13 @@ public class TileSpatialIOPort extends AENetworkInvTile implements IWorldCallabl
final MENetworkEvent res = gi.postEvent( new MENetworkSpatialEvent( this, req ) ); final MENetworkEvent res = gi.postEvent( new MENetworkSpatialEvent( this, req ) );
if( !res.isCanceled() ) if( !res.isCanceled() )
{ {
final TransitionResult tr = sc.doSpatialTransition( cell, this.world, spc.getMin(), spc.getMax(), true ); int playerId = -1;
if( getProxy().getSecurity().isAvailable() )
{
playerId = getProxy().getSecurity().getOwner();
}
final TransitionResult tr = sc.doSpatialTransition( cell, this.world, spc.getMin(), spc.getMax(), playerId );
if( tr.success ) if( tr.success )
{ {
energy.extractAEPower( req, Actionable.MODULATE, PowerMultiplier.CONFIG ); energy.extractAEPower( req, Actionable.MODULATE, PowerMultiplier.CONFIG );
@@ -170,6 +180,12 @@ public class TileSpatialIOPort extends AENetworkInvTile implements IWorldCallabl
return new DimensionalCoord( this ); return new DimensionalCoord( this );
} }
@Override
protected @Nonnull IItemHandler getItemHandlerForSide( @Nonnull EnumFacing side )
{
return this.invExt;
}
@Override @Override
public IItemHandler getInternalInventory() public IItemHandler getInternalInventory()
{ {
@@ -170,6 +170,7 @@ gui.appliedenergistics2.Blank=Blank
gui.appliedenergistics2.Unlinked=Unlinked gui.appliedenergistics2.Unlinked=Unlinked
gui.appliedenergistics2.Linked=Linked gui.appliedenergistics2.Linked=Linked
gui.appliedenergistics2.StoredSize=Stored Size gui.appliedenergistics2.StoredSize=Stored Size
gui.appliedenergistics2.CellId=Cell ID
gui.appliedenergistics2.SkyChest=Sky Stone Chest gui.appliedenergistics2.SkyChest=Sky Stone Chest
gui.appliedenergistics2.PatternTerminal=Pattern Terminal gui.appliedenergistics2.PatternTerminal=Pattern Terminal
gui.appliedenergistics2.CraftingPattern=Crafting Pattern gui.appliedenergistics2.CraftingPattern=Crafting Pattern
@@ -0,0 +1,74 @@
package appeng.core.worlddata;
import org.junit.Assert;
import org.junit.Test;
import net.minecraft.util.math.BlockPos;
public class SpatialDimensionManagerTest
{
private static final BlockPos CONTENT = new BlockPos(1, 1, 1);
private static final int ID_1 = 0;
private static final int ID_2 = 1;
private static final int ID_3 = 2;
private static final int ID_4 = 3;
private static final int ID_5 = 4;
private static final int ID_6 = 5;
private static final int ID_7 = 6;
private static final int ID_8 = 7;
private static final int ID_9 = 8;
private static final int ID_A = 9;
private static final int ID_B = 10;
private static final int ID_C = 11;
private static final BlockPos POS_1 = new BlockPos( -320, 64, -320);
private static final BlockPos POS_2 = new BlockPos( 192, 64, -320);
private static final BlockPos POS_3 = new BlockPos( -320, 64, 192);
private static final BlockPos POS_4 = new BlockPos( 192, 64, 192);
private static final BlockPos POS_5 = new BlockPos( -832, 64, -320);
private static final BlockPos POS_6 = new BlockPos( 704, 64, -320);
private static final BlockPos POS_7 = new BlockPos( -832, 64, 192);
private static final BlockPos POS_8 = new BlockPos( 704, 64, 192);
private static final BlockPos POS_9 = new BlockPos( -320, 64, -832);
private static final BlockPos POS_A = new BlockPos( 192, 64, -832);
private static final BlockPos POS_B = new BlockPos( -320, 64, 704);
private static final BlockPos POS_C = new BlockPos( 192, 64, 704);
@Test
public void testBlockPosGeneration()
{
SpatialDimensionManager manager = new SpatialDimensionManager( null );
Assert.assertEquals( ID_1, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_2, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_3, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_4, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_5, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_6, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_7, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_8, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_9, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_A, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_B, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( ID_C, manager.createNewCellDimension( CONTENT, -1 ));
Assert.assertEquals( POS_1, manager.getCellDimensionOrigin( ID_1 ) );
Assert.assertEquals( POS_2, manager.getCellDimensionOrigin( ID_2 ) );
Assert.assertEquals( POS_3, manager.getCellDimensionOrigin( ID_3 ) );
Assert.assertEquals( POS_4, manager.getCellDimensionOrigin( ID_4 ) );
Assert.assertEquals( POS_5, manager.getCellDimensionOrigin( ID_5 ) );
Assert.assertEquals( POS_6, manager.getCellDimensionOrigin( ID_6 ) );
Assert.assertEquals( POS_7, manager.getCellDimensionOrigin( ID_7 ) );
Assert.assertEquals( POS_8, manager.getCellDimensionOrigin( ID_8 ) );
Assert.assertEquals( POS_9, manager.getCellDimensionOrigin( ID_9 ) );
Assert.assertEquals( POS_A, manager.getCellDimensionOrigin( ID_A ) );
Assert.assertEquals( POS_B, manager.getCellDimensionOrigin( ID_B ) );
Assert.assertEquals( POS_C, manager.getCellDimensionOrigin( ID_C ) );
}
}