Giter Site home page Giter Site logo

lance-gg / lance Goto Github PK

View Code? Open in Web Editor NEW
1.5K 55.0 168.0 9.89 MB

Multiplayer game server based on Node.JS

Home Page: https://lance-gg.github.io/

License: Apache License 2.0

JavaScript 8.54% Shell 0.14% TypeScript 91.32%
multiplayer gamedev nodejs multiplayer-game-server websockets networking game-server game-development

lance's Introduction

Lance logo

Lance is a real-time multiplayer game server

It provides an extendible Node.JS based server, on which game logic runs, as well as a client-side library which synchronizes the client's game state with the server game state. In order to provide a smooth visual experience for each connected client, Lance implements efficient networking methods, position interpolation and extrapolation, user input coordination, shadow objects, physics and pseudo-physical movement, automatic handling of network spikes.

Lance aims to optimize the player's visual experience, while providing a simple development model which is highly configurable and easy to analyze and debug.

Features:

  • Focus on writing your game. Lance takes care of the netcode
  • Can support any type of game or genre
  • Optimized networking
    • TCP via websockets
    • Communication is packed and serialized into binary
    • Automatic handling of network spikes with step correction
  • Intelligent sync strategies for lag handling
    • Extrapolation (client side prediction) with step re-enactment or:
    • Interpolation for optimal object motion
  • Tools for debugging and tracing

More features in the pipeline:

  • UDP via WebRTC
  • Full-stack testing suite
  • Replay saving
  • More physics engines

That's so neat! Where do I start?

The official Lance documentation contains articles on theory and rationale, as well as the structure and architecture of the project.

Something went wrong! I need help!

If you're not exactly sure how to do something, Stack Overflow is your friend.

If you've encountered a bug and it's not already in the issues page, open a new issue.

lance's People

Contributors

alexanderson1993 avatar cshyeon avatar dependabot[bot] avatar dev-zetta avatar ggalansmithee avatar namel avatar opherv avatar sebring avatar smokku avatar unsigno avatar vinmaster avatar wighawag avatar wooki avatar yang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lance's Issues

UDP support

This is a feature request.

Request to add support for UDP - which is a faster networking mechanism than the current TCP, and would probably be built on top of WebRTC.

Slack invitation

Hey there, not sure where else to put this, but I am trying to get into your slack chatroom but I don't have an invitation. I'd love to hang out in there with you guys, this is an awesome framework.

Automated Cloud Deployment

This is a feature request.

Request for an automated cloud deployment, where game developers can provide links to their game repository in github, and game servers are automatically deployed, monitored, load-balanced, and statistics are collected.

Preserve State

This is a feature request.

Request to preserve game state, at fixed interval rate, or if possible at every step.
The durability test is that if the Incheon game server crashes, another server can be brought online to continue the game from the last saved game state.

Traces mechanism is unnecessarily creating strings for the garbage collector

Calls like this one are generating strings and polluting memory, even when tracing is disabled:

this.gameEngine.trace.warn(`step drift ${checkType}. [${clientStep} > ${serverStep} + ${maxLead}] Client is ahead of server.  Delaying next step.`);

Solution: the trace functions should be passed a callback which builds the string.

babel / es5 compatability

Thanks for this inspiring project!

Currently, it seems to not be possible to use this module with babel (or in an es5 environments), since it exports es6 code (classes etc). There is no engine requirements specified in the package.json file, so I cannot be sure what your intentions are, but the general consensus is to transpile your code to be es5 compatable, unless othervise stated. I think there are two options to solve this:

  1. Bundle and transpile your code, and export that bundle through main (and module / jsnext:main if you were to add es6 module exports)
  2. State in your docs, and in your package.json engine section that this module is not es5 compatable

With option 2, babel users can still use your package if they transpile it (babel ignores node_modules by default), but from a user's perspective, option 1 is much more frictionless.

Interpolate strategy not syncing "complex" netScheme properties

After the recent fix (#39), I noticed that Interpolate strategy now syncs properly all the additional "Simple" netScheme properties, but it doesn't sync the following types:

type: Serializer.TYPES.LIST
type: Serializer.CLASSINSTANCE

As workaround, extending the method interpolate does the trick.

Object with id 0 can't be queried

When I launch my game, the first GameObject that gets created has id 0. Attempting to get this object from the GameWorld with gameEngine.world.queryObject({id: 0}); returns null. I'm not sure if the issue here is having an id of 0 to begin with, or if that's by design and the issue is with queryObject. I have overridden some parts of the engines, but I don't think they'd affect this. e.g. not GameWorld or GameObject. Happy to post code but just not sure what to post at this point as I'm not sure whether id:0 is something that's even meant to happen. Thanks!

Great Project.. how to get involved?

Hello,
could i participate in development? I run a modified version of your code here with BabylonJS Renderer and Cannon Physics on server side. Maybe we could share skype contacts?

Regards
Stefan

Implement player timeout

Right now players are connected indefinitely.

It's important to have feature where the developer defines a timeout in seconds per server, and a player is disconnected if no input was received in the allotted time.

Visual Debugger

This is a feature request.

Request for a visual debugger, which is capable of parsing trace files from server and clients, and re-play the sequence of recorded steps. The visual debugger would show at any given step the game state at the server and each client, preferably on the same map. Additional features include

  • manual step forward/back
  • show fade-out tail of recent positions/orientations
  • zoom in on any object to get object attributes
  • step view as well as time view
  • additional visuals for ExtrapolationStrategy re-enactment, showing the new bending values that resulted from each synchronization point

GameEngine double process Input on the client side

I followed the Pong game and set the object position in processInput in GameEngine like this:

    processInput(inputData, playerId) {
        super.processInput(inputData, playerId);
        console.log(`player ${playerId} pressed ${inputData.input}`);
        let player = this.world.getPlayerObject(playerId);
        if (player) {
            switch(inputData.input) {
                case "e":
                    player.position.z -= 1;
                    break;
                case "d":
                    player.position.z += 1;
                    break;
                case "s":
                    player.position.x -= 1;
                    break;
                case "f":
                    player.position.x += 1;
                    break;
                case "w":
                    break;
                case "q":
                    break;
                default:
                    break;
            }
            console.log(inputData, player.position);
        }
    }

The player's client side log showed different player.position from the server and other clients. The GameEngine seems double processed.

How do I go about implementing an external physics engine.

I just need some pointers on where and how I should add a physics engine(Matter.js).

I got interpolation with matter js to work(I simply extended physics engine and updated the engine using step), however I think I might be doing the position, velocity, angle updating wrong.

Here is a GameObject snipet:

class MyGameObject extends DynamicObject {
	constructor(id) {
		super(id);
		this.position.set(0, 0);
		this.class = GameObject;
	}

	onAddToWorld(gameEngine) {
		if (gameEngine.physicsEngine) {
                      //Add body to matter and keep track of it using a reference.
                      this.matter = ...;
		}
	}

	draw(ctx) {
		ctx.fillRect(this.position.x-5, this.position.y-5, 10, 10); //Simple test
	}

	syncTo(other, options) {
		super.syncTo(other);

		if (this.matter) //If this has a matter body reference
			this.refreshToPhysics();
	}

	bendToCurrent(original, bending, worldSettings, isLocal, bendingIncrements) {
		super.bendToCurrent(original, bending, worldSettings, isLocal, bendingIncrements);

		if (this.matter)
			this.refreshToPhysics();
	}

	refreshFromPhysics() { //Note: This is called in the GameEngine::step() (I loop over all objects)
		if (this.matter) {
			this.position.set(this.matter.position.x, this.matter.position.y);
			this.velocity.set(this.matter.velocity.x, this.matter.velocity.y);
			this.angle = this.matter.angle;
		}
	}

	refreshToPhysics() {
		Matter.Body.setPosition(this.matter, this.position);
		this.matter.velocity = this.velocity;
		this.matter.angle = this.angle;
	}

	step () {
		super.step();

		this.refreshFromPhysics(); //This is not needed since its called from GameEngine.
	}
}

This code works but when I have over 200 objects(simple 10x7 rectangles) the game freezes(Im not sure if lance stops sending or if the packet size is too large or etc.). The physics engine when run locally can handle well over that amount.

I then tried using extrapolation:

  • with 200 objects the step takes 5s and eventually freezes.
  • with 10 objects the physics is out of sync for clients.

Does the physics engine need to be deterministic?
I have looked at other PhysicsEngine implementations (Cannon, etc) and see no trace of GameObject.position updatin.

I have not yet tested lance without physics with over 200 objects, but I assume the freezing is my fault and not lance's.

If you need any more info please ask(Im sure if left something out)

Thank you.

Platformers - gravity. Request to integrate P2 in Lance.

Hi i'm kind of new to the web engine scene altough i'm a programmer and already experimented with phaser and others.

I would like to know if there is any way to create 2D platformer games with the engine: basic gravity, stand on a platform, jumping, etc...

I have looked at the DynamicObject and SimplePhysicsEngine classes and I see nothing related.

I want to create a 4 player 2D arena platformer and this engine has everything needed for it but this.

sanity check values on serialization

When serializing an object with the netscheme, do some sanity checks:

  • correct data type
  • value present if required (consider making this explicit in the netscheme definition)
  • correct value range (e.g. UINT8 cannot be passed a value larger than 255)

Handle first sync event ( sync world )

For convenience reasons ( eg. initialize visual scene/world ) should be usefull a firstSyncReceived/worldSync or something similar , maybe with pre/post addition .

I can execute once 'client__syncReceived' , but a interesting thing can be add diferent params as syncReceived .

Eg.

beforeWorldSync( theFirstSyncData )
onWorldSync( the objectInstancesCreated ) // this implies divide onAddToWorld ( to onCreateRenderEl onAddToWorld )
afterWorldSync() // the instances are added to the world now

Memory Leak

Hello, testing the game engine in diverse network condition and found out that when the client can't keep up with the server, It starts leaking memory. I found this while playing "spaaace" game with a latency > 350 ms. I started shooting all over the screen and latency + memory started growing until the window hanged.
I think it has to do with the extrapolation and the sync.

Regards,
Guillermo

[Feature Request] Provide Client Side Library

Hello!
This library is exactly what we've been looking, but it's lacking one thing that is preventing us from using it: An stand-alone client library.

We started using it for a recent game jam but had to abandon it when we realized that it assumes you are using browserfy. Our projects use a build-less environment and are specifically designed not to use browserfy, so we can't use this library unless we completely change our build process.

All we need to be able to use Lance is a client library that we could include with a <script> tag. This is standard for many other javascript libraries, like socket.io:

Like so:

<script src="/socket.io/socket.io.js"></script>

Lance Client Example:

<script src="/js/lance-client.js"><script>

Lance Server Example

const ServerEngine = require('lance-gg').ServerEngine;

If you could provide a client side library that could be included with a script tag, then we could start using Lance and that would AWESOME!

V/H Scaling

A major factor in any Game Server is scaling, especially in Node. Running a single Node instance gives limited access to hardware (1 core), as per Node's architecture. This will result in an unscalable game that will only throttle itself.

Interpolate strategy not syncing additional netScheme properties

I noticed that when setting this strategy, any additional properties set in netScheme doesn't get synced. Digging in the code noticed that there are's a call to syncTo only when the object is created but further updates only update the position. Temporarily work-around extending interpolate method on the dynamic object as follows, ie:

class myobject extends DynamicObject {
interpolate(nextObj, playPercentage, worldSettings) {
   super.interpolate(nextObj, playPercentage, worldSettings);
   this.height = nextObj.height;
   this.health = nextObj.health;
   this.shield = nextObj.shield;
   this.kind = nextObj.kind;
   this.skills = nextObj.skills;
} 
}

playerJoined event is not emitted on the client

On the server, when a player connects, the events server__playerJoined and playerJoined are emitted, but on the client, neither are emitted. I was expecting that playerJoined would be emitted on both.
I do receive a playerJoined event on the client socket (which makes sense, since ServerEngine sends that separately).

Custom renderers

// TODO: I have mixed feelings about this class. It doesn't actually provide
// anything useful. I assume each game will write their own renderer even in THREE.
// we can make it store a list of objects, and provide a Raycaster, and send events.
// But it hijacks the creation of the scene and the THREE.renderer. It doesn't make
// sense to me that the camera and lights are in the derived class, but the scene and
// renderer are in the base class. seems like inheritance-abuse.
class ThreeRenderer extends Renderer {

I saw your comment there.

I have my own tool that I use for rendering: https://infamous.io

But I suppose that I need to somehow hook it up with Lance in order to take advantage of the client-side prediction of player position, to mitigate network lag, etc. (if I understand correctly, this is what Lance does)

What are requirements for making a renderer? I mean, I see the Renderer source, but some actual guides would be better. Maybe this discussion can be a starting point for that.

Socket.IO Connection options

Allowing passing of an object to ClientEngine.connect which will be used as the second parameter in the io() call.

object ID allocation should be inside GameEngine::addObjectToWorld()

Hide the specifics of object ID allocation from the developer.

objectID allocation is sensitive. It involves making sure that
an existing value is not reused. It also involves allocating
from the clientIDspace when creating on the client (extrapolate).

There is no benefit in exposing this to the game developer.

Elements do not appear to move/ client does not run

When I run netpong, the server seems to be operating, but when I connect in my browser I only see the two paddles stuck at the top of the screen at their respective locations and the ball stuck at the top left. The server still reports new connections and disconnections and announces that players are scoring. The method that responds to user input does not appear to execute on the server when I press keys in the browser.

When I connect to spaaace, I only see a white screen.

I'm using windows 10. This happens with both chrome and firefox.

documentation: document events collisionStart and collisionStop

documentation: document events collisionStart and collisionStop

From the slack conversation:
collisionStart and collisionStop are emitted only by one physics engine at this time: SimplePhysicsEngine. The registered event handlers will be passed a single argument, an object containing two keys o1 and o2. The values correspond to the two object IDs that collided.

home page issue: error when the incheon.gg tab is left in the background for a while

This issue is not really about incheon, it's about the incheon home page, but I don't want to forget it, so I'm putting it here anyways :)

When I load up the incheon home page, and leave the tab open for a while (as a background tab), then eventually when I select the tab again, the spaaace (demo) game goes nuts.

This is probably a spaaace issue. Though come to think of it, a general solution sounds rather useful.

Build error

I cant seem to build the project with web pack,it says the build parameters do not match webpacks norms.And i scoured the entire documentation,nothing states anything about what particular type of web pack to use

Provide game which demonstrated chat-services integration

This is a feature request.

Request to provide a new sample game - which integrates chat services. Since chat services are outside the scope of Incheon, there is a need to demonstrate how someone might integrate an Incheon game with a third-party chat service.

Send updates only when attributes change

It would be a great improvement in performance and bandwidth usage if the server only sent updates of attributes that have changed, e.g. position or velocity.
Right now it's sending the whole DynamicObject even if it hasn't moved since the last update.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.