public EntityRef newInstance(BlockFamily blockFamily, EntityRef blockEntity) { if (blockFamily == null) { return EntityRef.NULL; } EntityBuilder builder = entityManager.newBuilder("engine:blockItemBase"); if (blockFamily.getArchetypeBlock().getLuminance() > 0) { builder.addComponent(new LightComponent()); } // Copy the components from block prefab into the block item for (Component component : blockEntity.iterateComponents()) { if (component.getClass().getAnnotation(AddToBlockBasedItem.class) != null) { builder.addComponent(entityManager.getComponentLibrary().copy(component)); } } ItemComponent item = builder.getComponent(ItemComponent.class); if (blockFamily.getArchetypeBlock().isStackable()) { item.stackId = "block:" + blockFamily.getURI().toString(); item.stackCount = (byte) 1; } BlockItemComponent blockItem = builder.getComponent(BlockItemComponent.class); blockItem.blockFamily = blockFamily; return builder.build(); }
@Override public EntityRef deserializeEntity(EntityData.Entity entityData) { EntityRef entity = entityManager.createEntityRefWithId(entityData.getId()); if (entityData.hasParentPrefab() && !entityData.getParentPrefab().isEmpty() && prefabManager.exists(entityData.getParentPrefab())) { Prefab prefab = prefabManager.getPrefab(entityData.getParentPrefab()); for (Component component : prefab.listComponents()) { String componentName = ComponentUtil.getComponentClassName(component.getClass()); if (!containsIgnoreCase(componentName, entityData.getRemovedComponentList())) { entity.addComponent(componentLibrary.copy(component)); } } entity.addComponent(new EntityInfoComponent(entityData.getParentPrefab())); } for (EntityData.Component componentData : entityData.getComponentList()) { Class<? extends Component> componentClass = getComponentClass(componentData); if (componentClass == null) continue; if (!entity.hasComponent(componentClass)) { entity.addComponent(deserializeComponent(componentData)); } else { deserializeComponentOnto(entity.getComponent(componentClass), componentData); } } return entity; }
/** * Use this method instead of {@link #newInstance(BlockFamily)} to modify entity properties like * the persistence flag before it gets created. * * @param blockFamily must not be null */ public EntityBuilder newBuilder(BlockFamily blockFamily, int quantity) { EntityBuilder builder = entityManager.newBuilder("engine:blockItemBase"); if (blockFamily.getArchetypeBlock().getLuminance() > 0) { builder.addComponent(new LightComponent()); } // Copy the components from block prefab into the block item Prefab prefab = Assets.getPrefab(blockFamily.getArchetypeBlock().getPrefab()); if (prefab != null) { for (Component component : prefab.iterateComponents()) { if (component.getClass().getAnnotation(AddToBlockBasedItem.class) != null) { builder.addComponent(entityManager.getComponentLibrary().copy(component)); } } } DisplayNameComponent displayNameComponent = builder.getComponent(DisplayNameComponent.class); displayNameComponent.name = blockFamily.getDisplayName(); ItemComponent item = builder.getComponent(ItemComponent.class); if (blockFamily.getArchetypeBlock().isStackable()) { item.stackId = "block:" + blockFamily.getURI().toString(); item.stackCount = (byte) quantity; } BlockItemComponent blockItem = builder.getComponent(BlockItemComponent.class); blockItem.blockFamily = blockFamily; return builder; }
private void serializeComponentFull( Component component, boolean ignoreIfNoFields, FieldSerializeCheck<Component> fieldCheck, EntityData.PackedEntity.Builder entityData, ByteString.Output entityFieldIds, ByteString.Output componentFieldCounts, boolean componentInitial) { ComponentMetadata<?> componentMetadata = componentLibrary.getMetadata(component.getClass()); if (componentMetadata == null) { logger.error("Unregistered component type: {}", component.getClass()); return; } Serializer serializer = typeSerializationLibrary.getSerializerFor(componentMetadata); byte fieldCount = 0; for (ReplicatedFieldMetadata field : componentMetadata.getFields()) { if (fieldCheck.shouldSerializeField(field, component, componentInitial)) { PersistedData fieldValue = serializer.serialize(field, component, serializationContext); if (!fieldValue.isNull()) { entityFieldIds.write(field.getId()); entityData.addFieldValue(((ProtobufPersistedData) fieldValue).getValue()); fieldCount++; } } } if (fieldCount != 0 || !ignoreIfNoFields) { entityData.addComponentId(idTable.get(component.getClass())); componentFieldCounts.write(fieldCount); } }
private EntityData.Entity serializeEntityFull(EntityRef entityRef) { EntityData.Entity.Builder entity = EntityData.Entity.newBuilder(); entity.setId(entityRef.getId()); for (Component component : entityRef.iterateComponents()) { if (component.getClass().equals(EntityInfoComponent.class)) continue; EntityData.Component componentData = serializeComponent(component); if (componentData != null) { entity.addComponent(componentData); } } return entity.build(); }
private void cleanUpTemporaryEntity(EntityRef entity) { Prefab prefab = entity.getParentPrefab(); for (Component comp : entity.iterateComponents()) { if (!COMMON_BLOCK_COMPONENTS.contains(comp.getClass()) && (prefab == null || !prefab.hasComponent(comp.getClass()))) { entity.removeComponent(comp.getClass()); } } entity.removeComponent(NetworkComponent.class); if (prefab != null) { for (Component comp : prefab.iterateComponents()) { Component currentComp = entity.getComponent(comp.getClass()); if (currentComp == null) { entity.addComponent(entityManager.getComponentLibrary().copy(comp)); } else { ComponentMetadata<?> metadata = entityManager.getComponentLibrary().getMetadata(comp.getClass()); boolean changed = false; for (FieldMetadata field : metadata.getFields()) { Object expected = field.getValue(comp); if (!Objects.equal(expected, field.getValue(currentComp))) { field.setValue(currentComp, expected); changed = true; } } if (changed) { entity.saveComponent(currentComp); } } } } entityManager.destroyEntityWithoutEvents(entity); }
private EntityData.PackedEntity.Builder serializeEntityFull( EntityRef entityRef, FieldSerializeCheck<Component> fieldCheck) { EntityData.PackedEntity.Builder entity = EntityData.PackedEntity.newBuilder(); ByteString.Output fieldIds = ByteString.newOutput(); ByteString.Output componentFieldCounts = ByteString.newOutput(); for (Component component : entityRef.iterateComponents()) { if (!componentSerializeCheck.serialize(componentLibrary.getMetadata(component.getClass()))) { continue; } serializeComponentFull( component, false, fieldCheck, entity, fieldIds, componentFieldCounts, true); } entity.setFieldIds(fieldIds.toByteString()); entity.setComponentFieldCounts(componentFieldCounts.toByteString()); return entity; }
private void serializeComponentDelta( Component oldComponent, Component newComponent, FieldSerializeCheck<Component> fieldCheck, EntityData.PackedEntity.Builder entityData, ByteString.Output entityFieldIds, ByteString.Output componentFieldCounts, boolean componentInitial) { ComponentMetadata<?> componentMetadata = componentLibrary.getMetadata(oldComponent.getClass()); if (componentMetadata == null) { logger.error("Unregistered component type: {}", oldComponent.getClass()); return; } byte fieldCount = 0; Serializer serializer = typeSerializationLibrary.getSerializerFor(componentMetadata); for (ReplicatedFieldMetadata field : componentMetadata.getFields()) { if (fieldCheck.shouldSerializeField(field, newComponent, componentInitial)) { Object oldValue = field.getValue(oldComponent); Object newValue = field.getValue(newComponent); if (!Objects.equal(oldValue, newValue)) { PersistedData data = serializer.serializeValue(field, newValue, serializationContext); if (!data.isNull()) { entityFieldIds.write(field.getId()); entityData.addFieldValue(((ProtobufPersistedData) data).getValue()); fieldCount++; } else { logger.error( "Exception serializing component type: {}, field: {} - returned null", componentMetadata, field); } } } } if (fieldCount > 0) { entityData.addComponentId(idTable.get(newComponent.getClass())); componentFieldCounts.write(fieldCount); } }
/** * Transforms a block entity with the change of block type. This is driven from the delta between * the old and new block type prefabs, but takes into account changes made to the block entity. * * @param blockEntity The entity to update * @param oldType The previous type of the block * @param type The new type of the block */ private void updateBlockEntityComponents( EntityRef blockEntity, Block oldType, Block type, Set<Class<? extends Component>> retainComponents) { BlockComponent blockComponent = blockEntity.getComponent(BlockComponent.class); Optional<Prefab> oldPrefab = oldType.getPrefab(); EntityBuilder oldEntityBuilder = entityManager.newBuilder(oldPrefab.orElse(null)); oldEntityBuilder.addComponent( new BlockComponent(oldType, new Vector3i(blockComponent.getPosition()))); BeforeEntityCreated oldEntityEvent = new BeforeEntityCreated(oldPrefab.orElse(null), oldEntityBuilder.iterateComponents()); blockEntity.send(oldEntityEvent); for (Component comp : oldEntityEvent.getResultComponents()) { oldEntityBuilder.addComponent(comp); } Optional<Prefab> newPrefab = type.getPrefab(); EntityBuilder newEntityBuilder = entityManager.newBuilder(newPrefab.orElse(null)); newEntityBuilder.addComponent( new BlockComponent(type, new Vector3i(blockComponent.getPosition()))); BeforeEntityCreated newEntityEvent = new BeforeEntityCreated(newPrefab.orElse(null), newEntityBuilder.iterateComponents()); blockEntity.send(newEntityEvent); for (Component comp : newEntityEvent.getResultComponents()) { newEntityBuilder.addComponent(comp); } for (Component component : blockEntity.iterateComponents()) { if (!COMMON_BLOCK_COMPONENTS.contains(component.getClass()) && !entityManager .getComponentLibrary() .getMetadata(component.getClass()) .isRetainUnalteredOnBlockChange() && !newEntityBuilder.hasComponent(component.getClass()) && !retainComponents.contains(component.getClass())) { blockEntity.removeComponent(component.getClass()); } } blockComponent.setBlock(type); blockEntity.saveComponent(blockComponent); HealthComponent health = blockEntity.getComponent(HealthComponent.class); if (health == null && type.isDestructible()) { blockEntity.addComponent( new HealthComponent(type.getHardness(), type.getHardness() / BLOCK_REGEN_SECONDS, 1.0f)); } else if (health != null && !type.isDestructible()) { blockEntity.removeComponent(HealthComponent.class); } else if (health != null && type.isDestructible()) { health.maxHealth = type.getHardness(); health.currentHealth = Math.min(health.currentHealth, health.maxHealth); blockEntity.saveComponent(health); } for (Component comp : newEntityBuilder.iterateComponents()) { copyIntoPrefab(blockEntity, comp, retainComponents); } }
private EntityData.Entity serializeEntityDelta(EntityRef entityRef, Prefab prefab) { EntityData.Entity.Builder entity = EntityData.Entity.newBuilder(); entity.setId(entityRef.getId()); entity.setParentPrefab(prefab.getName()); for (Component component : entityRef.iterateComponents()) { if (component.getClass().equals(EntityInfoComponent.class)) continue; Component prefabComponent = prefab.getComponent(component.getClass()); EntityData.Component componentData; if (prefabComponent == null) { componentData = serializeComponent(component); } else { componentData = serializeComponent(prefabComponent, component); } if (componentData != null) { entity.addComponent(componentData); } } for (Component prefabComponent : prefab.listComponents()) { if (!entityRef.hasComponent(prefabComponent.getClass())) { entity.addRemovedComponent(ComponentUtil.getComponentClassName(prefabComponent.getClass())); } } return entity.build(); }
private EntityData.Component serializeComponent(Component base, Component delta) { ComponentMetadata<?> componentMetadata = componentLibrary.getMetadata(base.getClass()); if (componentMetadata == null) { logger.log(Level.SEVERE, "Unregistered component type: " + base.getClass()); return null; } EntityData.Component.Builder componentMessage = EntityData.Component.newBuilder(); if (useLookupTables) { componentMessage.setTypeIndex(componentIdTable.inverse().get(base.getClass())); } else { componentMessage.setType(ComponentUtil.getComponentClassName(delta)); } boolean changed = false; for (FieldMetadata field : componentMetadata.iterateFields()) { try { Object origValue = field.getValue(base); Object deltaValue = field.getValue(delta); if (!Objects.equal(origValue, deltaValue)) { EntityData.Value value = field.serialize(deltaValue); componentMessage.addField( EntityData.NameValue.newBuilder().setName(field.getName()).setValue(value).build()); changed = true; } } catch (IllegalAccessException e) { logger.log( Level.SEVERE, "Exception during serializing component type: " + base.getClass(), e); } catch (InvocationTargetException e) { logger.log( Level.SEVERE, "Exception during serializing component type: " + base.getClass(), e); } } if (changed) { return componentMessage.build(); } return null; }
@Override public EntityData.Component serializeComponent(Component component) { ComponentMetadata<?> componentMetadata = componentLibrary.getMetadata(component.getClass()); if (componentMetadata == null) { logger.log(Level.SEVERE, "Unregistered component type: " + component.getClass()); return null; } EntityData.Component.Builder componentMessage = EntityData.Component.newBuilder(); if (useLookupTables) { componentMessage.setTypeIndex(componentIdTable.inverse().get(component.getClass())); } else { componentMessage.setType(ComponentUtil.getComponentClassName(component)); } for (FieldMetadata field : componentMetadata.iterateFields()) { try { Object rawValue = field.getValue(component); if (rawValue == null) continue; EntityData.Value value = field.serialize(rawValue); if (value == null) continue; componentMessage.addField( EntityData.NameValue.newBuilder().setName(field.getName()).setValue(value).build()); } catch (IllegalAccessException e) { logger.log( Level.SEVERE, "Exception during serializing component type: " + component.getClass(), e); } catch (InvocationTargetException e) { logger.log( Level.SEVERE, "Exception during serializing component type: " + component.getClass(), e); } } return componentMessage.build(); }
private Component deserializeOnto( Component component, EntityData.Component componentData, ComponentMetadata componentMetadata) { try { for (EntityData.NameValue field : componentData.getFieldList()) { FieldMetadata fieldInfo = componentMetadata.getField(field.getName()); if (fieldInfo == null) continue; Object value = fieldInfo.deserialize(field.getValue()); if (value == null) continue; fieldInfo.setValue(component, value); } return component; } catch (InvocationTargetException e) { logger.log( Level.SEVERE, "Exception during serializing component type: " + component.getClass(), e); } catch (IllegalAccessException e) { logger.log( Level.SEVERE, "Exception during serializing component type: " + component.getClass(), e); } return null; }
private EntityData.PackedEntity.Builder serializeEntityDelta( EntityRef entityRef, Prefab prefab, FieldSerializeCheck<Component> fieldCheck) { EntityData.PackedEntity.Builder entity = EntityData.PackedEntity.newBuilder(); entity.setParentPrefabUri(prefab.getName()); Set<Class<? extends Component>> presentClasses = Sets.newHashSet(); ByteString.Output fieldIds = ByteString.newOutput(); ByteString.Output componentFieldCounts = ByteString.newOutput(); for (Component component : entityRef.iterateComponents()) { if (!componentSerializeCheck.serialize(componentLibrary.getMetadata(component.getClass()))) { continue; } presentClasses.add(component.getClass()); Component prefabComponent = prefab.getComponent(component.getClass()); if (prefabComponent == null) { serializeComponentFull( component, false, fieldCheck, entity, fieldIds, componentFieldCounts, true); } else { serializeComponentDelta( prefabComponent, component, fieldCheck, entity, fieldIds, componentFieldCounts, true); } } entity.setFieldIds(fieldIds.toByteString()); entity.setComponentFieldCounts(componentFieldCounts.toByteString()); for (Component prefabComponent : prefab.iterateComponents()) { if (!presentClasses.contains(prefabComponent.getClass()) && componentSerializeCheck.serialize( componentLibrary.getMetadata(prefabComponent.getClass()))) { entity.addRemovedComponent(idTable.get(prefabComponent.getClass())); } } return entity; }