gotti
TypeScript icon, indicating that this package has built-in type declarations

0.7.7 • Public • Published

THIS IS A HEAVILY IN-DEVELOPMENT BRANCH

I'm currently Implementing WebRTC within my systems to allow for peer to peer gameplay.

From a client system you will be able to do

// pings relay server to notify the player you want to connect
this.addPeer(playerId) 

// will send via WebRTC if available, or it will send via connector > relay (keeps track of which connector server a client is on) > connector > client  
this.dispatchToPeer(playerId, message) 

the goal is to allow for this api to work regardless if there's an existing WebRTC connection, the backup will normally relay the message across servers from your computer to theirs.

This will allow you to design your application without worrying about if the players browser supports WebRTC, your app will still work exactly the same either way (higher ping though). You'll just need to take into account performance and optimization for worse case scenario and everyone must relay or just use the regular connector > area for business logic. It's also my goal to try and make areas smart enough to not send redundant data if theres a peer connection between players but that's an issue for another day.

Node.js <-> HTML5 Networked ECS framework

Gotti.js

Gotti.js is a full stack javascript game engine framework.

It's mostly used by inheriting from the core base classes and implementing abstract methods.

SYSTEMS

CLIENT SYSTEM INHERITTED ABSTRACT METHODS

import { ClientSystem } from 'gotti';
import { SYSTEM, MESSAGES } from './Constants'; // should have a constants file with enumerated types 

export class CustomSystem extends ClientSystem {
    constructor() { 
        super(SYSTEM.PLAYER_MOVEMENT); // IMPORTANT TO USE CORRECT SYSTEM NAME HERE
     	// gotti.js hasnt decorated the system at this point do not use gotti.js methods.
    }

    public onInit() {
    	// gotti.js initialized system and decorated with needed methods at this point
    };

    /*{ 
        type: number | string - Message type/code
        data: any - Payload of message 
        to: Array<number | string> - system names/codes the message was dispatched to explicitly  
        from? number | string  - which system name/code it was sent from
    }*/
   
    public onLocalMessage(msg) { 
        switch(msg.type) {
            case MESSAGES.TEST_MESSAGE:
            	// handle message here
            	console.log(msg.data );
                break;  
        }
    };

    public onServerMessage(msg) {
        switch(msg.type) 
          case MESSAGES.SERVER_TEST_MESSAGE:
              break;
        }
    };

    public update(delta) {
     	// update loop called every tick 
    };
    public onStop() {
      	// called when process stops a system 
    };
    public onStart() {
     	// called when a process starts the system
    };
    public onEntityAddedComponent(entity: any): void {
      // hook that gets called when a component is added to an entity 
    }
    public onEntityRemovedComponent(entity: any): void {
      // hook that gets called when a component is removed from an
    }
}

CLIENT SYSTEM GOTTI.JS METHODS

dispatchLocal({type, data, to, from?})
dispatchToServer({type, data, to, from?})
immediateDispatchToServer ({type, data,to, from?}) // doesnt get queued in game loop from client or on server, use for data you want to be synched as fast as possible, I use it for projectile shooting
dispatchAllLocal // sends a message to all started systems
dispatchLocalInstant //triggers onLocalMessage instantly instead of waiting game loop
dispatchAllLocalInstant // triggers onLocalMessage instantly of all client started systems
initializeEntity(entity) // decorates entity to trigger system functions when adding/removing components with same name as the system
destroyEntity(entity) // as of now just calls entity.destroy() which if initialized with initializeEntity it will trigger the onEntityRemovedComponent of all components that have a sibling system started.
addMessageListener(messageType) // if a message isnt explicitly dispatched to a system a system can still listen for it, and then handle it normally inside the onLocalMessage TODO: listen for server messages too
removeMessageListener(messageType) // removes message listener (gets called if system is stopped too so you dont have to worry about doing this in the onStop abstract method)

Components

Creating a component

 import { Component } from 'gotti';
 import {  SYSTEM, MESSAGES } from './Constants';
 
 export class PositionComponent extends Component {
    private x: number;
    private y: number;
    constructor(x, y){
       super(SYSTEM.POSITION) // component should match system name 
                              // if you want to leverage onEntityAddedComponent 
                              // and onEntityRemovedComponent system hooks
       this.x = x;
       this.y = y;
    }
    setPositionByDeltas(dX, dY) {
        this.x += dX;
        this.y += dY;
    
 }

COMPONENT GOTTI.JS METHODS

setAttribute('attributeName', 'attributeValue')
setAttributeGetter('attributeName', () => { return 'attributeValue' });
// read more about setAttribute and setAttributeGetter in entity methods documentation
// since theyre the same functions for whatever entity the component lives on

#Entities ##Creating an Entity

adding PositionComponent

import { Entity, NetworkedComponent  } from 'gotti';
import { PositionComponent } from './PositionComponent;
export class Player extends Entity {
    // each entity should have a unique id and that should be about the only 
    // thing set in the constructor unless you add your own properties
    constructor(id) {
        super(id);
    }
    // use initialize function for component initialization 
    // so all the gotti hooks and decorators get applied correctly
    initialize(data) {
        const { x, y } = data; // data should be some initialization attributes
        this.addComponent(new PositionComponent(x, y)); // this would still work fine by dispatchRemote would not do anything
        
        // to leverage the networking do
        this.addComponent(NetworkComponent(new PositionComponent(x, y));
    }
}

Entity GOTTI.JS METHODS

addComponent(component) // adds component to entity and triggers sibling system onEntityAddedComponent        
removeComponent(component) // adds component to entity and triggers sibling system onEntityRemovedComponent        
getComponent(componentName) // gets component or null if entity doesnt have it
hasComponent(componentName) // returns boolean iif entity has component or not
setAttribute('attributeName', 'attributeValue') // sets an attribute which can also be called from components and will be called on the entity object.
setAttributeGetter('attributeName', () => { return 'attributeValue' })
                            // same as above but when getAttributes the value 
                            // will be whatever the function returns, this 
                            // is useful if you only want to do attribute formatting/encoding
                            // when you need to get the attributes and not every time a value
                            // in your component changes(changing areas)
                            
getAttributes() // returns key value pair of all attributes set from all components

Dynamic Component Methods

when you add a component to an entity, the component methods all 
get mapped to the entity and you can call any method without having 
to do a entity.getComponent(COMPONENT_NAME).callMethod();
so the above entity, from inside an system we can now do 

    const player = this.initializeEntity(new Player(clientId), playerData);
    player.setPositionByDeltas(x, y) 
    // instead of having to always write out
    player.getComponent(SYSTEM.POSITION).setPositionsByDeltas(x, y);

Not yet documented -

ServerSystem.ts

ClientManager.ts (ServerSystem with extra functionality)

Process.ts - initializing/adding systems to a pre defined process.

Client.ts - Web client used to start processes.

I'm going to work on writing better documentation and possibly a tutorial.. This is just the start of what the framework is capable of and it's meant to be configured with GottiColyseus servers in order to unlock it's real potential of a full stack ECS framework.. it's not as trivial to setup as I want it to be but after I write some documentation I will hopefully be able to make it more approachable.

Readme

Keywords

none

Package Sidebar

Install

npm i gotti

Weekly Downloads

64

Version

0.7.7

License

MIT

Unpacked Size

208 kB

Total Files

64

Last publish

Collaborators

  • jvisgotti