Skip to content

Commit

Permalink
feat: transmit and display held item when spectating
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacThoman committed Jan 18, 2025
1 parent ba6cccf commit de13c97
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 15 deletions.
52 changes: 37 additions & 15 deletions src/client/core/Inventory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { ItemBase, ItemType } from '../items/ItemBase.ts';
import { FishGun } from '../items/FishGun.ts';
import { Player } from '../../shared/Player.ts';
import { FlagItem } from '../items/FlagItem.ts';

export class Inventory {
private inventoryItems: ItemBase[] = [];
private renderer: Renderer;
Expand All @@ -24,6 +23,7 @@ export class Inventory {
private lastInventoryTouchTime: number = 0;
private localPlayer: Player;
private oldInventory: number[] = [];
private lastShootTime: number = 0;

private oldDownPressed: boolean = false;
private oldUpPressed: boolean = false;
Expand All @@ -44,15 +44,17 @@ export class Inventory {
}

private updateInventoryItems() {
if (!this.arraysEqual(this.oldInventory, this.localPlayer.inventory)) {
const spectatedPlayer = this.networking.getSpectatedPlayer();
const currentInventory = spectatedPlayer ? spectatedPlayer.inventory : this.localPlayer.inventory;

if (!this.arraysEqual(this.oldInventory, currentInventory)) {
for (let i = this.inventoryItems.length - 1; i >= 0; i--) {
this.inventoryItems[i].destroy();
this.inventoryItems.splice(i, 1);
}

//iterate through every number in localPlayer.inventory
for (let i = 0; i < this.localPlayer.inventory.length; i++) {
const num = this.localPlayer.inventory[i];
for (let i = 0; i < currentInventory.length; i++) {
const num = currentInventory[i];
switch (num) {
case 1: {
const banana = new BananaGun(this.renderer, this.networking, i, ItemType.InventoryItem);
Expand Down Expand Up @@ -83,7 +85,7 @@ export class Inventory {
}
}

this.oldInventory = this.localPlayer.inventory;
this.oldInventory = currentInventory;
}

public arraysEqual(a: number[], b: number[]) {
Expand All @@ -99,11 +101,26 @@ export class Inventory {
public onFrame() {
this.updateInventoryItems();
const gamepadInputs = this.inputHandler.getGamepadInputs();
const heldItemInput = new HeldItemInput(this.inputHandler.getShoot(), this.inputHandler.getAim(), false);
const spectatedPlayer = this.networking.getSpectatedPlayer();

// Handle shooting with tick rate timing
const currentTime = Date.now() / 1000;
const tickDuration = 1 / this.networking.getServerInfo().tickRate;
if (this.inputHandler.getShoot()) {
this.lastShootTime = currentTime;
}
const isShootActive = currentTime - this.lastShootTime < tickDuration;

// Use spectated player's states if available, otherwise use local states
const rightClickHeld = spectatedPlayer ? spectatedPlayer.rightClickHeld : this.inputHandler.getAim();
const shooting = spectatedPlayer ? spectatedPlayer.shooting : isShootActive;
const heldItemInput = new HeldItemInput(shooting, rightClickHeld, false);

let downPressed = (this.inputHandler.getKey('[') || this.inputHandler.getInventoryIterationTouched()) &&
!this.localPlayer.chatActive;
let upPressed = this.inputHandler.getKey(']') && !this.localPlayer.chatActive;
const qPressed = this.inputHandler.getKey('q') && !this.localPlayer.chatActive;

if (gamepadInputs.leftShoulder && !this.localPlayer.chatActive) upPressed = true;
if (gamepadInputs.rightShoulder && !this.localPlayer.chatActive) downPressed = true;
const lastScroll = this.inputHandler.getScrollClicks();
Expand All @@ -117,17 +134,16 @@ export class Inventory {
if (numPressed && !this.oldNumsPressed[i]) {
this.lastSelectedInventoryItem = this.selectedInventoryItem;
this.selectedInventoryItem = i;
this.lastInventoryTouchTime = Date.now() / 1000;
this.lastInventoryTouchTime = currentTime;
break;
}
}

for (let i = 0; i < nums.length; i++) {
this.oldNumsPressed[i] = this.inputHandler.getKey(nums[i]);
}
}

if (downPressed || upPressed) this.lastInventoryTouchTime = Date.now() / 1000;
if (downPressed || upPressed) this.lastInventoryTouchTime = currentTime;
const deltaTime = this.clock.getDelta();

if (downPressed && !this.oldDownPressed) {
Expand All @@ -139,14 +155,13 @@ export class Inventory {
this.selectedInventoryItem--;
}
if (this.inputHandler.getKey('enter')) {
this.lastInventoryTouchTime = 0; //hide inventory
this.lastInventoryTouchTime = 0;
}

if (qPressed && !this.oldQPressed) {
const temp = this.selectedInventoryItem;
this.selectedInventoryItem = this.lastSelectedInventoryItem;
this.lastSelectedInventoryItem = temp;
//this.lastInventoryTouchTime = Date.now() / 1000 - 1.25;
}

if (this.selectedInventoryItem < 0) {
Expand All @@ -163,17 +178,24 @@ export class Inventory {
this.lastSelectedInventoryItem = 0;
}

this.cameraY = this.selectedInventoryItem; //might be backwards
if (Date.now() / 1000 - this.lastInventoryTouchTime > 2) {
// Update localPlayer's states
this.localPlayer.heldItemIndex = this.selectedInventoryItem;
this.localPlayer.rightClickHeld = this.inputHandler.getAim();
this.localPlayer.shooting = isShootActive;

this.cameraY = this.selectedInventoryItem;
if (currentTime - this.lastInventoryTouchTime > 2) {
this.cameraX = -1;
} else {
this.cameraX = 0;
}

this.camera.position.lerp(new THREE.Vector3(this.cameraX, this.selectedInventoryItem, 5), 0.4 * deltaTime * 60);

const currentSelectedItem = spectatedPlayer ? spectatedPlayer.heldItemIndex : this.selectedInventoryItem;

for (const item of this.inventoryItems) {
item.onFrame(heldItemInput, this.selectedInventoryItem);
item.onFrame(heldItemInput, currentSelectedItem);
}

this.oldDownPressed = downPressed;
Expand Down
6 changes: 6 additions & 0 deletions src/client/core/Networking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ export class Networking {
return this.serverInfo;
}

public getSpectatedPlayer(): PlayerData | undefined {
if (this.localPlayer.playerSpectating === -1) return undefined;
return this.remotePlayers.find((player) => player.id === this.localPlayer.playerSpectating);
}

private processRemotePlayerData() {
this.messagesBeingTyped = [];
for (const remotePlayer of this.remotePlayers) {
Expand Down Expand Up @@ -256,6 +261,7 @@ export class Networking {
}

public applyDamage(id: number, damage: number) {
if (this.localPlayer.playerSpectating !== -1) return;
const player2 = this.remotePlayers.find((player) => player.id === id)!;
const damageRequest = {
localPlayer: this.localPlayer,
Expand Down
3 changes: 3 additions & 0 deletions src/server/DataValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ export class DataValidator {
updateTimestamp: z.number().optional(),
lastDamageTime: z.number().optional(),
inventory: z.array(z.number()),
heldItemIndex: z.number(),
shooting: z.boolean(),
rightClickHeld: z.boolean(),
idLastDamagedBy: z.number().optional(),
playerSpectating: z.number(),
gameMsgs: z.array(z.string()),
Expand Down
5 changes: 5 additions & 0 deletions src/server/managers/DamageSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export class DamageSystem {
return;
}

if (localPlayer.playerSpectating !== -1) {
console.log('⚠️Player is spectating, cannot apply damage');
return;
}

// Apply damage
targetPlayer.health -= data.damage / targetPlayer.protection;
targetPlayer.lastDamageTime = Date.now() / 1000;
Expand Down
3 changes: 3 additions & 0 deletions src/shared/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export class Player {
public forced = false; //server-controlled
public forcedAcknowledged = false;
public inventory: number[] = []; //server-controlled
public heldItemIndex = 0;
public shooting = false;
public rightClickHeld = false;
public idLastDamagedBy?: number = -1; //server-controlled
public playerSpectating = -1; //server-controlled
public gameMsgs: string[] = []; //server-controlled
Expand Down

0 comments on commit de13c97

Please sign in to comment.