You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
5.7 KiB
259 lines
5.7 KiB
class Command { |
|
execute() { } |
|
toNetwork() { |
|
return null; |
|
} |
|
} |
|
|
|
class PunchCmd extends Command { |
|
execute(p) { |
|
p.punch(); |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: ' ', |
|
ActionType: "keyDown" |
|
}; |
|
} |
|
} |
|
|
|
class JumpCmd extends Command { |
|
execute(p) { |
|
p.jump(); |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: 'w', |
|
ActionType: 'keyDown' |
|
}; |
|
} |
|
} |
|
|
|
class CrouchPressCmd extends Command { |
|
execute(p) { |
|
p.crouching = true; |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: 's', |
|
ActionType: 'keyDown' |
|
}; |
|
} |
|
} |
|
|
|
class CrouchUnpressCmd extends Command { |
|
execute(p) { |
|
p.crouching = false; |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: 's', |
|
ActionType: 'keyUp' |
|
}; |
|
} |
|
} |
|
|
|
class MoveLeftPressCmd extends Command { |
|
execute(p) { |
|
p.keys.a = true; |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: 'a', |
|
ActionType: 'keyDown' |
|
}; |
|
|
|
} |
|
} |
|
|
|
class MoveLeftUnpressCmd extends Command { |
|
execute(p) { |
|
p.keys.a = false; |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: 'a', |
|
ActionType: 'keyUp' |
|
}; |
|
|
|
} |
|
} |
|
|
|
class MoveRightPressCmd extends Command { |
|
execute(p) { |
|
p.keys.d = true; |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: 'd', |
|
ActionType: 'keyDown' |
|
}; |
|
} |
|
} |
|
|
|
class MoveRightUnpressCmd extends Command { |
|
execute(p) { |
|
p.keys.d = false; |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: 'd', |
|
ActionType: 'keyUp' |
|
}; |
|
} |
|
} |
|
|
|
class TalkCmd extends Command { |
|
constructor(message) { |
|
super(); |
|
this.message = message; |
|
} |
|
execute(p) { |
|
p.talk(this.message); |
|
} |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: 't', |
|
ActionType: '', |
|
Message: this.message |
|
} |
|
} |
|
} |
|
|
|
class DisconnectedCmd extends Command { |
|
execute() { } |
|
toNetwork(p) { |
|
return { |
|
Id: p.id, |
|
Action: "disconnected", |
|
ActionType: "" |
|
}; |
|
} |
|
} |
|
|
|
export class InputHandler { |
|
constructor(game) { |
|
this.game = game; |
|
|
|
this.downMap = new Map([ |
|
[' ', () => new PunchCmd()], |
|
['w', () => new JumpCmd()], |
|
['s', () => new CrouchPressCmd()], |
|
['a', () => new MoveLeftPressCmd()], |
|
['d', () => new MoveRightPressCmd()], |
|
]); |
|
|
|
this.upMap = new Map([ |
|
['s', () => new CrouchUnpressCmd()], |
|
['a', () => new MoveLeftUnpressCmd()], |
|
['d', () => new MoveRightUnpressCmd()], |
|
]); |
|
} |
|
|
|
handleKeyDown(e, player) { |
|
const key = e.code === 'Space' ? ' ' : (e.key || '').toLowerCase(); |
|
const k = this.downMap.get(key); |
|
if (!k) { |
|
return; |
|
} |
|
|
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
this.dispatch(k(), player) |
|
} |
|
|
|
handleKeyUp(e, player) { |
|
const key = e.code === "Space" ? ' ' : e.key; |
|
const k = this.upMap.get(key); |
|
if (!k) { |
|
return; |
|
} |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
this.dispatch(k(), player) |
|
} |
|
|
|
dispatch(cmd, player) { |
|
if (!player) return; |
|
cmd.execute(player, this.game); |
|
if (player.isLocal) { |
|
const msg = cmd.toNetwork(player); |
|
if (msg) { |
|
this.game._send({ |
|
...msg, |
|
PosX: Math.floor(player.x), |
|
PosY: Math.floor(player.y), |
|
Facing: player.facing, |
|
Ts: Date.now(), |
|
}); |
|
} |
|
} |
|
} |
|
|
|
handleNetworkMessage(data) { |
|
this.game._ensurePlayer(data.Id); |
|
const p = this.game.players?.[data.Id]; |
|
if (!p) { |
|
return; |
|
} |
|
|
|
if (typeof data.PosX === "number") { |
|
p._lastTx = p._tx ?? data.PosX; |
|
p._tx = data.PosX; |
|
} |
|
if (typeof data.PosY === "number") { |
|
p._lastTy = p._ty ?? data.PosY; |
|
p._ty = data.PosY; |
|
} |
|
if (typeof data.Facing === "number") { |
|
p._tFacing = data.Facing; |
|
} |
|
|
|
p._lastUpdateTime = Date.now(); |
|
|
|
const action = data.Action; |
|
const actionType = data.ActionType; |
|
|
|
const apply = (cmd) => cmd && cmd.execute(p, this.game); |
|
|
|
switch (action) { |
|
case 'disconnected': |
|
delete this.game.players[data.Id]; |
|
break; |
|
case 't': |
|
apply(new TalkCmd(data.Message ?? "")); |
|
break; |
|
case ' ': |
|
apply(new PunchCmd()); |
|
break; |
|
case 'w': |
|
apply(new JumpCmd()); |
|
break; |
|
case 's': |
|
apply(actionType === 'keyDown' ? new CrouchPressCmd() : new CrouchUnpressCmd()); |
|
break; |
|
case 'a': |
|
apply(actionType === 'keyDown' ? new MoveLeftPressCmd() : new MoveLeftUnpressCmd()); |
|
break; |
|
case 'd': |
|
apply(actionType === 'keyDown' ? new MoveRightPressCmd() : new MoveRightUnpressCmd()); |
|
break; |
|
} |
|
} |
|
releaseAll(player) { |
|
const cmds = []; |
|
if (player.keys?.a) cmds.push(new MoveLeftUnpressCmd()); |
|
if (player.keys?.d) cmds.push(new MoveRightUnpressCmd()); |
|
if (player.crouching) cmds.push(new CrouchUnpressCmd()); |
|
for (const c of cmds) this.dispatch(c, player); |
|
} |
|
}
|
|
|