1

I am trying to create a class to my javascript game to add multiplayer but within the class i am having problems with the values of arrays changing as you can see in the sendNetEntities() function

class NET_IO{
    //probably put address here
    //I want to check for localhost to denote MASTER client
    constructor(host, netlayer){
        this.socket = io();
        this.netLayer = netlayer
        console.log(this.socket)
        this.netEntities = this.netLayer.entities
        //setInterval(() => {this.update()}, 200)
    }

    getNetEntities(){
        this.socket.emit('getNetEntities', (net_entities) => {
            console.log(net_entities)
            this.netEntities = net_entities
        })
    }

    sendNetEntities(layer){
        var netEnt = this.netEntities
        console.log(netEnt)                 //this returns [background: Entity, NIkTag: Entity, player: Entity]` the value i want
        var ent = JSON.stringify(netEnt);
        console.log(ent)                   //this returns [] 
        this.socket.emit('sendNetEntities', ent)
    }

    update(layer, callback){
        //check host if localhost dont retreive new data only send
        this.sendNetEntities(layer)    
        callback(this.netEntities)


    }
}

I think im having problems with variables somehow being references of something instead of instances. But im not entirely sure all of the rules behind that for javascript. can anyone help me shed some light on this problem. I'm willing to edit my question as needed

EDIT

further debugging leads me to believe that it must be some sort of problem with socket.io. if i run this this.socket.emit('sendNetEntities', {netEnt}) my return on the server is {netEnt:[]} I havent had problems like this in socket.io in the past. Am i doing something wrong. is socket.io the problem

Nik Hendricks
  • 244
  • 2
  • 6
  • 29
  • you should console.log(str) before JSON.parse to see what the payload is, then when you get the payload, place in a json parser viewer to verify your data is what it is. Javascript is single threaded and won't change between lines of execution. – King Friday Apr 03 '21 at 00:41

1 Answers1

2

Based on this:

//this returns [background: Entity, NIkTag:  Entity, player: Entity]` the value i want
console.log(netEnt)                
var ent = JSON.stringify(netEnt);
console.log(ent)                   //this returns []

I think you are treating an Array as an Object. In JavaScript, this is technically possible because almost everything is an Object, including arrays. However, this may lead to unexpected behavior:

// Create an array and an object
a = [] // an array
o = {} // an object

// Set some properties on both
a.p = 42
o.p = 42

// Show differences between arrays and objects:
console.log(a.constructor)     // ƒ Array()
console.log(a)                 // [p: 42]
console.log(JSON.stringify(a)) // []

console.log(o.constructor)     // ƒ Object()
console.log(o)                 // {p: 42}
console.log(JSON.stringify(o)) // {"p":42}

As you can see, JSON.stringify() ignores properties set on arrays.

So the solution is to use netEnt either as an array or as an object, without mixing the types:

// As an array, don't use property names. Use the integer array indices:
netEnt = [entity1, entity2, entity3]
background = netEnt[0]
nikTag     = netEnt[1]
player     = netEnt[2]    

// As an object, property names can be used:
netEnt = {background: entity1, NIkTag: entity2, player: entity3}
background = netEnt.background 
nikTag     = netEnt.NIkTag     
player     = netEnt.player

update:

The fundamental problem is your classes use arrays, but access them as objects. The best solution is to change your classes so they either:

  • use arrays and access the arrays as arrays.
  • use objects and access the objects as objects.

Without seeing your class definitions, I cannot show you how to do this. However, it is as simple as changing the initial value of the class instances from [] to {}.

The following is a quick fix that serializes your array "objects" into true JS objects so JSON.stringify() will work as expected. However, in the future I highly recommend learning the difference between JS arrays and objects. This quick fix imposes a totally unnecessary performance penalty because JS arrays are being misused as objects:

    sendNetEntities(layer){
        var netEnt = this.netEntities
        
        // Convert netEnt array "object" into true JS object
        var trueObject = {}
        for (prop in netEnt) {
            trueObject[prop] = netEnt[prop]
        }

        var ent = JSON.stringify(trueObject);
        this.socket.emit('sendNetEntities', ent)
    }

Note in getNetEntities(), you will probably have to do the reverse: convert from true JS objects back to array "objects." I was unsure of the input format of net_entities, so I left this as an exercise.

Leftium
  • 16,497
  • 6
  • 64
  • 99
  • Its not necessarily my goal to be working with an object. I just really want to get the array containing class objects to my server and back. I would like to stick to an array because thats what all my other classes store there entitys in. – Nik Hendricks Apr 03 '21 at 02:32
  • @NikHendricks: Is there any reason your classes use arrays instead of objects? The problem is your classes store data in arrays but access those arrays as if they are objects. It should be quite simple to change your classes to use proper objects instead of arrays. If you show me one of your class definitions, I can show you the simple change required. – Leftium Apr 03 '21 at 02:46
  • @NikHendricks: I updated my answer with a quick fix to `sendNetEntities()` that will allow you to get your arrays to your server. (Getting them back from the server will require a similar quick fix, but I could not rewrite `getNetEntities()` without knowing the exact contents of `net_entities`) – Leftium Apr 03 '21 at 13:18
  • OH! understand. So since my entities are technically objects inside of the array. i'm not really just messing with arrays. I guess I was just missing what your were explaining thank you! – Nik Hendricks Apr 05 '21 at 19:34