Skip to content

Commit

Permalink
Fix delete network entity with childrens
Browse files Browse the repository at this point in the history
  • Loading branch information
gonpombo8 committed Nov 28, 2023
1 parent 48dc501 commit 3b48aa2
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 41 deletions.
31 changes: 10 additions & 21 deletions packages/@dcl/ecs/src/engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ValueSetOptions
} from './grow-only-value-set-component-definition'
import { removeEntityWithChildren as removeEntityWithChildrenEngine } from '../runtime/helpers/tree'
import { NetworkEntity } from '..'
export * from './input'
export * from './readonly'
export * from './types'
Expand All @@ -26,7 +27,6 @@ function preEngine(): PreEngine {
const entityContainer = EntityContainer()
const componentsDefinition = new Map<number, ComponentDefinition<unknown>>()
const systems = SystemContainer()
let networkManager: ReturnType<IEngine['addNetworkManager']>

let sealed = false

Expand All @@ -38,34 +38,27 @@ function preEngine(): PreEngine {
return systems.remove(selector)
}

function getNetworkManager() {
if (!networkManager) throw new Error('Network manager not initialized. Start CRDT Server')
return networkManager
}

function addNetworkManager(reservedLocalEntities: number, range: [number, number]) {
entityContainer.setNetworkEntitiesRange(reservedLocalEntities, range)
networkManager = {
addEntity: () => entityContainer.generateEntity(true)
}
return networkManager
}

function addEntity() {
const entity = entityContainer.generateEntity()
return entity
}

function removeEntity(entity: Entity) {
for (const [, component] of componentsDefinition) {
// TODO: hack for the moment. It should be enough to delete the entity, but the renderer is not cleaning the components.
// So we still need the NetworkEntity to forward this message to the SyncTransport.
if (component.componentId === NetworkEntity.componentId) continue
component.entityDeleted(entity, true)
}

return entityContainer.removeEntity(entity)
}

function removeEntityWithChildren(entity: Entity) {
return removeEntityWithChildrenEngine({ removeEntity, defineComponentFromSchema, getEntitiesWith }, entity)
return removeEntityWithChildrenEngine(
{ removeEntity, defineComponentFromSchema, getEntitiesWith, defineComponent },
entity
)
}

function registerComponentDefinition(
Expand Down Expand Up @@ -253,9 +246,7 @@ function preEngine(): PreEngine {
registerComponentDefinition,
entityContainer,
componentsIter,
seal,
addNetworkManager,
getNetworkManager
seal
}
}
/**
Expand Down Expand Up @@ -311,8 +302,6 @@ export function Engine(options?: IEngineOptions): IEngine {
getEntityState: partialEngine.entityContainer.getEntityState,
addTransport: crdtSystem.addTransport,

entityContainer: partialEngine.entityContainer,
addNetworkManager: partialEngine.addNetworkManager,
getNetworkManager: partialEngine.getNetworkManager
entityContainer: partialEngine.entityContainer
}
}
13 changes: 0 additions & 13 deletions packages/@dcl/ecs/src/engine/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ export type PreEngine = Pick<
| 'seal'
| 'entityContainer'
| 'getEntityOrNullByName'
| 'addNetworkManager'
| 'getNetworkManager'
> & {
getSystems: () => SystemItem[]
}
Expand Down Expand Up @@ -300,15 +298,4 @@ export interface IEngine {
* Entity container with custom methods to update their state.
*/
entityContainer: EntityContainer

/**
* @alpha
* Initialize network manager
*/
addNetworkManager(reservedLocalEntities: number, range: [number, number]): { addEntity: IEngine['addEntity'] }
/**
* @alpha
* Get netowrk manager to create entities.
*/
getNetworkManager(): ReturnType<IEngine['addNetworkManager']>
}
37 changes: 33 additions & 4 deletions packages/@dcl/ecs/src/runtime/helpers/tree.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as components from '../../components'
import { Entity } from '../../engine/entity'
import { Entity, EntityState } from '../../engine/entity'

Check warning on line 2 in packages/@dcl/ecs/src/runtime/helpers/tree.ts

View workflow job for this annotation

GitHub Actions / lint

'EntityState' is defined but never used. Allowed unused vars must match /^_|ReactEcs/u
import { ComponentDefinition, IEngine } from '../../engine'
import { NetworkParent } from '../..'

Check warning on line 4 in packages/@dcl/ecs/src/runtime/helpers/tree.ts

View workflow job for this annotation

GitHub Actions / lint

'NetworkParent' is defined but never used. Allowed unused vars must match /^_|ReactEcs/u

function* genEntityTree<T>(entity: Entity, entities: Map<Entity, T & { parent?: Entity }>): Generator<Entity> {
// This avoid infinite loop when there is a cyclic parenting
Expand Down Expand Up @@ -45,18 +46,46 @@ export function getComponentEntityTree<T>(
return genEntityTree(entity, entities)
}

function removeNetworkEntityChildrens(
engine: Pick<IEngine, 'getEntitiesWith' | 'defineComponentFromSchema' | 'removeEntity' | 'defineComponent'>,
parent: Entity
): void {
const NetworkParent = components.NetworkParent(engine)
const NetworkEntity = components.NetworkEntity(engine)

// Remove parent
engine.removeEntity(parent)

// Remove childs
const network = NetworkEntity.getOrNull(parent)
if (network) {
for (const [entity, parent] of engine.getEntitiesWith(NetworkParent)) {
if (parent.entityId === network.entityId && parent.networkId === network.networkId) {
removeNetworkEntityChildrens(engine, entity)
}
}
}
return
}

/**
* Remove all components of each entity in the tree made with Transform parenting
* @param engine - the engine running the entities
* @param firstEntity - the root entity of the tree
* @public
*/
export function removeEntityWithChildren(
engine: Pick<IEngine, 'getEntitiesWith' | 'defineComponentFromSchema' | 'removeEntity'>,
engine: Pick<IEngine, 'getEntitiesWith' | 'defineComponentFromSchema' | 'removeEntity' | 'defineComponent'>,
entity: Entity
) {
const Transform = components.Transform(engine)
for (const _entity of getComponentEntityTree(engine, entity, Transform)) {
engine.removeEntity(_entity)
const NetworkEntity = components.NetworkEntity(engine)

if (NetworkEntity.has(entity)) {
return removeNetworkEntityChildrens(engine, entity)
}

for (const ent of getComponentEntityTree(engine, entity, Transform)) {
engine.removeEntity(ent)
}
}
2 changes: 2 additions & 0 deletions packages/@dcl/ecs/src/systems/crdt/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,13 @@ export function crdtSceneSystem(engine: PreEngine, onProcessEntityComponentChang
for (const entityId of entitiesDeletedThisTick) {
const offset = buffer.currentWriteOffset()
DeleteEntity.write(entityId, buffer)

crdtMessages.push({
type: CrdtMessageType.DELETE_ENTITY,
entityId,
messageBuffer: buffer.buffer().subarray(offset, buffer.currentWriteOffset())
})

onProcessEntityComponentChange && onProcessEntityComponentChange(entityId, CrdtMessageType.DELETE_ENTITY)
}

Expand Down
7 changes: 5 additions & 2 deletions packages/@dcl/sdk/src/internal/transports/logger.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IEngine, CrdtMessage, CrdtMessageType } from '@dcl/ecs'
import { IEngine, CrdtMessage, CrdtMessageType, CRDT_MESSAGE_HEADER_LENGTH } from '@dcl/ecs'

Check warning on line 1 in packages/@dcl/sdk/src/internal/transports/logger.ts

View workflow job for this annotation

GitHub Actions / lint

'CRDT_MESSAGE_HEADER_LENGTH' is defined but never used. Allowed unused vars must match /^_|ReactEcs/u
import { ReadWriteByteBuffer } from '@dcl/ecs/dist/serialization/ByteBuffer'
import { readMessage } from '@dcl/ecs/dist/serialization/crdt/message'

Expand Down Expand Up @@ -32,7 +32,10 @@ export function* serializeCrdtMessages(prefix: string, data: Uint8Array, engine:
} catch {
yield `${preface} c=${componentId} t=${timestamp} data=?`
}
} else if (message.type === CrdtMessageType.DELETE_ENTITY) {
} else if (
message.type === CrdtMessageType.DELETE_ENTITY ||
message.type === CrdtMessageType.DELETE_ENTITY_NETWORK
) {
yield preface
} else {
yield `${preface} Unknown CrdtMessageType`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ export function createCube(x: number, y: number, z: number, sync: boolean = true
eventType: PointerEventType.PET_DOWN,
eventInfo: { button: InputAction.IA_POINTER, hoverText: 'Change Color' }
},
{ eventType: PointerEventType.PET_DOWN, eventInfo: { button: InputAction.IA_PRIMARY, hoverText: 'Grab Cube' } }
{ eventType: PointerEventType.PET_DOWN, eventInfo: { button: InputAction.IA_PRIMARY, hoverText: 'Grab Cube' } },
{
eventType: PointerEventType.PET_DOWN,
eventInfo: { button: InputAction.IA_SECONDARY, hoverText: 'Remove Cube' }
}
]
})

Expand Down Expand Up @@ -114,6 +118,9 @@ export function cubeSystem() {
if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN, entity)) {
Material.setPbrMaterial(entity, { albedoColor: Color4.fromHexString(getRandomHexColor()) })
}
if (inputSystem.isTriggered(InputAction.IA_SECONDARY, PointerEventType.PET_DOWN, entity)) {
engine.removeEntityWithChildren(entity)
}
if (
inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, entity) &&
!Grabbed.getOrNull(entity)?.userId
Expand Down

0 comments on commit 3b48aa2

Please sign in to comment.