Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

11.) MMO From Scratch - Iron Mines & Ground Items

Joined
Jun 8, 2007
Messages
1,985
Reaction score
490
Previous (Inventory)
Table of Contents (Introduction)
Next (Coming Soon)

In the last tutorial I complained about how I implemented inventory and coupled it to herbs. Today, we'll make some changes to the inventory and to the Slire Herb system, and we'll also implement two new features: Iron Mines and ground items.

The Server
I decided how I was going to implement every new game object. Basically, m.game.objects will be an object containing, well, game objects. Every game object will have it's own file. We already had one made for herbs, but I also made one for iron mines.In the objects extension, [STRIKE]I'll manually add these game objects much like I do with plugins on the client.[/STRIKE] Update: In the objects extension, the files will be automatically shoved into the m.game.objects object.

Each game object will have 2 special properties: class and instance. The class property is assigned to the class for that object. For example, the herbs game object has a property 'class', that points to the Herbs class. Of course this is JavaScript so technically Herbs isn't a class, but whatever Herbs is, it's assigned to the class property. The instance property is assigned null, and is meant to be a place for an instance of the class property to sit on. I created a helper function named setupGameObj(obj, objClass) to set up these two properties for us.

Code:
[COLOR=#BA2121]"use strict"[/COLOR];
[COLOR=#008000][B]var[/B][/COLOR] Herbs [COLOR=#666666]=[/COLOR] require([COLOR=#BA2121]'./objects/herbs.js'[/COLOR]);
[COLOR=#008000][B]var[/B][/COLOR] IronMines [COLOR=#666666]=[/COLOR] require([COLOR=#BA2121]'./objects/ironMines.js'[/COLOR]);

[COLOR=#008000][B]function[/B][/COLOR] setupGameObj (obj, objClass) {
    [COLOR=#008000]Object[/COLOR].defineProperties(obj, {
        [COLOR=#BA2121]"class"[/COLOR][COLOR=#666666]:[/COLOR] {
            value[COLOR=#666666]:[/COLOR] objClass,
            writable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR],
            configurable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR],
            enumerable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR]
        },
        [COLOR=#BA2121]"instance"[/COLOR][COLOR=#666666]:[/COLOR] {
            value[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]null[/B][/COLOR],
            writable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]true[/B][/COLOR],
            configurable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR],
            enumerable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR]
        }
    });
}

module.exports [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] (m) {
    m.game.objects [COLOR=#666666]=[/COLOR] {
        herbs[COLOR=#666666]:[/COLOR] {},
        ironMines[COLOR=#666666]:[/COLOR] {}
    };
    setupGameObj(m.game.objects.herbs, Herbs);
    setupGameObj(m.game.objects.ironMines, IronMines);
};

Hm.. I just noticed something. It should be possible to preload and automatically set up these game objects. So, I'll go a step further and do that now.
Code:
[COLOR=#BA2121]"use strict"[/COLOR];
[COLOR=#008000][B]function[/B][/COLOR] setupGameObj (obj, objClass) {
    [COLOR=#008000]Object[/COLOR].defineProperties(obj, {
        [COLOR=#BA2121]"class"[/COLOR][COLOR=#666666]:[/COLOR] {
            value[COLOR=#666666]:[/COLOR] objClass,
            writable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR],
            configurable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR],
            enumerable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR]
        },
        [COLOR=#BA2121]"instance"[/COLOR][COLOR=#666666]:[/COLOR] {
            value[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]null[/B][/COLOR],
            writable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]true[/B][/COLOR],
            configurable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR],
            enumerable[COLOR=#666666]:[/COLOR] [COLOR=#008000][B]false[/B][/COLOR]
        }
    });
}
module.exports [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] (m) {
    [COLOR=#008000][B]var[/B][/COLOR] dir [COLOR=#666666]=[/COLOR] m.fs.readdirSync([COLOR=#BA2121]'./private/extensions/objects'[/COLOR]);
    [COLOR=#008000][B]var[/B][/COLOR] index, objName;
    m.game.objects [COLOR=#666666]=[/COLOR] {};
    [COLOR=#008000][B]for[/B][/COLOR] (index [COLOR=#008000][B]in[/B][/COLOR] dir) {
        [COLOR=#008000][B]if[/B][/COLOR] (dir[index].match([COLOR=#BB6688]/[a-z]\.js/[/COLOR])) {
            objName [COLOR=#666666]=[/COLOR] dir[index].substr([COLOR=#666666]0[/COLOR], dir[index].indexOf([COLOR=#BA2121]'.'[/COLOR]));
            m.game.objects[objName] [COLOR=#666666]=[/COLOR] {};
            setupGameObj(m.game.objects[objName], require([COLOR=#BA2121]'./objects/'[/COLOR] [COLOR=#666666]+[/COLOR] dir[index]));
        }
    }
    console.log([COLOR=#BA2121]"Set up game objects:"[/COLOR], m.game.objects);
};
There. Now anytime we make a .js file in the /private/extensions/objects directory, it will be automatically shoved into the m.game.objects object. It should be noted that the file doesn't have to end with .js, the match is satisfied if it see's a lower-case letter followed by '.js' anywhere in the filename. So a file named 'herbs0.js' or 'herbs_.js' or 'herbs_OLD.js' will be ignored, and a folder or non-JavaScript file named 'thisIsNot.jsFile' will be imported. The error thrown by the require function from an invalid module will crash the server more/less immediately after it's started, so this isn't a big deal to me. Further, the solution is to name things nicely, so I consider the side effect a feature rather than a known bug.

Moving on.

I coded very much the same way I coded . I did have different needs though. Herbs are supposed to be created and deleted often, where iron mines are pretty much stationary. A player can't take an iron mine off of the map, nor may a player place one onto the map. This may be a feature for admins later down the road, but I can just as easily open up a mongo shell and create iron mines manually. Iron mines do need to be updated often, though. I decided on a 10 second replenishing time for now. I also decided Iron Mines should have a fixed amount of iron bits they can contain. I put this number at 128 for now. So every 10 seconds, the iron mine accumulates 1 additional iron bit. Once the iron mine accumulates 128 iron bits, it cannot produce any more until it is mined.

I wrote this code in . Everytime the iron mine runs an interval that adds an iron bit, it calls a callback function. The IronMines class uses this callback to tell MongoDB to update that mine in the DB, and it also forwards this information to a self.cycleCallback. Like the Herbs class, IronMines requires a callback as the second argument, that is assigned to self.cycleCallback. Also like Herbs, self.cycleCallback may be changed at anytime after instantiation during the lifetime of the program.

I entered a mongo shell and created an iron mine:
Code:
db.mines.insert({name: 'iron', place: [300, 300], bits: 0});
Someday in the future, I'll have more metals/minerals to mine in this game. In the first version I want to release, the only type of mine will be an iron mine. This schema is intended to be future-compatible.

Now that we have an iron mine, I really want to get it on the game canvas! Before we can do that, we need to create a channel to send this mine at (300, 300) to the client. So I created a file named to communicate with the client.

It didn't take me long to figure out that I was checking if the state was 4 in just about every socket emition. Wherever I wasn't checking if it was state 4, it was most-likely an error. So I went into and added a method to the session called state4Broadcast. It will cycle through every connection, check if the state is 4, and if so will emit the packet.

After I got that sorted out, I updated the herbs channel to use state4Broadcast instead of system events, and I feel much better about the style now. Events are cool and all, but I was using them for the wrong reasons in respect to herb operations. Then I went back to my /private/channels/mines.js file and continued working.

The users interact with mines to get iron bits- and that's it. So I added a socket event listener for 'iron-mined', that takes the id of the mine they attempted to mine from. I check that the state is 4 and that the iron mine with that ID actually exists, and I then check if the player is close enough to that mine to interact with it. Finally, I check if it was possible to add iron to the user's inventory, and if so I subtract the iron.bits by 1, and tell the mines instance about the change. Whether the iron bit was added to the inventory successfully or not, I send an update to all of the clients using my fancy new state4Broadcast emitter.

To ship the iron mines to the clients, I listen on the session's 'game-ready' event, and send the client all of the mines, tagged 'mines-init' . To tell the client when an iron mine's amount of iron bits changes, I send an 'iron-updated' emit using state4Broadcast.

Then, I was compelled to move the inventory to it's very own channel. So I created . In the last tutorial I put the inventory communications in the herbs channel, but now I needed to generalize items a little bit. So I created 2 socket listeners- 'item-placed' and 'item-picked'. I also created a server-side groundItems object. For now, I decided not to store groundItems in the DB, but I will almost certainly use the DB for them later. A ground item has a schema like this:
Code:
{
    _id: <String: unique identifier>, 
    name: <String: item name>, 
    place: <Array:Int(2): coordinates of ground item>
}
The switch to a database will rely on the exact same schema, so little code should need to be changed. There is 1 condition at the moment, that will most certainly need to be changed once I add more herbs. I check if the name is 'slire', and if so I run the 'herb-planted' system event. When an herb is placed on the map, it needs to became an Herb instance so it can reproduce and be alive. Every other item at the moment isn't alive once it's placed.. Well, we only have iron bits and herbs right now.. Anyway, at some point I need to have a more educated mapping system that will determine what items should do when they are placed.

When a ground item is picked up, we check if the user is close enough to the item, is state 4, if the item really exists, if the user has inventory space, etc etc- then delete the ground item from the server's list and use our fancy state4Broadcast function to tell all the other users the item was removed. If the item couldn't be removed, then we tell the client who tried to pick it up that the item was created- as the client will optimistically destroy the ground item before it receives confirmation from the server.

That about sums it up for the server changes this round. Now let's see what I did to get mining and ground items working on the client!

The Client
On the client we update to work for more general items, rather than only slire herbs. I then create a file, . It works very much the same as /public/objects/herbs.js does in the last tutorial. The difference is, instead of removing the sprite from the game canvas when adding iron to the inventory, we just leave the sprite alone. I did make one condition for the appearance of the sprite, though. If there are 0 iron bits in the mine, I tint the sprite to a darker color to indicate that the mine has been exhausted. As soon as bits are available, the sprite is restored to a normal tint.

I used clever naming of files to get the inventory working for iron bits. The sprite for an iron mine is in /public/assets/game/ironrock.png. In the items folder- which is where the inventory grabs the image for items in the inventory, the name of the image is iron.png. Since the name of the mine is also iron, it works great. In order for ground items to work, though, we must create a plugin for them. So I created a file named .

Ground items must be initialized when the user first enters the game, and then may be placed/picked up by any player by clicking on them. Like anything else, the player must be close to a ground item in order to pick it up. The same rules do not apply for placing items- and that is a bug in the game we will soon fix.

Previous (Inventory)
Table of Contents (Introduction)
Next (Coming Soon)
 
Last edited:
Joined
Jun 23, 2010
Messages
2,318
Reaction score
2,195
Interesting, may I ask what browser you were testing in? Or if you got any errors in the console/network logs?

The latest version of Chrome (Versie 48.0.2564.109 m (64-bit)).

Console log:
Code:
VM1949:4 status: Object {status: "Processing Login.."}
io.js:26 content: Object {selector: "#canvas", html: "<script>↵if (window.gameObj === void 0) {↵    window.….log(gameObj);↵initializeGame(gameObj);↵</script>"}
VM1954:6 Object {}
phaser.min.js:11    Phaser v2.4.4 | Pixi.js v2.2.9 | Canvas | WebAudio     http://phaser.io ♥♥♥
herbs.js:34 got herbs init:
herbs.js:35 Object {56bba39f66c750e52ccefa97: Object, 56bba45766c750e52ccefad4: Object, 56bbaa5ce7ba31862d928588: Object, 56bbaa5ce7ba31862d928589: Object, 56bbaa5de7ba31862d92858a: Object…}
groundItems.js:31 Ground items init: Object {}
mines.js:43 got mines init:
mines.js:44 Object {56bb953d52bf8ea4c2979203: Object}
others.js:78 got other update Object {username: "foo", game: Object}
others.js:55 queue size: 1
others.js:19 moving to:  Object {x: 287.5, y: 227.5}
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c58865e7ba31862d9287ac
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c58822e7ba31862d9287a6
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c56ed3e7ba31862d9287a2
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c5885be7ba31862d9287ab
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c5881ee7ba31862d9287a5
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c58828e7ba31862d9287a8
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c55f76e7ba31862d928799
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c58826e7ba31862d9287a7
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c56e96e7ba31862d9287a0
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c58828e7ba31862d9287a9
main.js:19 is close? true
herbs.js:47 herb deleted
herbs.js:48 56c58829e7ba31862d9287aa
player.js:96 steps: 1 0
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 107
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 104
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 104
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 113
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 104
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 107
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 106
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 106
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 104
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 107
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 111
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 104
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 106
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 105
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 105
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 112
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 105
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 117
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 105
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 105
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 104
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 105
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 112
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 113
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 105
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 109
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 112
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 110
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 108
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 110
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 114
player.js:162 player-move: Object {x: 250, y: 250, inventory: Array[2]}
player.js:165 lag: 110
 
Joined
Jun 8, 2007
Messages
1,985
Reaction score
490
Hm. It appears the server never accepted your move. I'll start working on a better way to log things so I can figure out what happened next time. Right now I'm just baffled. It could be a "moving too fast" error, but that's purely speculation.
 
Moderator
Staff member
Moderator
Joined
Feb 22, 2008
Messages
2,404
Reaction score
723
It doesn't work for me either, cant move. firefox 44.0.2
Code:
content: Object { selector: "#canvas", html: "<style> #loginContainer {     position…" } io.js:26:3
Campos de senha presentes em uma página insegura (http://). Este é um risco de segurança que permite que credenciais de login do usuário sejam roubadas.[Saiba mais] <desconhecido>
Campos de senha presentes em um formulário que será enviado a uma página insegura (http://). Este é um risco de segurança que permite que credenciais de login do usuário sejam roubadas.[Saiba mais] <desconhecido>
action: login Array [ Object, Object, Object ] io.js:18:1
status: Object { status: "Processing Login.." } jquery.js line 2 > eval:4:3
status: Object { status: "(1) No Bueno.", code: 1 } jquery.js line 2 > eval:4:3
action: login Array [ Object, Object, Object ] io.js:18:1
status: Object { status: "Processing Login.." } jquery.js line 2 > eval:4:3
status: Object { status: "(1) No Bueno.", code: 1 } jquery.js line 2 > eval:4:3
action: login Array [ Object, Object, Object ] io.js:18:1
status: Object { status: "Processing Login.." } jquery.js line 2 > eval:4:3
status: Object { status: "(3) Unable to find user.", code: 3 } jquery.js line 2 > eval:4:3
status: Object { status: "Processing Registration.." } jquery.js line 2 > eval:4:3
content: Object { selector: "#canvas", html: "<script> if (window.gameObj === voi…" } io.js:26:3
Object { game: Object, map: Object, player: Object, herbs: Object, mines: Object, groundItems: Object, utils: Object, objects: Object } jquery.js line 2 > eval:6:1
"Phaser v2.4.4 | Pixi.js v2.2.9 | Canvas | WebAudio | http://phaser.io" phaser.min.js:11:26341
got herbs init: herbs.js:34:9
Object { 56bbaa5ce7ba31862d928588: Object, 56bbaa99e7ba31862d92858d: Object, 56bbaad8e7ba31862d928597: Object, 56bbaad9e7ba31862d928598: Object, 56bbab16e7ba31862d9285a5: Object, 56bbab17e7ba31862d9285a6: Object, 56bbab18e7ba31862d9285a7: Object, 56bbab56e7ba31862d9285b7: Object, 56bbab91e7ba31862d9285c3: Object, 56bbab91e7ba31862d9285c4: Object, 390 mais… } herbs.js:35:9
Ground items init: Object {  } groundItems.js:31:9
got mines init: mines.js:43:9
Object { 56bb953d52bf8ea4c2979203: Object } mines.js:44:9
is close? true main.js:19:13
herb deleted herbs.js:47:9
56c588d7e7ba31862d9287b3 herbs.js:48:9
is close? true main.js:19:13
herb deleted herbs.js:47:9
56c5889be7ba31862d9287ae herbs.js:48:9
is close? true main.js:19:13
herb deleted herbs.js:47:9
56c588d7e7ba31862d9287b4 herbs.js:48:9
herb created herbs.js:42:9
Object { name: "slire", place: Array[2], _id: "56c6bbfe82e6cf6054cfec3a", sprite: Object } herbs.js:43:9
herb created herbs.js:42:9
Object { name: "slire", place: Array[2], _id: "56c6bbfe82e6cf6054cfec3b", sprite: Object } herbs.js:43:9
steps: 1 0 player.js:96:17
player-move: Object { x: 250, y: 257.5, inventory: Array[3] } player.js:162:9
lag: 221 player.js:165:9
player-move: Object { x: 250, y: 257.5, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 191 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[2] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 182 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 178 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 187 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 176 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 186 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 196 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 172 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 171 player.js:165:9
player-move: Object { x: 250, y: 257.5, inventory: Array[1] } player.js:162:9
lag: 173 player.js:165:9
player-move: Object { x: 250, y: 257.5, inventory: Array[1] } player.js:162:9
lag: 171 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[2] } player.js:162:9
lag: 178 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 179 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 172 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 250, y: 242.5, inventory: Array[2] } player.js:162:9
lag: 170 player.js:165:9
player-move: Object { x: 250, y: 242.5, inventory: Array[1] } player.js:162:9
lag: 178 player.js:165:9
player-move: Object { x: 250, y: 242.5, inventory: Array[1] } player.js:162:9
lag: 182 player.js:165:9
player-move: Object { x: 250, y: 242.5, inventory: Array[1] } player.js:162:9
lag: 177 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[2] } player.js:162:9
lag: 191 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 176 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 192 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 179 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 173 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 172 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[1] } player.js:162:9
lag: 175
 
Initiate Mage
Joined
Nov 11, 2006
Messages
73
Reaction score
6
Oh Man! i want give to you Beer! :) this is realy perfect help for developers :) I inspired from it to our MMORPG . Is here chance for any cooperation with you on our SCI-FI project?
 
Joined
Jun 8, 2007
Messages
1,985
Reaction score
490
It doesn't work for me either, cant move. firefox 44.0.2
Code:
content: Object { selector: "#canvas", html: "<style> #loginContainer {     position…" } io.js:26:3
Campos de senha presentes em uma página insegura (http://). Este é um risco de segurança que permite que credenciais de login do usuário sejam roubadas.[Saiba mais] <desconhecido>
Campos de senha presentes em um formulário que será enviado a uma página insegura (http://). Este é um risco de segurança que permite que credenciais de login do usuário sejam roubadas.[Saiba mais] <desconhecido>
action: login Array [ Object, Object, Object ] io.js:18:1
status: Object { status: "Processing Login.." } jquery.js line 2 > eval:4:3
status: Object { status: "(1) No Bueno.", code: 1 } jquery.js line 2 > eval:4:3
action: login Array [ Object, Object, Object ] io.js:18:1
status: Object { status: "Processing Login.." } jquery.js line 2 > eval:4:3
status: Object { status: "(1) No Bueno.", code: 1 } jquery.js line 2 > eval:4:3
action: login Array [ Object, Object, Object ] io.js:18:1
status: Object { status: "Processing Login.." } jquery.js line 2 > eval:4:3
status: Object { status: "(3) Unable to find user.", code: 3 } jquery.js line 2 > eval:4:3
status: Object { status: "Processing Registration.." } jquery.js line 2 > eval:4:3
content: Object { selector: "#canvas", html: "<script> if (window.gameObj === voi…" } io.js:26:3
Object { game: Object, map: Object, player: Object, herbs: Object, mines: Object, groundItems: Object, utils: Object, objects: Object } jquery.js line 2 > eval:6:1
"Phaser v2.4.4 | Pixi.js v2.2.9 | Canvas | WebAudio | http://phaser.io" phaser.min.js:11:26341
got herbs init: herbs.js:34:9
Object { 56bbaa5ce7ba31862d928588: Object, 56bbaa99e7ba31862d92858d: Object, 56bbaad8e7ba31862d928597: Object, 56bbaad9e7ba31862d928598: Object, 56bbab16e7ba31862d9285a5: Object, 56bbab17e7ba31862d9285a6: Object, 56bbab18e7ba31862d9285a7: Object, 56bbab56e7ba31862d9285b7: Object, 56bbab91e7ba31862d9285c3: Object, 56bbab91e7ba31862d9285c4: Object, 390 mais… } herbs.js:35:9
Ground items init: Object {  } groundItems.js:31:9
got mines init: mines.js:43:9
Object { 56bb953d52bf8ea4c2979203: Object } mines.js:44:9
is close? true main.js:19:13
herb deleted herbs.js:47:9
56c588d7e7ba31862d9287b3 herbs.js:48:9
is close? true main.js:19:13
herb deleted herbs.js:47:9
56c5889be7ba31862d9287ae herbs.js:48:9
is close? true main.js:19:13
herb deleted herbs.js:47:9
56c588d7e7ba31862d9287b4 herbs.js:48:9
herb created herbs.js:42:9
Object { name: "slire", place: Array[2], _id: "56c6bbfe82e6cf6054cfec3a", sprite: Object } herbs.js:43:9
herb created herbs.js:42:9
Object { name: "slire", place: Array[2], _id: "56c6bbfe82e6cf6054cfec3b", sprite: Object } herbs.js:43:9
steps: 1 0 player.js:96:17
player-move: Object { x: 250, y: 257.5, inventory: Array[3] } player.js:162:9
lag: 221 player.js:165:9
player-move: Object { x: 250, y: 257.5, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 191 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[2] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 182 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 178 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 187 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 176 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 186 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 196 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 172 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 171 player.js:165:9
player-move: Object { x: 250, y: 257.5, inventory: Array[1] } player.js:162:9
lag: 173 player.js:165:9
player-move: Object { x: 250, y: 257.5, inventory: Array[1] } player.js:162:9
lag: 171 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[2] } player.js:162:9
lag: 178 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 179 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 172 player.js:165:9
player-move: Object { x: 242.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 250, y: 242.5, inventory: Array[2] } player.js:162:9
lag: 170 player.js:165:9
player-move: Object { x: 250, y: 242.5, inventory: Array[1] } player.js:162:9
lag: 178 player.js:165:9
player-move: Object { x: 250, y: 242.5, inventory: Array[1] } player.js:162:9
lag: 182 player.js:165:9
player-move: Object { x: 250, y: 242.5, inventory: Array[1] } player.js:162:9
lag: 177 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[2] } player.js:162:9
lag: 191 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 176 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 192 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 179 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 173 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 175 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 172 player.js:165:9
player-move: Object { x: 257.5, y: 250, inventory: Array[1] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[2] } player.js:162:9
lag: 174 player.js:165:9
player-move: Object { x: 250, y: 250, inventory: Array[1] } player.js:162:9
lag: 175
Well.. 50% of the users (not counting me) can move. And according to both of the logs posted here, people are trying to move and the server is rejecting the move and responding with the entry position- 250, 250. The reason for this is the server gets invalid lag data.
Code:
cmd: left lag: -6749 step: 1
Client supplied invalid lag data! undefined
I calculate the lag using Date.now() on the client, and subtracting Date.now() on the server from the time passed by the client. So (psuedo code: server.epochTime - client.epochTime).

It occurs to me that this logic should work in theory, but is flawed in practice. Date.now() returns the Epoch time- that is, the amount of seconds since 1/1/1970. Now, according to the log above, your computer is almost 7 seconds ahead of my server in Epoch Time.

In theory that's impossible- but in practice, there are a lot of reasons why this is possible. I assume you're not living 7 seconds in the future, and I'll assume your connection to my server isn't 7 seconds faster than the speed of time. So I'm gonna take a shot in the dark here, and guess that either the server or the 50% of clients that cannot move, is a computer that is out of sync with Epoch Time.

The solution is... Well to be honest, I'm not using the lag data for anything anyway, so I'm checking it for no reason. I'll just delete some code and we'll see if that works.

I won't be uploading any code (this includes the fix for the issues with moving) until the next tutorial.


Oh Man! i want give to you Beer! :) this is realy perfect help for developers :) I inspired from it to our MMORPG . Is here chance for any cooperation with you on our SCI-FI project?

Thanks, tell me more about the SCI-FI project- you can PM me so we don't drift off topic in this thread ;)
 
Last edited:
Back
Top