summaryrefslogtreecommitdiff
path: root/test-client
diff options
context:
space:
mode:
Diffstat (limited to 'test-client')
-rw-r--r--test-client/main.ts50
-rw-r--r--test-client/protocol.ts1
-rw-r--r--test-client/visual.ts7
3 files changed, 38 insertions, 20 deletions
diff --git a/test-client/main.ts b/test-client/main.ts
index 8d19be51..18382b04 100644
--- a/test-client/main.ts
+++ b/test-client/main.ts
@@ -24,7 +24,8 @@ import { Gamedata, ItemIndex, ItemLocation, Message, MessageTimeout, PacketC, Pa
import { V2, lerp_exp_v2_mut, normalize, lerp_exp } from "./util.ts";
import { draw_ingame, draw_wait } from "./visual.ts";
-const KEY_INTERACT = "KeyJ"
+const KEY_INTERACT_LEFT = "KeyJ"
+const KEY_INTERACT_RIGHT = "KeyL"
const KEY_BOOST = "KeyK"
const KEY_UP = "KeyW"
const KEY_DOWN = "KeyS"
@@ -32,7 +33,8 @@ const KEY_LEFT = "KeyA"
const KEY_RIGHT = "KeyD"
const KEY_CHAT = "Enter"
const KEY_CLOSE = "Escape"
-const HANDLED_KEYS = [KEY_INTERACT, KEY_BOOST, KEY_CHAT, KEY_CLOSE, KEY_DOWN, KEY_UP, KEY_LEFT, KEY_RIGHT]
+const KEY_ZOOM = "KeyI"
+const HANDLED_KEYS = [KEY_INTERACT_LEFT, KEY_BOOST, KEY_CHAT, KEY_CLOSE, KEY_DOWN, KEY_UP, KEY_LEFT, KEY_RIGHT]
export let ctx: CanvasRenderingContext2D;
export let canvas: HTMLCanvasElement;
@@ -80,10 +82,13 @@ export interface Involvement {
speed: number,
warn: boolean
}
+export interface ItemSlot {
+ item?: ItemData,
+}
export interface PlayerData extends MovementBase {
id: number,
name: string,
- item?: ItemData,
+ hands: ItemSlot[],
direction: V2,
class: PlayerClass,
character: number,
@@ -93,11 +98,10 @@ export interface PlayerData extends MovementBase {
message?: MessageData,
}
-export interface TileData {
+export interface TileData extends ItemSlot {
x: number, y: number // tile position
position: V2, // center position
kind: TileIndex
- item?: ItemData
}
export type MessageStyle = "hint" | "normal" | "error" | "pinned"
export interface MessageData {
@@ -113,7 +117,7 @@ export const tiles = new Map<string, TileData>()
export const items_removed = new Set<ItemData>()
export const server_hints = new Map<string, MessageData>()
-export let data: Gamedata = { item_names: [], tile_names: [], spawn: [0, 0], tile_collide: [], tile_interact: [], maps: [] }
+export let data: Gamedata = { item_names: [], tile_names: [], spawn: [0, 0], tile_collide: [], tile_interact: [], maps: [], hand_count: 0 }
export let global_message: MessageData | undefined = undefined
export let my_id: PlayerID = -1
@@ -128,9 +132,14 @@ export let is_lobby = false
let interacting: V2 | undefined;
let last_server_sent_position: V2 = { x: 0, y: 0 }
-function get_item_location(loc: ItemLocation): PlayerData | TileData {
+function get_item_location(loc: ItemLocation): ItemSlot {
if ("tile" in loc) return tiles.get(loc.tile.toString())!
- if ("player" in loc) return players.get(loc.player[0])!
+ if ("player" in loc) return players.get(loc.player[0])!.hands[loc.player[1]]
+ throw new Error("invalid item location");
+}
+function get_item_location_tracking(loc: ItemLocation): V2 {
+ if ("tile" in loc) return tiles.get(loc.tile.toString())!.position
+ if ("player" in loc) return players.get(loc.player[0])!.position
throw new Error("invalid item location");
}
@@ -154,6 +163,7 @@ function packet(p: PacketC) {
case "add_player": {
players.set(p.id, {
id: p.id,
+ hands: new Array(data.hand_count).fill(null).map(() => ({})),
position: { x: p.position[0], y: p.position[1], },
anim_position: { x: p.position[0], y: p.position[1] },
character: p.character.color,
@@ -189,16 +199,17 @@ function packet(p: PacketC) {
const to = get_item_location(p.to)
to.item = from.item
- to.item!.tracking = to.position
+ to.item!.tracking = get_item_location_tracking(p.to)
from.item = undefined
break;
}
case "set_item": {
const slot = get_item_location(p.location)
+ const slotpos = get_item_location_tracking(p.location)
if (slot.item !== undefined && slot.item !== null) items_removed.add(slot.item)
- slot.item = undefined
- if (p.item !== undefined && p.item !== null) slot.item = { kind: p.item, x: slot.position.x, y: slot.position.y, tracking: slot.position }
+ delete slot.item
+ if (p.item !== undefined && p.item !== null) slot.item = { kind: p.item, x: slotpos.x, y: slotpos.y, tracking: slotpos }
break;
}
case "clear_progress": {
@@ -345,8 +356,10 @@ function keyboard(ev: KeyboardEvent, down: boolean) {
else if (down && ev.code == KEY_CLOSE && chat) return close_chat()
else if (chat) return
if (HANDLED_KEYS.includes(ev.code)) ev.preventDefault()
- if (!keys_down.has(KEY_INTERACT) && ev.code == KEY_INTERACT && down) set_interact(true)
- if (keys_down.has(KEY_INTERACT) && ev.code == KEY_INTERACT && !down) set_interact(false)
+ if (!keys_down.has(KEY_INTERACT_LEFT) && ev.code == KEY_INTERACT_LEFT && down) set_interact(true, 0)
+ if (keys_down.has(KEY_INTERACT_LEFT) && ev.code == KEY_INTERACT_LEFT && !down) set_interact(false, 0)
+ if (!keys_down.has(KEY_INTERACT_RIGHT) && ev.code == KEY_INTERACT_RIGHT && down) set_interact(true, 1)
+ if (keys_down.has(KEY_INTERACT_RIGHT) && ev.code == KEY_INTERACT_RIGHT && !down) set_interact(false, 1)
if (down && ev.code in QUICK_COMMANDS) send({ player: my_id, type: "communicate", message: { text: QUICK_COMMANDS[ev.code] } })
if (down && ev.code == "KeyE") particle_splash(get_interact_target() ?? { x: 0, y: 0 }, 0.8)
if (down) keys_down.add(ev.code)
@@ -412,9 +425,9 @@ export function get_interact_target(): V2 | undefined {
return best
}
-function set_interact(edge: boolean) {
+function set_interact(edge: boolean, hand: number) {
if (edge) interacting = get_interact_target()
- if (interacting) send({ player: my_id, type: "interact", pos: edge ? [interacting.x, interacting.y] : undefined, hand: 0 })
+ if (interacting) send({ player: my_id, type: "interact", pos: edge ? [interacting.x, interacting.y] : undefined, hand })
if (!edge) interacting = undefined
}
@@ -445,13 +458,12 @@ function frame_update(dt: number) {
const update_item = (item: ItemData) => {
if (item.tracking) lerp_exp_v2_mut(item, item.tracking, dt * 10.)
if (item.active) item.active.position += item.active.speed * dt
-
}
let pin_xo = 0
for (const [pid, player] of players) {
if (pid == my_id) player.anim_position.x = player.position.x, player.anim_position.y = player.position.y
else lerp_exp_v2_mut(player.anim_position, player.position, dt * 15)
- if (player.item !== undefined && player.item !== null) update_item(player.item)
+ player.hands.forEach(h => { if (h.item) update_item(h.item) })
if (player.message && tick_message(player.message, dt)) delete player.message
if (player.message_persist && tick_message(player.message_persist, dt)) delete player.message_persist
if (player.message_pinned && tick_message(player.message_pinned, dt)) delete player.message_pinned
@@ -482,9 +494,9 @@ function frame_update(dt: number) {
interact_possible_anim = lerp_exp(interact_possible_anim, +possible, dt * 18.)
interact_active_anim = lerp_exp(interact_active_anim, +!!interacting, dt * 15.)
- const zoom_target = Math.min(canvas.width, canvas.height) * (keys_down.has("KeyL") ? 0.05 : 0.1)
+ const zoom_target = Math.min(canvas.width, canvas.height) * (keys_down.has(KEY_ZOOM) ? 0.05 : 0.1)
camera_scale = lerp_exp(camera_scale, zoom_target, dt * 5)
- overlay_vis_anim = lerp_exp(overlay_vis_anim, +keys_down.has("KeyL"), dt * 10)
+ overlay_vis_anim = lerp_exp(overlay_vis_anim, +keys_down.has(KEY_ZOOM), dt * 10)
tick_particles(dt)
}
diff --git a/test-client/protocol.ts b/test-client/protocol.ts
index 1cfdab79..fb8c11a8 100644
--- a/test-client/protocol.ts
+++ b/test-client/protocol.ts
@@ -34,6 +34,7 @@ export interface Gamedata {
tile_interact: boolean[], // Look-up table for TileIndex to check if a tile is interactable
spawn: Vec2, // Where players spawn when they join.
maps: [string, MapMetadata][], // Metadata for most available maps
+ hand_count: number,
}
export type PacketS =
diff --git a/test-client/visual.ts b/test-client/visual.ts
index c5f34c1c..80c36da2 100644
--- a/test-client/visual.ts
+++ b/test-client/visual.ts
@@ -147,7 +147,12 @@ function draw_player(player: PlayerData) {
if (player.boosting) ctx.scale(1.3, 1.3)
draw_character(player.class, player.character)
ctx.restore()
- if (player.item) draw_item(player.item)
+ ctx.save()
+ for (const h of player.hands) {
+ if (h.item) draw_item(h.item)
+ ctx.translate(0.2, 0.0)
+ }
+ ctx.restore()
}
function draw_player_nametag(player: PlayerData) {