Created
October 4, 2017 18:50
-
-
Save mflux/60e6393266c0168d555aa3d95ba35483 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import R from 'ramda'; | |
import * as Debug from './debug'; | |
export function create(){ | |
const events = { | |
componentCreations: [], | |
componentChanges: [], | |
componentDeletions: [] | |
}; | |
const update = handleStateChange( events ); | |
const out = { | |
update, | |
componentCreated: ( filter ) => events.componentCreations.push( filter ), | |
componentChanged: ( filter ) => events.componentChanges.push( filter ), | |
componentDeleted: ( filter ) => events.componentDeletions.push( filter ), | |
bind: function( handlers ){ | |
if( Array.isArray( handlers ) ){ | |
bind( out, handlers ); | |
} | |
else{ | |
bindOne( out, handlers ); | |
} | |
return out; | |
}, | |
unbind: function( handlerId ){ | |
Object.keys( events ).forEach( function( eventType ){ | |
events[ eventType ] = events[ eventType ].filter( function( e ){ | |
return e.handlerId !== handlerId; | |
}); | |
}); | |
} | |
}; | |
return out; | |
} | |
export function bindOne( stateEvents, handler ){ | |
const { type } = handler; | |
stateEvents[ type ]( handler ); | |
} | |
export function bind( stateEvents, handlers ){ | |
if( Array.isArray( handlers ) === false ){ | |
bindOne( stateEvents, handlers ); | |
return; | |
} | |
handlers.forEach( function( handler ){ | |
bindOne( stateEvents, handler ); | |
}); | |
} | |
const handleStateChange = R.curry( function( events, states ){ | |
// Debug.time('state change handler'); | |
const { componentCreations, componentChanges, componentDeletions } = events; | |
const { oldState, gameState } = states; | |
const entities = gameState.entities; | |
const oldEntities = oldState.entities; | |
R.forEach( handleComponentCreations( entities, oldEntities ), componentCreations ); | |
R.forEach( handleComponentChanges( entities, oldEntities ), componentChanges ); | |
R.forEach( handleComponentDeletions( entities, oldEntities ), componentDeletions ); | |
// Debug.timeEnd('state change handler'); | |
}); | |
const handleComponentCreations = R.curry( function( entities, oldEntities, filter ){ | |
const componentName = filter.component; | |
const relevant = entitiesWithComponent( componentName, R.values( entities ) ).filter( hasRequiredComponents( filter ) ); | |
function perform( entity ){ | |
const oldEntity = oldEntities[ entity._id ]; | |
if( oldEntity === undefined ){ | |
filter.result( oldEntity, entity ); | |
return; | |
} | |
if( entity[ componentName ] !== undefined && oldEntity[ componentName ] === undefined ){ | |
filter.result( oldEntity, entity ); | |
} | |
} | |
if( filter.specificId ){ | |
perform( entities[ filter.specificId ] ) | |
} | |
else{ | |
relevant.forEach( perform ); | |
} | |
}); | |
const handleComponentDeletions = R.curry( function( entities, oldEntities, filter ){ | |
const relevantOld = entitiesWithComponent( filter.component, R.values( oldEntities ) ).filter( hasRequiredComponents( filter ) ); | |
function perform( oldEntity ){ | |
const componentName = filter.component; | |
const entity = entities[ oldEntity._id ]; | |
if( entity === undefined ){ | |
filter.result( oldEntity, oldEntity ); | |
return; | |
} | |
if( oldEntity[ componentName ] !== undefined && entity[ componentName ] === undefined ){ | |
filter.result( oldEntity, entity ); | |
} | |
} | |
if( filter.specificId ){ | |
perform( oldEntities[ filter.specificId ] ); | |
} | |
else{ | |
relevantOld.forEach( perform ); | |
} | |
}); | |
const handleComponentChanges = R.curry( function( entities, oldEntities, filter ){ | |
if( filter.check === undefined ){ | |
console.warn('no check for handling component updates', JSON.stringify( filter, null, 2 ) ); | |
return; | |
} | |
const relevant = filter.component === undefined ? R.values( entities ) : entitiesWithComponent( filter.component, R.values( entities ) ).filter( hasRequiredComponents( filter ) ); | |
function perform( entity ){ | |
const oldEntity = oldEntities[ entity._id ]; | |
if( oldEntity === undefined ){ | |
return; | |
} | |
const componentName = filter.component; | |
if( oldEntity[ componentName ] === undefined ){ | |
return; | |
} | |
if( filter.check( oldEntity[ componentName ], entity[ componentName ] ) ){ | |
filter.result( oldEntity, entity ); | |
} | |
} | |
if( filter.specificId ){ | |
perform( entities[ filter.specificId ] ); | |
} | |
else{ | |
relevant.forEach( perform ); | |
} | |
}); | |
function entitiesWithComponent( componentName, entities ){ | |
return R.reject( ( entity ) => entity[ componentName ] === undefined, entities ); | |
} | |
export const componentCheck = R.curry( function( componentKey, old, cur ){ | |
return !R.equals( old[ componentKey ], cur[ componentKey ] ); | |
}); | |
const hasRequiredComponents = R.curry( function( filter, entity ){ | |
if( filter.requireComponents !== undefined ){ | |
const req = filter.requireComponents; | |
for( let i=0; i<req.length; i++ ){ | |
const reqN = req[ i ]; | |
if( entity[ reqN ] === undefined ){ | |
return false; | |
} | |
} | |
} | |
return true; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment