diff --git a/engine-tests/src/test/java/org/terasology/persistence/internal/StorageManagerTest.java b/engine-tests/src/test/java/org/terasology/persistence/internal/StorageManagerTest.java index c9d7cd322ee..2633d429889 100644 --- a/engine-tests/src/test/java/org/terasology/persistence/internal/StorageManagerTest.java +++ b/engine-tests/src/test/java/org/terasology/persistence/internal/StorageManagerTest.java @@ -61,6 +61,7 @@ import org.terasology.world.block.Block; import org.terasology.world.block.BlockManager; import org.terasology.world.block.family.SymmetricFamily; +import org.terasology.world.block.internal.BlockManagerImpl; import org.terasology.world.block.loader.BlockFamilyDefinition; import org.terasology.world.block.loader.BlockFamilyDefinitionData; import org.terasology.world.chunks.Chunk; @@ -75,6 +76,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; +import java.util.Collections; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -158,6 +160,7 @@ public void setup() throws Exception { data.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("test:testblock"), data, BlockFamilyDefinition.class); assetManager.loadAsset(new ResourceUrn("test:testblock2"), data, BlockFamilyDefinition.class); + ((BlockManagerImpl)blockManager).initialise(Collections.EMPTY_LIST, Collections.EMPTY_MAP); testBlock = context.get(BlockManager.class).getBlock("test:testblock"); testBlock2 = context.get(BlockManager.class).getBlock("test:testblock2"); diff --git a/engine-tests/src/test/java/org/terasology/world/ChunkTest.java b/engine-tests/src/test/java/org/terasology/world/ChunkTest.java index 7373d6898d2..7a8cb5ec279 100644 --- a/engine-tests/src/test/java/org/terasology/world/ChunkTest.java +++ b/engine-tests/src/test/java/org/terasology/world/ChunkTest.java @@ -38,6 +38,8 @@ import org.terasology.world.chunks.blockdata.ExtraBlockDataManager; import org.terasology.world.chunks.internal.ChunkImpl; +import java.util.Collections; + import static org.junit.jupiter.api.Assertions.assertEquals; public class ChunkTest extends TerasologyTestingEnvironment { @@ -50,20 +52,20 @@ public class ChunkTest extends TerasologyTestingEnvironment { public void setup() throws Exception { super.setup(); AssetManager assetManager = CoreRegistry.get(AssetManager.class); - blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager); - CoreRegistry.put(BlockManager.class, blockManager); ExtraBlockDataManager extraDataManager = new ExtraBlockDataManager(); - chunk = new ChunkImpl(new Vector3i(0, 0, 0), blockManager, extraDataManager); - BlockFamilyDefinitionData solidData = new BlockFamilyDefinitionData(); solidData.getBaseSection().setDisplayName("Stone"); - solidData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); solidData.getBaseSection().setTranslucent(false); solidData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:stone"), solidData, BlockFamilyDefinition.class); + blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager); + blockManager.initialise(Collections.EMPTY_LIST, Collections.EMPTY_MAP); + CoreRegistry.put(BlockManager.class, blockManager); solid = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:stone"))); + + chunk = new ChunkImpl(new Vector3i(0, 0, 0), blockManager, extraDataManager); } @Test diff --git a/engine-tests/src/test/java/org/terasology/world/ChunkViewTest.java b/engine-tests/src/test/java/org/terasology/world/ChunkViewTest.java index 7b6776f3aa6..95d62e59822 100644 --- a/engine-tests/src/test/java/org/terasology/world/ChunkViewTest.java +++ b/engine-tests/src/test/java/org/terasology/world/ChunkViewTest.java @@ -27,6 +27,7 @@ import org.terasology.world.internal.ChunkViewCoreImpl; import java.io.IOException; +import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -34,24 +35,24 @@ public class ChunkViewTest extends TerasologyTestingEnvironment { Block airBlock; Block solidBlock; - private BlockManager blockManager; + private BlockManagerImpl blockManager; private ExtraBlockDataManager extraDataManager; @BeforeEach public void setup() throws IOException { AssetManager assetManager = CoreRegistry.get(AssetManager.class); - blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager); - CoreRegistry.put(BlockManager.class, blockManager); - airBlock = blockManager.getBlock(BlockManager.AIR_ID); extraDataManager = new ExtraBlockDataManager(); BlockFamilyDefinitionData solidData = new BlockFamilyDefinitionData(); solidData.getBaseSection().setDisplayName("Stone"); - solidData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); solidData.getBaseSection().setTranslucent(false); solidData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:stone"), solidData, BlockFamilyDefinition.class); + blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager); + blockManager.initialise(Collections.EMPTY_LIST, Collections.EMPTY_MAP); + CoreRegistry.put(BlockManager.class, blockManager); + airBlock = blockManager.getBlock(BlockManager.AIR_ID); solidBlock = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:stone"))); } diff --git a/engine-tests/src/test/java/org/terasology/world/EntityAwareWorldProviderTest.java b/engine-tests/src/test/java/org/terasology/world/EntityAwareWorldProviderTest.java index 5946ec08bd3..9352d1c8b5f 100644 --- a/engine-tests/src/test/java/org/terasology/world/EntityAwareWorldProviderTest.java +++ b/engine-tests/src/test/java/org/terasology/world/EntityAwareWorldProviderTest.java @@ -52,10 +52,12 @@ import org.terasology.world.block.family.BlockFamily; import org.terasology.world.block.family.HorizontalFamily; import org.terasology.world.block.family.SymmetricFamily; +import org.terasology.world.block.internal.BlockManagerImpl; import org.terasology.world.block.loader.BlockFamilyDefinition; import org.terasology.world.block.loader.BlockFamilyDefinitionData; import org.terasology.world.internal.EntityAwareWorldProvider; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -91,38 +93,45 @@ public void setup() throws Exception { AssetManager assetManager = context.get(AssetManager.class); BlockManager blockManager = context.get(BlockManager.class); - airBlock = blockManager.getBlock(BlockManager.AIR_ID); - - worldStub = new WorldProviderCoreStub(airBlock); - worldProvider = new EntityAwareWorldProvider(worldStub, context); - - plainBlock = createBlock("test:plainblock", assetManager, blockManager); + createBlock("test:plainblock", assetManager); prefabWithString = createPrefabWithString("test:prefabWithString", "Test", assetManager); - blockWithString = createBlockWithPrefab("test:blockWithString", prefabWithString, false, assetManager, blockManager); - keepActiveBlock = createBlockWithPrefab("test:keepActiveBlock", prefabWithString, true, assetManager, blockManager); + createBlockWithPrefab("test:blockWithString", prefabWithString, false, assetManager); + createBlockWithPrefab("test:keepActiveBlock", prefabWithString, true, assetManager); Prefab prefabWithDifferentString = createPrefabWithString("test:prefabWithDifferentString", "Test2", assetManager); - blockWithDifferentString = createBlockWithPrefab("test:prefabWithDifferentString", prefabWithDifferentString, false, assetManager, blockManager); + createBlockWithPrefab("test:prefabWithDifferentString", prefabWithDifferentString, false, assetManager); - BlockFamily blockFamily = createBlockFamily("test:blockFamily", prefabWithString, assetManager, blockManager); - Iterator iterator = blockFamily.getBlocks().iterator(); - blockInFamilyOne = iterator.next(); - blockInFamilyTwo = iterator.next(); + createBlockFamily("test:blockFamily", prefabWithString, assetManager); PrefabData retainedPrefabData = new PrefabData(); retainedPrefabData.addComponent(new RetainedOnBlockChangeComponent(3)); Prefab retainedPrefab = assetManager.loadAsset(new ResourceUrn("test:retainedPrefab"), retainedPrefabData, Prefab.class); - blockWithRetainedComponent = createBlockWithPrefab("test:blockWithRetainedComponent", retainedPrefab, false, assetManager, blockManager); + createBlockWithPrefab("test:blockWithRetainedComponent", retainedPrefab, false, assetManager); + + ((BlockManagerImpl)blockManager).initialise(Collections.EMPTY_LIST, Collections.EMPTY_MAP); + airBlock = blockManager.getBlock(BlockManager.AIR_ID); + plainBlock = blockManager.getBlock("test:plainblock"); + blockWithString = blockManager.getBlock("test:blockWithString"); + keepActiveBlock = blockManager.getBlock("test:keepActiveBlock"); + blockWithDifferentString = blockManager.getBlock("test:prefabWithDifferentString"); + BlockFamily blockFamily = blockManager.getBlockFamily("test:blockFamily"); + Iterator iterator = blockFamily.getBlocks().iterator(); + blockInFamilyOne = iterator.next(); + blockInFamilyTwo = iterator.next(); + blockWithRetainedComponent = blockManager.getBlock("test:blockWithRetainedComponent"); + + worldStub = new WorldProviderCoreStub(airBlock); + worldProvider = new EntityAwareWorldProvider(worldStub, context); + worldProvider.initialise(); } - private Block createBlockWithPrefab(String urn, Prefab prefab, boolean keepActive, AssetManager assetManager, BlockManager blockManager) { + private void createBlockWithPrefab(String urn, Prefab prefab, boolean keepActive, AssetManager assetManager) { BlockFamilyDefinitionData data = new BlockFamilyDefinitionData(); data.setBlockFamily(SymmetricFamily.class); data.getBaseSection().getEntity().setPrefab(prefab); data.getBaseSection().getEntity().setKeepActive(keepActive); assetManager.loadAsset(new ResourceUrn(urn), data, BlockFamilyDefinition.class); - return blockManager.getBlock(urn); } private Prefab createPrefabWithString(String urn, String text, AssetManager assetManager) { @@ -131,20 +140,18 @@ private Prefab createPrefabWithString(String urn, String text, AssetManager asse return assetManager.loadAsset(new ResourceUrn(urn), prefabData, Prefab.class); } - private Block createBlock(String urn, AssetManager assetManager, BlockManager blockManager) { + private void createBlock(String urn, AssetManager assetManager) { BlockFamilyDefinitionData data = new BlockFamilyDefinitionData(); data.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn(urn), data, BlockFamilyDefinition.class); - return blockManager.getBlock(urn); } - private BlockFamily createBlockFamily(String urn, Prefab prefab, AssetManager assetManager, BlockManager blockManager) { + private void createBlockFamily(String urn, Prefab prefab, AssetManager assetManager) { BlockFamilyDefinitionData data = new BlockFamilyDefinitionData(); data.setBlockFamily(HorizontalFamily.class); data.getBaseSection().getEntity().setKeepActive(true); data.getBaseSection().getEntity().setPrefab(prefab); assetManager.loadAsset(new ResourceUrn(urn), data, BlockFamilyDefinition.class); - return blockManager.getBlockFamily(urn); } @Test diff --git a/engine-tests/src/test/java/org/terasology/world/generator/InternalLightGeneratorTest.java b/engine-tests/src/test/java/org/terasology/world/generator/InternalLightGeneratorTest.java index 07f97e8659d..25a155c5218 100644 --- a/engine-tests/src/test/java/org/terasology/world/generator/InternalLightGeneratorTest.java +++ b/engine-tests/src/test/java/org/terasology/world/generator/InternalLightGeneratorTest.java @@ -27,6 +27,8 @@ import org.terasology.world.chunks.internal.ChunkImpl; import org.terasology.world.propagation.light.InternalLightProcessor; +import java.util.Collections; + import static org.junit.jupiter.api.Assertions.assertEquals; public class InternalLightGeneratorTest extends TerasologyTestingEnvironment { @@ -43,20 +45,13 @@ public class InternalLightGeneratorTest extends TerasologyTestingEnvironment { public void setup() throws Exception { super.setup(); AssetManager assetManager = CoreRegistry.get(AssetManager.class); - blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager); - CoreRegistry.put(BlockManager.class, blockManager); - airBlock = blockManager.getBlock(BlockManager.AIR_ID); - - extraDataManager = new ExtraBlockDataManager(); BlockFamilyDefinitionData solidData = new BlockFamilyDefinitionData(); solidData.getBaseSection().setDisplayName("Stone"); - solidData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); solidData.getBaseSection().setTranslucent(false); solidData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:stone"), solidData, BlockFamilyDefinition.class); - solidBlock = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:stone"))); BlockFamilyDefinitionData fullLightData = new BlockFamilyDefinitionData(); fullLightData.getBaseSection().setDisplayName("Torch"); @@ -64,6 +59,12 @@ public void setup() throws Exception { fullLightData.getBaseSection().setLuminance(Chunks.MAX_LIGHT); fullLightData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:torch"), fullLightData, BlockFamilyDefinition.class); + + blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager); + ((BlockManagerImpl)blockManager).initialise(Collections.EMPTY_LIST, Collections.EMPTY_MAP); + CoreRegistry.put(BlockManager.class, blockManager); + airBlock = blockManager.getBlock(BlockManager.AIR_ID); + solidBlock = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:stone"))); fullLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:torch"))); } diff --git a/engine-tests/src/test/java/org/terasology/world/propagation/BetweenChunkPropagationTest.java b/engine-tests/src/test/java/org/terasology/world/propagation/BetweenChunkPropagationTest.java index dda164c756a..7e5dd4ded82 100644 --- a/engine-tests/src/test/java/org/terasology/world/propagation/BetweenChunkPropagationTest.java +++ b/engine-tests/src/test/java/org/terasology/world/propagation/BetweenChunkPropagationTest.java @@ -36,6 +36,7 @@ import org.terasology.world.propagation.light.SunlightWorldView; import java.util.Collection; +import java.util.Collections; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -63,16 +64,16 @@ public void setup() throws Exception { AssetManager assetManager = CoreRegistry.get(AssetManager.class); regenRules = new SunlightRegenPropagationRules(); - blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager, true); - CoreRegistry.put(BlockManager.class, blockManager); extraDataManager = new ExtraBlockDataManager(); BlockFamilyDefinitionData solidData = new BlockFamilyDefinitionData(); solidData.getBaseSection().setDisplayName("Stone"); - solidData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); solidData.getBaseSection().setTranslucent(false); solidData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:stone"), solidData, BlockFamilyDefinition.class); + blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager, true); + blockManager.initialise(Collections.EMPTY_LIST, Collections.EMPTY_MAP); + CoreRegistry.put(BlockManager.class, blockManager); solid = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:stone"))); regenWorldView = new SunlightRegenWorldView(provider); diff --git a/engine-tests/src/test/java/org/terasology/world/propagation/BulkLightPropagationTest.java b/engine-tests/src/test/java/org/terasology/world/propagation/BulkLightPropagationTest.java index 6082f90f358..299528f52cc 100644 --- a/engine-tests/src/test/java/org/terasology/world/propagation/BulkLightPropagationTest.java +++ b/engine-tests/src/test/java/org/terasology/world/propagation/BulkLightPropagationTest.java @@ -37,6 +37,8 @@ import org.terasology.world.chunks.Chunks; import org.terasology.world.propagation.light.LightPropagationRules; +import java.util.Collections; + import static org.junit.jupiter.api.Assertions.assertEquals; public class BulkLightPropagationTest extends TerasologyTestingEnvironment { @@ -60,8 +62,6 @@ public void setup() throws Exception { super.setup(); lightRules = new LightPropagationRules(); AssetManager assetManager = CoreRegistry.get(AssetManager.class); - blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager, true); - CoreRegistry.put(BlockManager.class, blockManager); BlockFamilyDefinitionData fullLightData = new BlockFamilyDefinitionData(); fullLightData.getBaseSection().setDisplayName("Torch"); fullLightData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); @@ -69,44 +69,43 @@ public void setup() throws Exception { fullLightData.getBaseSection().setTranslucent(true); fullLightData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:torch"), fullLightData, BlockFamilyDefinition.class); - fullLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:torch"))); BlockFamilyDefinitionData weakLightData = new BlockFamilyDefinitionData(); weakLightData.getBaseSection().setDisplayName("PartLight"); - weakLightData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); weakLightData.getBaseSection().setLuminance((byte) 2); weakLightData.getBaseSection().setTranslucent(true); weakLightData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:weakLight"), weakLightData, BlockFamilyDefinition.class); - weakLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:weakLight"))); BlockFamilyDefinitionData mediumLightData = new BlockFamilyDefinitionData(); mediumLightData.getBaseSection().setDisplayName("MediumLight"); - mediumLightData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); mediumLightData.getBaseSection().setLuminance((byte) 5); mediumLightData.getBaseSection().setTranslucent(true); mediumLightData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:mediumLight"), mediumLightData, BlockFamilyDefinition.class); - mediumLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:mediumLight"))); BlockFamilyDefinitionData solidData = new BlockFamilyDefinitionData(); solidData.getBaseSection().setDisplayName("Stone"); - solidData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); solidData.getBaseSection().setTranslucent(false); solidData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:stone"), solidData, BlockFamilyDefinition.class); - solid = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:stone"))); BlockFamilyDefinitionData solidMediumLightData = new BlockFamilyDefinitionData(); solidMediumLightData.getBaseSection().setDisplayName("SolidMediumLight"); - solidMediumLightData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); solidMediumLightData.getBaseSection().setTranslucent(false); solidMediumLightData.getBaseSection().setLuminance((byte) 5); solidMediumLightData.setBlockFamily(SymmetricFamily.class); - assetManager.loadAsset(new ResourceUrn("engine:solidMediumLight"), solidMediumLightData, - BlockFamilyDefinition.class); - solidMediumLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:solidMediumLight"))); + assetManager.loadAsset(new ResourceUrn("engine:solidMediumLight"), solidMediumLightData, BlockFamilyDefinition.class); + blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager, true); + blockManager.initialise(Collections.EMPTY_LIST, Collections.EMPTY_MAP); + CoreRegistry.put(BlockManager.class, blockManager); + + fullLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:torch"))); + weakLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:weakLight"))); + mediumLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:mediumLight"))); + solid = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:stone"))); + solidMediumLight = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:solidMediumLight"))); air = blockManager.getBlock(BlockManager.AIR_ID); } diff --git a/engine-tests/src/test/java/org/terasology/world/propagation/BulkSunlightPropagationTest.java b/engine-tests/src/test/java/org/terasology/world/propagation/BulkSunlightPropagationTest.java index f4ce541828b..cc0fc8a8354 100644 --- a/engine-tests/src/test/java/org/terasology/world/propagation/BulkSunlightPropagationTest.java +++ b/engine-tests/src/test/java/org/terasology/world/propagation/BulkSunlightPropagationTest.java @@ -38,6 +38,7 @@ import org.terasology.world.propagation.light.SunlightPropagationRules; import org.terasology.world.propagation.light.SunlightRegenPropagationRules; +import java.util.Collections; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -63,15 +64,15 @@ public void setup() throws Exception { regenRules = new SunlightRegenPropagationRules(); AssetManager assetManager = CoreRegistry.get(AssetManager.class); - blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager, true); - CoreRegistry.put(BlockManager.class, blockManager); BlockFamilyDefinitionData solidData = new BlockFamilyDefinitionData(); solidData.getBaseSection().setDisplayName("Stone"); - solidData.getBaseSection().setShape(assetManager.getAsset("engine:cube", BlockShape.class).get()); solidData.getBaseSection().setTranslucent(false); solidData.setBlockFamily(SymmetricFamily.class); assetManager.loadAsset(new ResourceUrn("engine:stone"), solidData, BlockFamilyDefinition.class); + blockManager = new BlockManagerImpl(new NullWorldAtlas(), assetManager, true); + blockManager.initialise(Collections.EMPTY_LIST, Collections.EMPTY_MAP); + CoreRegistry.put(BlockManager.class, blockManager); solid = blockManager.getBlock(new BlockUri(new ResourceUrn("engine:stone"))); air = blockManager.getBlock(BlockManager.AIR_ID); diff --git a/engine/src/main/java/org/terasology/engine/modes/loadProcesses/InitialiseBlockTypeEntities.java b/engine/src/main/java/org/terasology/engine/modes/loadProcesses/InitialiseBlockTypeEntities.java index 960e8514013..28aebadbdb1 100644 --- a/engine/src/main/java/org/terasology/engine/modes/loadProcesses/InitialiseBlockTypeEntities.java +++ b/engine/src/main/java/org/terasology/engine/modes/loadProcesses/InitialiseBlockTypeEntities.java @@ -17,10 +17,20 @@ import org.terasology.context.Context; import org.terasology.engine.modes.SingleStepLoadProcess; +import org.terasology.entitySystem.Component; +import org.terasology.entitySystem.entity.EntityBuilder; import org.terasology.entitySystem.entity.EntityManager; +import org.terasology.entitySystem.entity.EntityRef; +import org.terasology.entitySystem.prefab.Prefab; +import org.terasology.entitySystem.prefab.PrefabManager; +import org.terasology.network.NetworkComponent; +import org.terasology.world.block.Block; import org.terasology.world.block.BlockManager; +import org.terasology.world.block.family.BlockFamily; import org.terasology.world.block.internal.BlockManagerImpl; -import org.terasology.world.block.typeEntity.BlockTypeEntityGenerator; +import org.terasology.world.block.typeEntity.BlockTypeComponent; + +import java.util.Optional; public class InitialiseBlockTypeEntities extends SingleStepLoadProcess { @@ -38,7 +48,38 @@ public String getMessage() { @Override public boolean step() { BlockManagerImpl blockManager = (BlockManagerImpl) context.get(BlockManager.class); - blockManager.subscribe(new BlockTypeEntityGenerator(context.get(EntityManager.class), blockManager)); + EntityManager entityManager = context.get(EntityManager.class); + Prefab blockTypePrefab = entityManager.getPrefabManager().getPrefab("engine:blockType"); + + // connect existing entities + for (EntityRef entity : entityManager.getEntitiesWith(BlockTypeComponent.class)) { + BlockTypeComponent blockTypeComp = entity.getComponent(BlockTypeComponent.class); + if (blockTypeComp.block == null) { + entity.destroy(); + } else { + blockTypeComp.block.setEntity(entity); + } + } + + // generate for existing blocks + for (BlockFamily blockFamily : blockManager.listRegisteredBlockFamilies()) { + for (Block block : blockFamily.getBlocks()) { + if (!block.getEntity().exists()) { + EntityBuilder builder = entityManager.newBuilder(blockTypePrefab); + builder.getComponent(BlockTypeComponent.class).block = block; + // TODO: Copy across settings as necessary + Optional prefab = block.getPrefab(); + if (prefab.isPresent()) { + for (Component comp : prefab.get().iterateComponents()) { + if (!(comp instanceof NetworkComponent)) { + builder.addComponent(entityManager.getComponentLibrary().copy(comp)); + } + } + } + block.setEntity(builder.build()); + } + } + } return true; } diff --git a/engine/src/main/java/org/terasology/engine/modes/loadProcesses/ProcessBlockPrefabs.java b/engine/src/main/java/org/terasology/engine/modes/loadProcesses/ProcessBlockPrefabs.java index cd491934def..5b5d932d269 100644 --- a/engine/src/main/java/org/terasology/engine/modes/loadProcesses/ProcessBlockPrefabs.java +++ b/engine/src/main/java/org/terasology/engine/modes/loadProcesses/ProcessBlockPrefabs.java @@ -17,10 +17,16 @@ import org.terasology.context.Context; import org.terasology.engine.modes.SingleStepLoadProcess; +import org.terasology.entitySystem.Component; import org.terasology.entitySystem.entity.EntityManager; +import org.terasology.entitySystem.metadata.ComponentMetadata; +import org.terasology.entitySystem.prefab.Prefab; +import org.terasology.world.block.Block; import org.terasology.world.block.BlockManager; +import org.terasology.world.block.family.BlockFamily; import org.terasology.world.block.internal.BlockManagerImpl; -import org.terasology.world.block.internal.BlockPrefabManager; + +import java.util.Optional; /** */ @@ -40,7 +46,29 @@ public String getMessage() { @Override public boolean step() { BlockManagerImpl blockManager = (BlockManagerImpl) context.get(BlockManager.class); - blockManager.subscribe(new BlockPrefabManager(context.get(EntityManager.class), blockManager)); + EntityManager entityManager = context.get(EntityManager.class); + + for (BlockFamily blockFamily : blockManager.listRegisteredBlockFamilies()) { + for (Block block : blockFamily.getBlocks()) { + Optional prefab = block.getPrefab(); + boolean keepActive = block.isKeepActive(); + boolean requiresLifecycleEvents = false; + if (prefab.isPresent()) { + for (Component comp : prefab.get().iterateComponents()) { + ComponentMetadata metadata = entityManager.getComponentLibrary().getMetadata(comp.getClass()); + if (metadata.isForceBlockActive()) { + keepActive = true; + break; + } + if (metadata.isBlockLifecycleEventsRequired()) { + requiresLifecycleEvents = true; + } + } + } + block.setKeepActive(keepActive); + block.setLifecycleEventsRequired(requiresLifecycleEvents && !keepActive); + } + } return true; } diff --git a/engine/src/main/java/org/terasology/engine/modes/loadProcesses/RegisterBlocks.java b/engine/src/main/java/org/terasology/engine/modes/loadProcesses/RegisterBlocks.java index 0f3f2bf9a07..d1b4250563c 100644 --- a/engine/src/main/java/org/terasology/engine/modes/loadProcesses/RegisterBlocks.java +++ b/engine/src/main/java/org/terasology/engine/modes/loadProcesses/RegisterBlocks.java @@ -62,12 +62,7 @@ public boolean step() { BlockManagerImpl blockManager; - if (networkSystem.getMode().isAuthority()) { - blockManager = new BlockManagerImpl(atlas, context.get(AssetManager.class), true); - blockManager.subscribe(context.get(NetworkSystem.class)); - } else { - blockManager = new BlockManagerImpl(atlas, context.get(AssetManager.class), false); - } + blockManager = new BlockManagerImpl(atlas, context.get(AssetManager.class), networkSystem.getMode().isAuthority()); context.put(BlockManager.class, blockManager); context.get(TypeHandlerLibrary.class).addTypeHandler(Block.class, new BlockTypeHandler(blockManager)); context.get(TypeHandlerLibrary.class).addTypeHandler(BlockFamily.class, new BlockFamilyTypeHandler(blockManager)); diff --git a/engine/src/main/java/org/terasology/network/NetworkSystem.java b/engine/src/main/java/org/terasology/network/NetworkSystem.java index 98adea41244..f174405d70c 100644 --- a/engine/src/main/java/org/terasology/network/NetworkSystem.java +++ b/engine/src/main/java/org/terasology/network/NetworkSystem.java @@ -23,7 +23,6 @@ import org.terasology.network.exceptions.HostingFailedException; import org.terasology.nui.Color; import org.terasology.world.BlockEntityRegistry; -import org.terasology.world.block.internal.BlockRegistrationListener; import org.terasology.world.chunks.remoteChunkProvider.RemoteChunkProvider; /** @@ -31,7 +30,7 @@ * */ // TODO: Refactor the core gameplay components like the list of players into a separate system. -public interface NetworkSystem extends BlockRegistrationListener { +public interface NetworkSystem { void host(int port, boolean dedicatedServer) throws HostingFailedException; diff --git a/engine/src/main/java/org/terasology/network/internal/NetworkSystemImpl.java b/engine/src/main/java/org/terasology/network/internal/NetworkSystemImpl.java index 2efd01daabf..8f1dcfb4872 100644 --- a/engine/src/main/java/org/terasology/network/internal/NetworkSystemImpl.java +++ b/engine/src/main/java/org/terasology/network/internal/NetworkSystemImpl.java @@ -1021,15 +1021,4 @@ private Map, Integer> applySerializationInfo(Listuri mapping"); - } else if (blockFamily.getBlockUriCount() == 0) { - logger.error("Received empty block registration"); - } else { - try { - BlockUri family = new BlockUri(blockFamily.getBlockUri(0)).getFamilyUri(); - Map registrationMap = Maps.newHashMap(); - for (int i = 0; i < blockFamily.getBlockIdCount(); ++i) { - registrationMap.put(blockFamily.getBlockUri(i), blockFamily.getBlockId(i)); - } - blockManager.receiveFamilyRegistration(family, registrationMap); - } catch (BlockUriParseException e) { - logger.error("Received invalid block uri {}", blockFamily.getBlockUri(0)); - } - } - } - } - private void updateEntity(NetData.UpdateEntityMessage updateEntity) { EntityRef currentEntity = networkSystem.getEntity(updateEntity.getNetId()); if (currentEntity.exists()) { diff --git a/engine/src/main/java/org/terasology/world/block/BlockExplorer.java b/engine/src/main/java/org/terasology/world/block/BlockExplorer.java deleted file mode 100644 index 1c69db0d644..00000000000 --- a/engine/src/main/java/org/terasology/world/block/BlockExplorer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015 MovingBlocks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.terasology.world.block; - -import org.terasology.assets.management.AssetManager; -import org.terasology.world.block.loader.BlockFamilyDefinition; - -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -/** - */ -public class BlockExplorer { - private AssetManager assetManager; - - public BlockExplorer(AssetManager assetManager) { - this.assetManager = assetManager; - } - - public Set getAvailableBlockFamilies() { - return assetManager.getAvailableAssets(BlockFamilyDefinition.class) - .stream().>map(urn -> assetManager.getAsset(urn, BlockFamilyDefinition.class)) - .filter(def -> def.isPresent() && def.get().isLoadable() && !def.get().isFreeform()) - .map(r -> new BlockUri(r.get().getUrn())).collect(Collectors.toSet()); - } - - public Set getFreeformBlockFamilies() { - return assetManager.getAvailableAssets(BlockFamilyDefinition.class) - .stream().>map(urn -> assetManager.getAsset(urn, BlockFamilyDefinition.class)) - .filter(def -> def.isPresent() && def.get().isLoadable() && def.get().isFreeform()) - .map(r -> new BlockUri(r.get().getUrn())).collect(Collectors.toSet()); - } -} diff --git a/engine/src/main/java/org/terasology/world/block/entity/BlockCommands.java b/engine/src/main/java/org/terasology/world/block/entity/BlockCommands.java index 84efd8db7ed..eb340815dd9 100644 --- a/engine/src/main/java/org/terasology/world/block/entity/BlockCommands.java +++ b/engine/src/main/java/org/terasology/world/block/entity/BlockCommands.java @@ -46,7 +46,6 @@ import org.terasology.world.WorldProvider; import org.terasology.world.block.Block; import org.terasology.world.block.BlockComponent; -import org.terasology.world.block.BlockExplorer; import org.terasology.world.block.BlockManager; import org.terasology.world.block.BlockUri; import org.terasology.world.block.family.BlockFamily; @@ -104,12 +103,10 @@ public class BlockCommands extends BaseComponentSystem { private WorldProviderCoreImpl worldImpl; private BlockItemFactory blockItemFactory; - private BlockExplorer blockExplorer; @Override public void initialise() { blockItemFactory = new BlockItemFactory(entityManager); - blockExplorer = new BlockExplorer(assetManager); targetSystem = new TargetSystem(blockRegistry, physics); } @@ -132,19 +129,6 @@ public String listBlocks(@CommandParam(value = "startsWith", required = false) S } stringBuilder.append(Console.NEW_LINE); - stringBuilder.append("Available Blocks"); - stringBuilder.append(Console.NEW_LINE); - stringBuilder.append("----------------"); - stringBuilder.append(Console.NEW_LINE); - List availableBlocks = sortItems(blockExplorer.getAvailableBlockFamilies()); - for (BlockUri blockUri : availableBlocks) { - if (!uriStartsWithAnyString(blockUri.toString(), startsWith)) { - continue; - } - stringBuilder.append(blockUri.toString()); - stringBuilder.append(Console.NEW_LINE); - } - return stringBuilder.toString(); } @@ -169,29 +153,6 @@ public String listShapes(@CommandParam(value = "startsWith", required = false) S return stringBuilder.toString(); } - @Command(shortDescription = "Lists available free shape blocks", - helpText = "Lists all the available free shape blocks. These blocks can be created with any shape.\n" + - "You can filter by adding the beginning of words after the commands, e.g.: \"listFreeShapeBlocks" + - "engine: core\" will list all free shape blocks from the engine and modules starting with 'core'", - requiredPermission = PermissionManager.CHEAT_PERMISSION) - public String listFreeShapeBlocks(@CommandParam(value = "startsWith", required = false) String[] startsWith) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Free Shape Blocks"); - stringBuilder.append(Console.NEW_LINE); - stringBuilder.append("-----------------"); - stringBuilder.append(Console.NEW_LINE); - List sortedUris = sortItems(blockExplorer.getFreeformBlockFamilies()); - for (BlockUri uri : sortedUris) { - if (!uriStartsWithAnyString(uri.toString(), startsWith)) { - continue; - } - stringBuilder.append(uri.toString()); - stringBuilder.append(Console.NEW_LINE); - } - - return stringBuilder.toString(); - } - @Command(shortDescription = "Replaces a block in front of user", helpText = "Replaces a block in front of the user at the specified max distance", runOnServer = true, requiredPermission = PermissionManager.CHEAT_PERMISSION) @@ -282,28 +243,24 @@ public String giveBlock( if (matchingUris.size() == 1) { Optional def = Assets.get(matchingUris.iterator().next(), BlockFamilyDefinition.class); if (def.isPresent()) { - if (def.get().isFreeform()) { - if (shapeUriParam == null) { - blockFamily = blockManager.getBlockFamily(new BlockUri(def.get().getUrn(), new ResourceUrn("engine:cube"))); - } else { - Set resolvedShapeUris = Assets.resolveAssetUri(shapeUriParam, BlockShape.class); - if (resolvedShapeUris.isEmpty()) { - return "Found block. No shape found for '" + shapeUriParam + "'"; - } else if (resolvedShapeUris.size() > 1) { - StringBuilder builder = new StringBuilder(); - builder.append("Found block. Non-unique shape name, possible matches: "); - Iterator shapeUris = sortItems(resolvedShapeUris).iterator(); - while (shapeUris.hasNext()) { - builder.append(shapeUris.next().toString()); - if (shapeUris.hasNext()) { - builder.append(", "); - } + if (shapeUriParam != null) { + Set resolvedShapeUris = Assets.resolveAssetUri(shapeUriParam, BlockShape.class); + if (resolvedShapeUris.isEmpty()) { + return "Found block. No shape found for '" + shapeUriParam + "'"; + } else if (resolvedShapeUris.size() > 1) { + StringBuilder builder = new StringBuilder(); + builder.append("Found block. Non-unique shape name, possible matches: "); + Iterator shapeUris = sortItems(resolvedShapeUris).iterator(); + while (shapeUris.hasNext()) { + builder.append(shapeUris.next().toString()); + if (shapeUris.hasNext()) { + builder.append(", "); } - - return builder.toString(); } - blockFamily = blockManager.getBlockFamily(new BlockUri(def.get().getUrn(), resolvedShapeUris.iterator().next())); + + return builder.toString(); } + blockFamily = blockManager.getBlockFamily(new BlockUri(def.get().getUrn(), resolvedShapeUris.iterator().next())); } else { blockFamily = blockManager.getBlockFamily(new BlockUri(def.get().getUrn())); } diff --git a/engine/src/main/java/org/terasology/world/block/family/BlockFamilyLibrary.java b/engine/src/main/java/org/terasology/world/block/family/BlockFamilyLibrary.java index 3adb876dcbd..13c4af1d16a 100644 --- a/engine/src/main/java/org/terasology/world/block/family/BlockFamilyLibrary.java +++ b/engine/src/main/java/org/terasology/world/block/family/BlockFamilyLibrary.java @@ -157,15 +157,4 @@ public static MultiSection[] getMultiSections(Class blockFamily) { - if (blockFamily == null) { - return false; - } - FreeFormSupported freeFormSupported = blockFamily.getAnnotation(FreeFormSupported.class); - if (freeFormSupported == null) { - return false; - } - return freeFormSupported.value(); - } } diff --git a/engine/src/main/java/org/terasology/world/block/family/FreeFormSupported.java b/engine/src/main/java/org/terasology/world/block/family/FreeFormSupported.java deleted file mode 100644 index d1792f604ef..00000000000 --- a/engine/src/main/java/org/terasology/world/block/family/FreeFormSupported.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018 MovingBlocks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.terasology.world.block.family; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation used to mark if a {@link BlockFamily} supports blocks that have freeform shapes. - * It takes an argument of the boolean type to mark if the annotated BlockFamily supports freeform shapes. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface FreeFormSupported { - boolean value() default false; -} diff --git a/engine/src/main/java/org/terasology/world/block/family/FreeformFamily.java b/engine/src/main/java/org/terasology/world/block/family/FreeformFamily.java index 8b753f90571..e69de29bb2d 100644 --- a/engine/src/main/java/org/terasology/world/block/family/FreeformFamily.java +++ b/engine/src/main/java/org/terasology/world/block/family/FreeformFamily.java @@ -1,130 +0,0 @@ -// Copyright 2021 The Terasology Foundation -// SPDX-License-Identifier: Apache-2.0 -package org.terasology.world.block.family; - -import com.google.common.collect.Maps; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.terasology.math.Rotation; -import org.terasology.math.Side; -import org.terasology.naming.Name; -import org.terasology.world.block.Block; -import org.terasology.world.block.BlockBuilderHelper; -import org.terasology.world.block.BlockUri; -import org.terasology.world.block.loader.BlockFamilyDefinition; -import org.terasology.world.block.shapes.BlockShape; - -import java.util.Arrays; -import java.util.Locale; -import java.util.Map; - -/** - * A freeform family is a pseudo block family that can be combined with any block shape to produce an actual block family. - */ -@RegisterBlockFamily("freeform") -@FreeFormSupported(true) -public class FreeformFamily extends AbstractBlockFamily implements SideDefinedBlockFamily { - private static final Logger logger = LoggerFactory.getLogger(FreeformFamily.class); - - private Map blocks = Maps.newEnumMap(Side.class); - private Block archetypeBlock; - - public FreeformFamily(BlockFamilyDefinition definition, BlockShape shape, BlockBuilderHelper blockBuilder) { - super(definition, shape, blockBuilder); - BlockUri uri; - if (CUBE_SHAPE_URN.equals(shape.getUrn())) { - uri = new BlockUri(definition.getUrn()); - } else { - uri = new BlockUri(definition.getUrn(), shape.getUrn()); - } - if (shape.isCollisionYawSymmetric()) { - archetypeBlock = blockBuilder.constructSimpleBlock(definition, shape, uri, this); - } else { - for (Rotation rot : Rotation.horizontalRotations()) { - Side side = rot.rotate(Side.FRONT); - Block block = blockBuilder.constructTransformedBlock(definition, shape, side.toString().toLowerCase(Locale.ENGLISH), rot, - new BlockUri(uri, new Name(side.name())), this); - if (block == null) { - throw new IllegalArgumentException("Missing block for side: " + side.toString()); - } - blocks.put(side, block); - } - } - - setBlockUri(uri); - } - - public FreeformFamily(BlockFamilyDefinition blockFamilyDefinition, BlockBuilderHelper blockBuilderHelper) { - super(blockFamilyDefinition, blockBuilderHelper); - throw new UnsupportedOperationException("Shape expected"); - } - - @Override - public Block getBlockForPlacement(BlockPlacementData data) { - if (archetypeBlock != null) { - return archetypeBlock; - } - - if (data.attachmentSide.isHorizontal()) { - return blocks.get(data.attachmentSide); - } else { - Side blockDirection = Side.inDirection(-data.viewingDirection.x(), 0, -data.viewingDirection.z()); - return blocks.get(blockDirection); - } - } - - @Override - public Block getArchetypeBlock() { - if (archetypeBlock == null) { - return blocks.get(this.getArchetypeSide()); - } - return archetypeBlock; - } - - protected Side getArchetypeSide() { - return Side.FRONT; - } - - @Override - public Block getBlockFor(BlockUri blockUri) { - if (archetypeBlock == null && getURI().equals(blockUri.getFamilyUri())) { - try { - Side side = Side.valueOf(blockUri.getIdentifier().toString().toUpperCase(Locale.ENGLISH)); - return blocks.get(side); - } catch (IllegalArgumentException e) { - logger.error("can't find block with URI: {}", blockUri, e); - return null; - } - - } - return archetypeBlock; - } - - @Override - public Iterable getBlocks() { - if (archetypeBlock == null) { - return blocks.values(); - } - return Arrays.asList(archetypeBlock); - } - - @Override - public Block getBlockForSide(Side side) { - if (archetypeBlock == null) { - return blocks.get(side); - } - return archetypeBlock; - } - - @Override - public Side getSide(Block block) { - if (archetypeBlock == null) { - for (Map.Entry sideBlockEntry : blocks.entrySet()) { - if (block == sideBlockEntry.getValue()) { - return sideBlockEntry.getKey(); - } - } - } - return archetypeBlock.getDirection(); - } -} diff --git a/engine/src/main/java/org/terasology/world/block/internal/BlockManagerImpl.java b/engine/src/main/java/org/terasology/world/block/internal/BlockManagerImpl.java index 025aec86e1d..ade97f665d9 100644 --- a/engine/src/main/java/org/terasology/world/block/internal/BlockManagerImpl.java +++ b/engine/src/main/java/org/terasology/world/block/internal/BlockManagerImpl.java @@ -66,8 +66,6 @@ public class BlockManagerImpl extends BlockManager { private AtomicReference registeredBlockInfo = new AtomicReference<>(new RegisteredState()); - private Set listeners = Sets.newLinkedHashSet(); - private boolean generateNewIds; private AtomicInteger nextId = new AtomicInteger(1); @@ -88,6 +86,11 @@ public BlockManagerImpl(WorldAtlas atlas, this.blockBuilder = new BlockBuilder(atlas); } + /** + * Put all the existing families and blocks from the manifest back with the + * same IDs, and if this is the authority (singleplayer or server), check + * for any other block family definitions and register all of those as well. + */ public void initialise(List registeredBlockFamilies, Map knownBlockMappings) { @@ -100,27 +103,50 @@ public void initialise(List registeredBlockFamilies, for (String rawFamilyUri : registeredBlockFamilies) { try { - BlockUri familyUri = new BlockUri(rawFamilyUri); - Optional family = loadFamily(familyUri); - if (family.isPresent()) { - for (Block block : family.get().getBlocks()) { - Short id = knownBlockMappings.get(block.getURI().toString()); - if (id != null) { - block.setId(id); - } else { - logger.error("Missing id for block {} in provided family {}", block.getURI(), family.get().getURI()); - if (generateNewIds) { - block.setId(getNextId()); - } else { - block.setId(UNKNOWN_ID); + addFamily(new BlockUri(rawFamilyUri), knownBlockMappings); + } catch (BlockUriParseException e) { + logger.error("Failed to parse block family, skipping", e); + } + } + if (generateNewIds) { + Set availableFamilies = assetManager.getAvailableAssets(BlockFamilyDefinition.class); + for (ResourceUrn familyUrn : availableFamilies) { + BlockFamily existingFamily = getBlockFamily(new BlockUri(familyUrn)); + if (null == existingFamily) { + assetManager.getAsset(familyUrn, BlockFamilyDefinition.class).ifPresent(def -> { + if (def.isFreeform()) { + for (BlockShape shape : def.getData().getBaseSection().getShapes()) { + addFamily(new BlockUri(familyUrn, shape.getUrn()), knownBlockMappings); } + } else { + addFamily(new BlockUri(familyUrn), knownBlockMappings); } + }); + } + } + } + } + + /** + * Load a family from its assets and then register it and its blocks, respecting existing block IDs. + */ + private void addFamily(BlockUri familyUri, Map knownBlockMappings) { + Optional family = loadFamily(familyUri); + if (family.isPresent()) { + for (Block block : family.get().getBlocks()) { + Short id = knownBlockMappings.get(block.getURI().toString()); + if (id != null) { + block.setId(id); + } else { + logger.error("Missing id for block {} in provided family {}", block.getURI(), family.get().getURI()); + if (generateNewIds) { + block.setId(getNextId()); + } else { + block.setId(UNKNOWN_ID); } - registerFamily(family.get()); } - } catch (BlockUriParseException e) { - logger.error("Failed to parse block family, skipping", e); } + registerFamily(family.get()); } } @@ -149,35 +175,9 @@ private Block getAirBlock() { return airBlock; } - public void subscribe(BlockRegistrationListener listener) { - this.listeners.add(listener); - } - - public void unsubscribe(BlockRegistrationListener listener) { - this.listeners.remove(listener); - } - - public void receiveFamilyRegistration(BlockUri familyUri, Map registration) { - Optional family = loadFamily(familyUri); - if (family.isPresent()) { - lock.lock(); - try { - for (Block block : family.get().getBlocks()) { - Integer id = registration.get(block.getURI().toString()); - if (id != null) { - block.setId((short) id.intValue()); - } else { - logger.error("Missing id for block {} in registered family {}", block.getURI(), familyUri); - block.setId(UNKNOWN_ID); - } - } - registerFamily(family.get()); - } finally { - lock.unlock(); - } - } - } - + /** + * Add an already generated family and all its contained blocks to the lists. + */ @VisibleForTesting protected void registerFamily(BlockFamily family) { Preconditions.checkNotNull(family); @@ -193,11 +193,11 @@ protected void registerFamily(BlockFamily family) { } finally { lock.unlock(); } - for (BlockRegistrationListener listener : listeners) { - listener.onBlockFamilyRegistered(family); - } } + /** + * Add an already generated block to the lists. + */ private void registerBlock(Block block, RegisteredState newState) { if (block.getId() != UNKNOWN_ID) { logger.info("Registered Block {} with id {}", block, block.getId()); @@ -220,6 +220,9 @@ public Map getBlockIdMap() { return result; } + /** + * Recall the family registered with the given name. + */ @Override public BlockFamily getBlockFamily(String uri) { if (!uri.contains(":")) { @@ -244,35 +247,20 @@ public BlockFamily getBlockFamily(String uri) { return getBlockFamily(AIR_ID); } + /** + * Recall the family registered with the given name. + */ @Override public BlockFamily getBlockFamily(BlockUri uri) { if (uri.getShapeUrn().isPresent() && uri.getShapeUrn().get().equals(CUBE_SHAPE_URN)) { return getBlockFamily(uri.getShapelessUri()); } - BlockFamily family = registeredBlockInfo.get().registeredFamilyByUri.get(uri); - if (family == null && generateNewIds) { - Optional newFamily = loadFamily(uri); - if (newFamily.isPresent()) { - lock.lock(); - try { - for (Block block : newFamily.get().getBlocks()) { - block.setId(getNextId()); - } - registerFamily(newFamily.get()); - - } catch (Exception ex) { - // A family can fail to register if the block is missing uri or list of categories, - // but can fail to register if the family throws an error for any reason - logger.error("Failed to register block family '{}'", newFamily, ex); - } finally { - lock.unlock(); - } - return newFamily.get(); - } - } - return family; + return registeredBlockInfo.get().registeredFamilyByUri.get(uri); } + /** + * Create a block family by loading the relevant assets. + */ private Optional loadFamily(BlockUri uri) { Optional familyDef = assetManager.getAsset(uri.getBlockFamilyDefinitionUrn(), BlockFamilyDefinition.class); if (familyDef.isPresent() && familyDef.get().isLoadable()) { @@ -287,7 +275,7 @@ private Optional loadFamily(BlockUri uri) { if (shape.isPresent()) { return Optional.of(familyDef.get().createFamily(shape.get(), blockBuilder)); } - } else if (!familyDef.get().isFreeform()) { + } else { return Optional.of(familyDef.get().createFamily(blockBuilder)); } } else { @@ -296,6 +284,9 @@ private Optional loadFamily(BlockUri uri) { return Optional.empty(); } + /** + * Recall the block registered with the given name. + */ @Override public Block getBlock(String uri) { try { @@ -306,6 +297,9 @@ public Block getBlock(String uri) { } } + /** + * Recall the block registered with the given name. + */ @Override public Block getBlock(BlockUri uri) { if (uri.getShapeUrn().isPresent() && uri.getShapeUrn().get().equals(CUBE_SHAPE_URN)) { @@ -313,18 +307,15 @@ public Block getBlock(BlockUri uri) { } Block block = registeredBlockInfo.get().blocksByUri.get(uri); if (block == null) { - // Check if partially registered by getting the block family - BlockFamily family = getBlockFamily(uri.getFamilyUri()); - if (family != null) { - block = family.getBlockFor(uri); - } - if (block == null) { - return getAirBlock(); - } + throw new NullPointerException("Attempt to fetch block with unknown uri '" + uri + "'"); + } else { + return block; } - return block; } + /** + * Recall the block registered with the given id. + */ @Override public Block getBlock(short id) { Block result = registeredBlockInfo.get().blocksById.get(id); diff --git a/engine/src/main/java/org/terasology/world/block/internal/BlockPrefabManager.java b/engine/src/main/java/org/terasology/world/block/internal/BlockPrefabManager.java deleted file mode 100644 index dc9ecdcc181..00000000000 --- a/engine/src/main/java/org/terasology/world/block/internal/BlockPrefabManager.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2013 MovingBlocks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.terasology.world.block.internal; - -import org.terasology.entitySystem.Component; -import org.terasology.entitySystem.entity.EntityManager; -import org.terasology.entitySystem.metadata.ComponentMetadata; -import org.terasology.entitySystem.prefab.Prefab; -import org.terasology.world.block.Block; -import org.terasology.world.block.BlockManager; -import org.terasology.world.block.family.BlockFamily; - -import java.util.Optional; - -/** - */ -public class BlockPrefabManager implements BlockRegistrationListener { - - private EntityManager entityManager; - private BlockManager blockManager; - - public BlockPrefabManager(EntityManager entityManager, BlockManager blockManager) { - this.entityManager = entityManager; - this.blockManager = blockManager; - - updateExistingBlocks(); - } - - @Override - public void onBlockFamilyRegistered(BlockFamily family) { - for (Block block : family.getBlocks()) { - updateBlock(block); - } - } - - private void updateExistingBlocks() { - for (BlockFamily blockFamily : blockManager.listRegisteredBlockFamilies()) { - for (Block block : blockFamily.getBlocks()) { - updateBlock(block); - } - } - } - - private void updateBlock(Block block) { - Optional prefab = block.getPrefab(); - boolean keepActive = block.isKeepActive(); - boolean requiresLifecycleEvents = false; - if (prefab.isPresent()) { - for (Component comp : prefab.get().iterateComponents()) { - ComponentMetadata metadata = entityManager.getComponentLibrary().getMetadata(comp.getClass()); - if (metadata.isForceBlockActive()) { - keepActive = true; - break; - } - if (metadata.isBlockLifecycleEventsRequired()) { - requiresLifecycleEvents = true; - } - } - } - block.setKeepActive(keepActive); - block.setLifecycleEventsRequired(requiresLifecycleEvents && !keepActive); - } -} diff --git a/engine/src/main/java/org/terasology/world/block/internal/BlockRegistrationListener.java b/engine/src/main/java/org/terasology/world/block/internal/BlockRegistrationListener.java deleted file mode 100644 index a84a9a2e510..00000000000 --- a/engine/src/main/java/org/terasology/world/block/internal/BlockRegistrationListener.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2013 MovingBlocks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.terasology.world.block.internal; - -import org.terasology.world.block.family.BlockFamily; - -@FunctionalInterface -public interface BlockRegistrationListener { - - void onBlockFamilyRegistered(BlockFamily family); -} diff --git a/engine/src/main/java/org/terasology/world/block/loader/AutoBlockProvider.java b/engine/src/main/java/org/terasology/world/block/loader/AutoBlockProvider.java index a154cdac234..d0d43b2e907 100644 --- a/engine/src/main/java/org/terasology/world/block/loader/AutoBlockProvider.java +++ b/engine/src/main/java/org/terasology/world/block/loader/AutoBlockProvider.java @@ -22,7 +22,7 @@ import org.terasology.assets.module.annotations.RegisterAssetDataProducer; import org.terasology.naming.Name; import org.terasology.world.block.BlockPart; -import org.terasology.world.block.family.FreeformFamily; +import org.terasology.world.block.family.SymmetricFamily; import org.terasology.world.block.sounds.BlockSounds; import org.terasology.world.block.tiles.BlockTile; @@ -74,7 +74,7 @@ public Optional getAssetData(ResourceUrn urn) throws data.getBaseSection().getBlockTiles().put(part, blockTile.get()); } data.getBaseSection().setSounds(assetManager.getAsset("engine:default", BlockSounds.class).get()); - data.setBlockFamily(FreeformFamily.class); + data.setBlockFamily(SymmetricFamily.class); return Optional.of(data); } return Optional.empty(); diff --git a/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinition.java b/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinition.java index 15c8d65f4d4..c51df87425d 100644 --- a/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinition.java +++ b/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinition.java @@ -21,8 +21,11 @@ import org.terasology.assets.ResourceUrn; import org.terasology.module.sandbox.API; import org.terasology.world.block.BlockBuilderHelper; +import org.terasology.world.block.family.AbstractBlockFamily; import org.terasology.world.block.family.BlockFamily; import org.terasology.world.block.family.BlockFamilyLibrary; +import org.terasology.world.block.family.HorizontalFamily; +import org.terasology.world.block.family.SymmetricFamily; import org.terasology.world.block.shapes.BlockShape; import java.util.Collections; @@ -48,17 +51,25 @@ public List getCategories() { } public boolean isFreeform() { - return BlockFamilyLibrary.isFreeformSupported(getData().getBlockFamily()); + return data.getBaseSection().getShapes() != null; } public BlockFamily createFamily(BlockBuilderHelper blockBuilderHelper) { - Preconditions.checkState(!isFreeform()); - return BlockFamilyLibrary.createFamily(getData().getBlockFamily(), this, blockBuilderHelper); + return BlockFamilyLibrary.createFamily(getFamilyForShape(data.getBaseSection().getShape()), this, blockBuilderHelper); } public BlockFamily createFamily(BlockShape shape, BlockBuilderHelper blockBuilderHelper) { - Preconditions.checkState(isFreeform()); - return BlockFamilyLibrary.createFamily(getData().getBlockFamily(), this, shape, blockBuilderHelper); + return BlockFamilyLibrary.createFamily(getFamilyForShape(shape), this, shape, blockBuilderHelper); + } + + private Class getFamilyForShape(BlockShape shape) { + if (data.getBlockFamily() != null) { + return data.getBlockFamily(); + } else if (shape.isCollisionYawSymmetric()) { + return SymmetricFamily.class; + } else { + return HorizontalFamily.class; + } } @@ -67,6 +78,6 @@ public BlockFamilyDefinitionData getData() { } public boolean isLoadable() { - return getData().isValid() && !getData().isTemplate(); + return !data.isTemplate(); } } diff --git a/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinitionData.java b/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinitionData.java index 604cc474aae..e9f97c974c9 100644 --- a/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinitionData.java +++ b/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinitionData.java @@ -47,10 +47,6 @@ public BlockFamilyDefinitionData(BlockFamilyDefinitionData other) { this.categories = Lists.newArrayList(other.categories); } - public boolean isValid() { - return family != null; - } - public boolean isTemplate() { return template; } diff --git a/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinitionFormat.java b/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinitionFormat.java index bca4f58b1c4..5f1701c5ffe 100644 --- a/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinitionFormat.java +++ b/engine/src/main/java/org/terasology/world/block/loader/BlockFamilyDefinitionFormat.java @@ -3,8 +3,10 @@ package org.terasology.world.block.loader; import com.google.common.base.Charsets; +import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; @@ -32,7 +34,6 @@ import org.terasology.world.block.BlockPart; import org.terasology.world.block.family.BlockFamily; import org.terasology.world.block.family.BlockFamilyLibrary; -import org.terasology.world.block.family.FreeformFamily; import org.terasology.world.block.family.HorizontalFamily; import org.terasology.world.block.family.MultiSection; import org.terasology.world.block.family.SymmetricFamily; @@ -44,6 +45,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.Locale; @@ -82,14 +84,8 @@ public BlockFamilyDefinitionData load(ResourceUrn resourceUrn, List applyDefaults(resourceUrn, section)); if (!data.isTemplate()) { - if (data.getBlockFamily() == null && data.getBaseSection().getShape() != null) { - if (data.getBaseSection().getShape().isCollisionYawSymmetric()) { - data.setBlockFamily(SymmetricFamily.class); - } else { - data.setBlockFamily(HorizontalFamily.class); - } - } else if (data.getBlockFamily() == null) { - data.setBlockFamily(FreeformFamily.class); + if (data.getBlockFamily() == null && data.getBaseSection().getShape() == null && data.getBaseSection().getShapes() == null) { + data.getBaseSection().setShapes(Lists.newArrayList(assetManager.getAsset("engine:cube", BlockShape.class).get())); } } @@ -202,6 +198,7 @@ private void deserializeSectionDefinitionData(SectionDefinitionData data, JsonOb } setObject(data::setShape, jsonObject, "shape", BlockShape.class, context); + setArray(data::setShapes, jsonObject, "shapes", BlockShape.class, context); setBoolean(data::setWater, jsonObject, "water"); setBoolean(data::setGrass, jsonObject, "grass"); setBoolean(data::setIce, jsonObject, "ice"); @@ -287,16 +284,21 @@ private void setObject(Consumer setter, JsonObject jsonObject, String nam } } + private void setArray(Consumer> setter, JsonObject jsonObject, String name, Type type, JsonDeserializationContext context) { + JsonArray array = jsonObject.getAsJsonArray(name); + if (array != null) { + ArrayList list = new ArrayList<>(); + array.forEach(t -> list.add(context.deserialize(t, type))); + setter.accept(list); + } + } + private BlockFamilyDefinitionData createBaseData(JsonObject jsonObject) { JsonPrimitive basedOn = jsonObject.getAsJsonPrimitive("basedOn"); if (basedOn != null && !basedOn.getAsString().isEmpty()) { Optional baseDef = assetManager.getAsset(basedOn.getAsString(), BlockFamilyDefinition.class); if (baseDef.isPresent()) { - BlockFamilyDefinitionData data = baseDef.get().getData(); - if (data.getBlockFamily() == FreeformFamily.class) { - data.setBlockFamily(null); - } - return data; + return baseDef.get().getData(); } else { throw new JsonParseException("Unable to resolve based block definition '" + basedOn.getAsString() + "'"); } diff --git a/engine/src/main/java/org/terasology/world/block/loader/SectionDefinitionData.java b/engine/src/main/java/org/terasology/world/block/loader/SectionDefinitionData.java index b29f80433c0..da200560853 100644 --- a/engine/src/main/java/org/terasology/world/block/loader/SectionDefinitionData.java +++ b/engine/src/main/java/org/terasology/world/block/loader/SectionDefinitionData.java @@ -23,6 +23,7 @@ import org.terasology.world.block.sounds.BlockSounds; import org.terasology.world.block.tiles.BlockTile; +import java.util.ArrayList; import java.util.EnumMap; /** @@ -63,6 +64,7 @@ public class SectionDefinitionData { private InventoryData inventory = new InventoryData(); private BlockShape shape; + private ArrayList shapes; private boolean water; private boolean grass; private boolean ice; @@ -104,6 +106,7 @@ public SectionDefinitionData(SectionDefinitionData other) { this.inventory = new InventoryData(other.inventory); this.shape = other.shape; + this.shapes = other.shapes; this.water = other.water; this.grass = other.grass; @@ -312,6 +315,14 @@ public void setShape(BlockShape shape) { this.shape = shape; } + public ArrayList getShapes() { + return shapes; + } + + public void setShapes(ArrayList shapes) { + this.shapes = shapes; + } + public boolean isWater() { return water; } diff --git a/engine/src/main/java/org/terasology/world/block/shapes/BlockShapeImpl.java b/engine/src/main/java/org/terasology/world/block/shapes/BlockShapeImpl.java index 3bb908a4172..ad57e6f921e 100644 --- a/engine/src/main/java/org/terasology/world/block/shapes/BlockShapeImpl.java +++ b/engine/src/main/java/org/terasology/world/block/shapes/BlockShapeImpl.java @@ -114,6 +114,5 @@ public boolean isCollisionYawSymmetric() { private Rotation applySymmetry(Rotation rot) { return Rotation.rotate(yawSymmetric ? Yaw.NONE : rot.getYaw(), pitchSymmetric ? Pitch.NONE : rot.getPitch(), rollSymmetric ? Roll.NONE : rot.getRoll()); } - } diff --git a/engine/src/main/java/org/terasology/world/block/typeEntity/BlockTypeEntityGenerator.java b/engine/src/main/java/org/terasology/world/block/typeEntity/BlockTypeEntityGenerator.java deleted file mode 100644 index e84b4c661bd..00000000000 --- a/engine/src/main/java/org/terasology/world/block/typeEntity/BlockTypeEntityGenerator.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2013 MovingBlocks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.terasology.world.block.typeEntity; - -import org.terasology.entitySystem.Component; -import org.terasology.entitySystem.entity.EntityBuilder; -import org.terasology.entitySystem.entity.EntityManager; -import org.terasology.entitySystem.entity.EntityRef; -import org.terasology.entitySystem.prefab.Prefab; -import org.terasology.entitySystem.prefab.PrefabManager; -import org.terasology.network.NetworkComponent; -import org.terasology.world.block.Block; -import org.terasology.world.block.BlockManager; -import org.terasology.world.block.family.BlockFamily; -import org.terasology.world.block.internal.BlockRegistrationListener; - -import java.util.Optional; - -/** - */ -public class BlockTypeEntityGenerator implements BlockRegistrationListener { - - private EntityManager entityManager; - private PrefabManager prefabManager; - private BlockManager blockManager; - private Prefab blockTypePrefab; - - public BlockTypeEntityGenerator(EntityManager entityManager, BlockManager blockManager) { - this.entityManager = entityManager; - this.prefabManager = entityManager.getPrefabManager(); - this.blockManager = blockManager; - blockTypePrefab = entityManager.getPrefabManager().getPrefab("engine:blockType"); - - connectExistingEntities(); - generateForExistingBlocks(); - } - - private void connectExistingEntities() { - for (EntityRef entity : entityManager.getEntitiesWith(BlockTypeComponent.class)) { - BlockTypeComponent blockTypeComp = entity.getComponent(BlockTypeComponent.class); - if (blockTypeComp.block == null) { - entity.destroy(); - } else { - blockTypeComp.block.setEntity(entity); - } - } - } - - private void generateForExistingBlocks() { - for (BlockFamily blockFamily : blockManager.listRegisteredBlockFamilies()) { - for (Block block : blockFamily.getBlocks()) { - if (!block.getEntity().exists()) { - generateBlockTypeEntity(block); - } - } - } - } - - @Override - public void onBlockFamilyRegistered(BlockFamily family) { - for (Block block : family.getBlocks()) { - generateBlockTypeEntity(block); - } - } - - private void generateBlockTypeEntity(Block block) { - EntityBuilder builder = entityManager.newBuilder(blockTypePrefab); - builder.getComponent(BlockTypeComponent.class).block = block; - // TODO: Copy across settings as necessary - Optional prefab = block.getPrefab(); - if (prefab.isPresent()) { - for (Component comp : prefab.get().iterateComponents()) { - if (!(comp instanceof NetworkComponent)) { - builder.addComponent(entityManager.getComponentLibrary().copy(comp)); - } - } - } - block.setEntity(builder.build()); - } -} diff --git a/engine/src/main/protobuf/NetMessage.proto b/engine/src/main/protobuf/NetMessage.proto index 0300119d8fb..1df6e1dffb1 100644 --- a/engine/src/main/protobuf/NetMessage.proto +++ b/engine/src/main/protobuf/NetMessage.proto @@ -17,13 +17,12 @@ message NetMessage { optional ServerInfoRequest serverInfoRequest = 15; optional ServerInfoMessage serverInfo = 16; - repeated BlockFamilyRegisteredMessage blockFamilyRegistered = 17; - optional JoinMessage join = 18; - repeated ModuleRequest moduleRequest = 19; - optional ModuleDataHeader moduleDataHeader = 20; - optional ModuleData moduleData = 21; - optional JoinCompleteMessage joinComplete = 22; + optional JoinMessage join = 17; + repeated ModuleRequest moduleRequest = 18; + optional ModuleDataHeader moduleDataHeader = 19; + optional ModuleData moduleData = 20; + optional JoinCompleteMessage joinComplete = 21; // Authentication optional HandshakeHello handshakeHello = 100; @@ -77,13 +76,6 @@ message Certificate { extensions 5000 to max; } -message BlockFamilyRegisteredMessage { - repeated string blockUri = 1; - repeated int32 blockId = 2; - - extensions 5000 to max; -} - message InvalidateChunkMessage { optional Vector3iData pos = 1;