@Override
  public boolean step() {
    NetworkSystem networkSystem = context.get(NetworkSystem.class);
    WorldAtlas atlas =
        new WorldAtlasImpl(context.get(Config.class).getRendering().getMaxTextureAtlasResolution());
    context.put(WorldAtlas.class, atlas);

    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);
    }
    context.put(BlockManager.class, blockManager);
    context
        .get(TypeSerializationLibrary.class)
        .add(Block.class, new BlockTypeHandler(blockManager));
    context
        .get(TypeSerializationLibrary.class)
        .add(BlockFamily.class, new BlockFamilyTypeHandler(blockManager));

    blockManager.initialise(
        gameManifest.getRegisteredBlockFamilies(), gameManifest.getBlockIdMap());

    return true;
  }
 private void processBlockChanges(NetData.NetMessage message) {
   for (NetData.BlockChangeMessage blockChange : message.getBlockChangeList()) {
     Block newBlock = blockManager.getBlock((short) blockChange.getNewBlock());
     logger.debug("Received block change to {}", newBlock);
     // TODO: Store changes to blocks that aren't ready to be modified (the surrounding chunks
     // aren't available)
     WorldProvider worldProvider = CoreRegistry.get(WorldProvider.class);
     Vector3i pos = NetMessageUtil.convert(blockChange.getPos());
     if (worldProvider.isBlockRelevant(pos)) {
       worldProvider.setBlock(pos, newBlock);
     } else {
       awaitingChunkReadyBlockUpdates.put(ChunkMath.calcChunkPos(pos), blockChange);
     }
   }
 }
  @Test
  public void testActiveBlockNotCleanedUp() {
    Block testBlock = new Block();
    testBlock.setKeepActive(true);
    BlockFamily blockFamily = new SymmetricFamily(new BlockUri("test:keepActive"), testBlock);
    blockManager.addBlockFamily(blockFamily, true);
    worldStub.setBlock(Vector3i.zero(), testBlock);

    BlockEventChecker checker = new BlockEventChecker();
    entityManager.getEventSystem().registerEventHandler(checker);

    EntityRef blockEntity = worldProvider.getBlockEntityAt(new Vector3i(0, 0, 0));
    worldProvider.update(1.0f);
    assertTrue(blockEntity.exists());
    assertTrue(blockEntity.isActive());
    assertTrue(checker.addedReceived);
    assertTrue(checker.activateReceived);
  }
  @Override
  public void onChunkReady(Vector3i chunkPos) {
    WorldProvider worldProvider = CoreRegistry.get(WorldProvider.class);

    List<NetData.BlockChangeMessage> updateBlockMessages =
        awaitingChunkReadyBlockUpdates.removeAll(chunkPos);
    for (NetData.BlockChangeMessage message : updateBlockMessages) {
      Vector3i pos = NetMessageUtil.convert(message.getPos());
      Block newBlock = blockManager.getBlock((short) message.getNewBlock());
      worldProvider.setBlock(pos, newBlock);
    }

    List<NetData.BiomeChangeMessage> updateBiomeMessages =
        awaitingChunkReadyBiomeUpdates.removeAll(chunkPos);
    for (NetData.BiomeChangeMessage message : updateBiomeMessages) {
      Vector3i pos = NetMessageUtil.convert(message.getPos());
      Biome newBiome = biomeManager.getBiomeByShortId((short) message.getNewBiome());
      worldProvider.setBiome(pos, newBiome);
    }
  }
 private void processBlockRegistrations(NetData.NetMessage message) {
   for (NetData.BlockFamilyRegisteredMessage blockFamily :
       message.getBlockFamilyRegisteredList()) {
     if (blockFamily.getBlockIdCount() != blockFamily.getBlockUriCount()) {
       logger.error("Received block registration with mismatched id<->uri mapping");
     } else if (blockFamily.getBlockUriCount() == 0) {
       logger.error("Received empty block registration");
     } else {
       try {
         BlockUri family = new BlockUri(blockFamily.getBlockUri(0)).getFamilyUri();
         Map<String, Integer> 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));
       }
     }
   }
 }
  @Before
  public void setup() {
    GameThread.setGameThread();
    AssetManager assetManager =
        CoreRegistry.put(
            AssetManager.class,
            new AssetManager(new ModuleManagerImpl(new ModuleSecurityManager())));
    assetManager.setAssetFactory(
        AssetType.PREFAB,
        new AssetFactory<PrefabData, Prefab>() {

          @Override
          public Prefab buildAsset(AssetUri uri, PrefabData data) {
            return new PojoPrefab(uri, data);
          }
        });
    EntitySystemBuilder builder = new EntitySystemBuilder();

    CoreRegistry.put(ComponentSystemManager.class, mock(ComponentSystemManager.class));

    blockManager =
        CoreRegistry.put(
            BlockManager.class,
            new BlockManagerImpl(mock(WorldAtlas.class), new DefaultBlockFamilyFactoryRegistry()));
    NetworkSystem networkSystem = mock(NetworkSystem.class);
    when(networkSystem.getMode()).thenReturn(NetworkMode.NONE);
    entityManager = builder.build(moduleManager, networkSystem, new ReflectionReflectFactory());
    worldStub = new WorldProviderCoreStub(BlockManager.getAir());
    worldProvider = new EntityAwareWorldProvider(worldStub, entityManager);

    plainBlock = new Block();
    blockManager.addBlockFamily(
        new SymmetricFamily(new BlockUri("test:plainBlock"), plainBlock), true);

    blockWithString = new Block();
    PrefabData prefabData = new PrefabData();
    prefabData.addComponent(new StringComponent("Test"));
    Assets.generateAsset(
        new AssetUri(AssetType.PREFAB, "test:prefabWithString"), prefabData, Prefab.class);
    blockWithString.setPrefab("test:prefabWithString");
    blockManager.addBlockFamily(
        new SymmetricFamily(new BlockUri("test:blockWithString"), blockWithString), true);

    blockWithDifferentString = new Block();
    prefabData = new PrefabData();
    prefabData.addComponent(new StringComponent("Test2"));
    Assets.generateAsset(
        new AssetUri(AssetType.PREFAB, "test:prefabWithDifferentString"), prefabData, Prefab.class);
    blockWithDifferentString.setPrefab("test:prefabWithDifferentString");
    blockManager.addBlockFamily(
        new SymmetricFamily(
            new BlockUri("test:blockWithDifferentString"), blockWithDifferentString),
        true);

    blockWithRetainedComponent = new Block();
    prefabData = new PrefabData();
    prefabData.addComponent(new RetainedOnBlockChangeComponent(3));
    Assets.generateAsset(
        new AssetUri(AssetType.PREFAB, "test:prefabWithRetainedComponent"),
        prefabData,
        Prefab.class);
    blockWithRetainedComponent.setPrefab("test:prefabWithRetainedComponent");
    blockManager.addBlockFamily(
        new SymmetricFamily(
            new BlockUri("test:blockWithRetainedComponent"), blockWithRetainedComponent),
        true);

    blockInFamilyOne = new Block();
    blockInFamilyOne.setKeepActive(true);
    blockInFamilyOne.setPrefab("test:prefabWithString");
    blockInFamilyTwo = new Block();
    blockInFamilyTwo.setPrefab("test:prefabWithString");
    blockInFamilyTwo.setKeepActive(true);
    blockManager.addBlockFamily(
        new HorizontalBlockFamily(
            new BlockUri("test:blockFamily"),
            ImmutableMap.<Side, Block>of(
                Side.FRONT,
                blockInFamilyOne,
                Side.LEFT,
                blockInFamilyTwo,
                Side.RIGHT,
                blockInFamilyTwo,
                Side.BACK,
                blockInFamilyOne),
            Collections.<String>emptyList()),
        true);

    keepActiveBlock = new Block();
    keepActiveBlock.setKeepActive(true);
    keepActiveBlock.setPrefab("test:prefabWithString");
    blockManager.addBlockFamily(
        new SymmetricFamily(new BlockUri("test:keepActiveBlock"), keepActiveBlock), true);

    worldProvider.initialise();
  }