colyseus / colyseus

⚔ Multiplayer Framework for Node.js
https://colyseus.io
MIT License
5.77k stars 546 forks source link

"Uncaught TypeError: Cannot read property '_schema' of undefined" when reloading tab with 0.10.2 #227

Closed halftheopposite closed 5 years ago

halftheopposite commented 5 years ago

Steps to Reproduce (for bugs)

  1. Connect a client on Chrome
  2. Connect a client on Firefox (everything works fine at this point and the map is loaded correctly and players see each other and can move)
  3. Reload one of the tab (either Chrome or Firefox)
  4. The reloaded tabs throws the following error, and the state is corrupted (no more listeners working)
    at _loop_1 (annotations.js:175)
    at _.Schema.decode (annotations.js:351)
    at _loop_1 (annotations.js:320)
    at _.Schema.decode (annotations.js:351)
    at SchemaSerializer.setState (SchemaSerializer.js:15)
    at Room.setState (Room.js:177)
    at Room.onMessageCallback (Room.js:165)
    at Connection.onMessageCallback (index.js:118)

    This is how I initialize my listeners to the Colyseus room events:

this.colyseusClient = new Client(API_WS_URL)
this.colyseusRoom = this.colyseusClient.join(ROOM_NAME)
this.colyseusRoom.onJoin.add(() => {

  // Walls
  this.colyseusRoom.state.walls.onAdd = (wall, key) => this.handleWallAdd(key, wall)

  // Players
  this.colyseusRoom.state.players.onAdd = (player, key) => this.handlePlayerAdd(key, player)
  this.colyseusRoom.state.players.onChange = (player, key) => this.handlePlayerChange(key, player)
  this.colyseusRoom.state.players.onRemove = (player, key) => this.handlePlayerRemove(key)

})

Context

I am creating a top-down shooter in 2d and had it working fine with Colyseus 9.x (working demo https://tdbr-cf83c.firebaseapp.com/).

I tried migrating on 10.x, but I get errors whenever a client reloads a tab when other clients are connected too.

Your Environment

endel commented 5 years ago

Hi @Ephismen, can you share how your schema files look like? Are you extending the Schema class in all of the data structures?

halftheopposite commented 5 years ago

Hi @endel,

Sure I'll list them here:

import { type, Schema } from '@colyseus/schema'

import { rectangleToRectangle } from "../utils/collisions"

export class Rectangle extends Schema {

  @type('number')
  public x: number

  @type('number')
  public y: number

  @type('number')
  public width: number

  @type('number')
  public height: number

  // Init
  constructor(x: number, y: number, width: number, height: number) {
    super()
    this.x = x
    this.y = y
    this.width = width
    this.height = height
  }

  // Methods
  collidesWithRectangle(other: Rectangle) {
    return rectangleToRectangle(this, other)
  }
}
import { type } from '@colyseus/schema'

import { Rectangle } from './Rectangle'

export class Player extends Rectangle {

  @type('boolean')
  public isActive: boolean

  @type('string')
  public name: string

  @type('number')
  public color: number

  @type('number')
  public score: number

  @type('number')
  public lastAck: number

  // Init
  constructor(x: number, y: number, width: number, height: number, isActive: boolean, name: string) {
    super(x, y, width, height)
    this.isActive = isActive
    this.setName(name)
    this.color = Number.parseInt(`0x${randomColor().replace('#', '')}`)
    this.score = 0
    this.lastAck = null
  }

  // Methods
  setName(name: string) {
    this.name = validateName(name)
  }
}
import { Rectangle } from './Rectangle'

export class Wall extends Rectangle {

  // Init
  constructor(x: number, y: number, width: number, height: number) {
    super(x, y, width, height)
  }
}

Basically I have Rectangle, from which Player and Wall inherit.

And here is my State:

export class MyState extends Schema {

  @type([Wall])
  walls = new ArraySchema<Wall>();

  @type({ map: Player })
  players = new MapSchema<Player>()

  //...

If that's not enough I can give you a private read access to my GitLab's repos to clone and test.

Thanks again for your hard work and passion, I waited years for something as simple and straightforward as Colyseus!

PS: What I don't get is why do I get the error only after reloading one of tab when two players are connected.

endel commented 5 years ago

Hi @Ephismen, do you mind sharing the GitLab repo with me? It would speed things up for me. My email address is available on my profile. Cheers!

halftheopposite commented 5 years ago

Hey @endel, just added you to the project as Guest (tell me if these permissions are enough). You can pull the features/colyseus-schema-update branches on the app and server projects to test the 0.10.x implementations.

endel commented 5 years ago

@Ephismen thanks, I can see the project but I think don't have permission to clone it

halftheopposite commented 5 years ago

Just updated your rights to Developer, it should be good now!

endel commented 5 years ago

Thanks a lot for trying out and reporting this so quickly @Ephismen, I've fixed it on version @colyseus/schema@0.4.4. If you remove node_modules, package-json.lock and install them again you should be fine!

Please do let me know if you find any other weird behaviors like this!

halftheopposite commented 5 years ago

Hi @endel, and thanks for the quick fix! It works perfectly now :+1:

I'll do my best to test as much as I can on the 0.10.x versions and let you know if I find anything weird indeed.

Thanks again for the great work :clap: