Added more logic for separate handling of creative/spectator modes.

This commit is contained in:
Andrew Lalis 2022-08-01 16:40:26 +02:00
parent dbb2e8a40f
commit 935cbd1393
9 changed files with 72 additions and 46 deletions

View File

@ -96,7 +96,7 @@ public class Client implements Runnable {
gameRenderer.getCamera().interpolatePosition(dt);
interpolatePlayers(now, dt);
interpolateProjectiles(dt);
soundManager.playWalkingSounds(myPlayer, now);
soundManager.playWalkingSounds(myPlayer, world, now);
gameRenderer.draw();
lastFrameAt = now;
@ -121,6 +121,7 @@ public class Client implements Runnable {
myPlayer.getPosition().set(playerUpdate.px(), playerUpdate.py(), playerUpdate.pz());
myPlayer.getVelocity().set(playerUpdate.vx(), playerUpdate.vy(), playerUpdate.vz());
myPlayer.setCrouching(playerUpdate.crouching());
myPlayer.setMode(playerUpdate.mode());
if (gameRenderer != null) {
gameRenderer.getCamera().setToPlayer(myPlayer);
}
@ -138,7 +139,7 @@ public class Client implements Runnable {
}
});
} else if (msg instanceof ClientInventoryMessage inventoryMessage) {
myPlayer.setInventory(inventoryMessage.inv());
runLater(() -> myPlayer.setInventory(inventoryMessage.inv()));
} else if (msg instanceof InventorySelectedStackMessage selectedStackMessage) {
myPlayer.getInventory().setSelectedIndex(selectedStackMessage.index());
} else if (msg instanceof ItemStackMessage itemStackMessage) {
@ -238,7 +239,7 @@ public class Client implements Runnable {
movement.set(player.getVelocity()).mul(dt);
player.getPosition().add(movement);
player.updateModelTransform();
soundManager.playWalkingSounds(player, now);
soundManager.playWalkingSounds(player, world, now);
}
gameRenderer.getGuiRenderer().updateNamePlates(players.values());
}

View File

@ -11,11 +11,14 @@ import nl.andrewl.aos2_client.render.model.Model;
import nl.andrewl.aos_core.model.PlayerMode;
import nl.andrewl.aos_core.model.Team;
import nl.andrewl.aos_core.model.item.BlockItemStack;
import nl.andrewl.aos_core.model.item.Inventory;
import nl.andrewl.aos_core.model.item.ItemTypes;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.lwjgl.glfw.*;
import org.lwjgl.glfw.Callbacks;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import java.io.IOException;
@ -173,6 +176,7 @@ public class GameRenderer {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
ClientPlayer myPlayer = client.getMyPlayer();
Inventory inv = myPlayer.getInventory();
if (inputHandler.isNormalContextActive() && inputHandler.getNormalContext().isScopeEnabled()) {
updatePerspective(15);
} else {
@ -199,7 +203,7 @@ public class GameRenderer {
// Render guns!
rifleModel.bind();
if (myPlayer.getInventory().getSelectedItemStack().getType().getId() == ItemTypes.RIFLE.getId()) {
if (inv.getSelectedItemStack() != null && inv.getSelectedItemStack().getType().getId() == ItemTypes.RIFLE.getId()) {
modelRenderer.render(rifleModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData());
}
for (var player : client.getPlayers().values()) {
@ -210,7 +214,7 @@ public class GameRenderer {
}
rifleModel.unbind();
smgModel.bind();
if (myPlayer.getInventory().getSelectedItemStack().getType().getId() == ItemTypes.AK_47.getId()) {
if (inv.getSelectedItemStack() != null && inv.getSelectedItemStack().getType().getId() == ItemTypes.AK_47.getId()) {
modelRenderer.render(smgModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData());
}
for (var player : client.getPlayers().values()) {
@ -221,7 +225,7 @@ public class GameRenderer {
}
smgModel.unbind();
shotgunModel.bind();
if (myPlayer.getInventory().getSelectedItemStack().getType().getId() == ItemTypes.WINCHESTER.getId()) {
if (inv.getSelectedItemStack() != null && inv.getSelectedItemStack().getType().getId() == ItemTypes.WINCHESTER.getId()) {
modelRenderer.render(shotgunModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData());
}
for (var player : client.getPlayers().values()) {
@ -233,7 +237,7 @@ public class GameRenderer {
shotgunModel.unbind();
blockModel.bind();
if (myPlayer.getInventory().getSelectedItemStack().getType().getId() == ItemTypes.BLOCK.getId()) {
if (inv.getSelectedItemStack() != null && inv.getSelectedItemStack().getType().getId() == ItemTypes.BLOCK.getId()) {
BlockItemStack stack = (BlockItemStack) myPlayer.getInventory().getSelectedItemStack();
modelRenderer.setAspectColor(client.getWorld().getPalette().getColor(stack.getSelectedValue()));
modelRenderer.render(blockModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData());

View File

@ -8,6 +8,7 @@ import nl.andrewl.aos2_client.render.ShaderProgram;
import nl.andrewl.aos2_client.sound.SoundSource;
import nl.andrewl.aos_core.FileUtils;
import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.PlayerMode;
import nl.andrewl.aos_core.model.item.BlockItem;
import nl.andrewl.aos_core.model.item.BlockItemStack;
import nl.andrewl.aos_core.model.item.Gun;
@ -196,10 +197,12 @@ public class GuiRenderer {
glUniform1i(namePlateTextureSamplerUniform, 0);
glUniformMatrix4fv(namePlateViewTransformUniform, false, viewTransformData);
glUniformMatrix4fv(namePlatePerspectiveTransformUniform, false, perspectiveTransformData);
// Show nameplates from farther away if we're in creative/spectator.
float nameplateRadius = myPlayer.getMode() == PlayerMode.NORMAL ? 50 : 200;
for (var entry : playerNamePlates.entrySet()) {
OtherPlayer player = entry.getKey();
// Skip rendering far-away nameplates.
if (player.getPosition().distance(myPlayer.getPosition()) > 50) continue;
// There are some scenarios where we skip rendering the name.
if (player.getPosition().distance(myPlayer.getPosition()) > nameplateRadius || player.getMode() == PlayerMode.SPECTATOR) continue;
GuiTexture texture = entry.getValue();
float aspectRatio = (float) texture.getHeight() / (float) texture.getWidth();
transformMatrix.identity()
@ -223,11 +226,12 @@ public class GuiRenderer {
nvgSave(vgId);
boolean scopeEnabled = client.getInputHandler().getNormalContext().isScopeEnabled();
PlayerMode mode = client.getMyPlayer().getMode();
drawCrosshair(width, height, scopeEnabled);
drawHeldItemStackInfo(width, height, client.getMyPlayer());
if (!scopeEnabled) {
drawChat(width, height, client);
drawHealthBar(width, height, client.getMyPlayer());
if (mode == PlayerMode.NORMAL) drawHealthBar(width, height, client.getMyPlayer());
}
if (client.getInputHandler().getNormalContext().isDebugEnabled()) {
drawDebugInfo(width, height, client);

View File

@ -1,6 +1,8 @@
package nl.andrewl.aos2_client.sound;
import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.PlayerMode;
import nl.andrewl.aos_core.model.world.World;
import org.joml.Vector3f;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.ALC;
@ -115,8 +117,9 @@ public class SoundManager {
play(soundName, gain, position, new Vector3f(0, 0, 0));
}
public void playWalkingSounds(Player player, long now) {
if (player.getVelocity().length() <= 0) return;
public void playWalkingSounds(Player player, World world, long now) {
// Don't play sounds for players who are still, non-normal mode, or not on the ground.
if (player.getVelocity().length() <= 0 || player.getMode() != PlayerMode.NORMAL || !player.isGrounded(world)) return;
long lastSoundAt = lastPlayerWalkingSounds.computeIfAbsent(player, p -> 0L);
long delay = 500; // Delay in ms between footfalls.
if (player.getVelocity().length() > 5) delay -= 150;

View File

@ -31,6 +31,7 @@ public class Inventory {
}
public ItemStack getSelectedItemStack() {
if (itemStacks.isEmpty()) return null;
return itemStacks.get(selectedIndex);
}
@ -62,4 +63,9 @@ public class Inventory {
}
return 1;
}
public void clear() {
itemStacks.clear();
selectedIndex = -1;
}
}

View File

@ -4,10 +4,7 @@ import nl.andrewl.aos2_server.model.ServerPlayer;
import nl.andrewl.aos_core.Net;
import nl.andrewl.aos_core.model.PlayerMode;
import nl.andrewl.aos_core.model.Team;
import nl.andrewl.aos_core.model.item.BlockItemStack;
import nl.andrewl.aos_core.model.item.Gun;
import nl.andrewl.aos_core.model.item.GunItemStack;
import nl.andrewl.aos_core.model.item.ItemStack;
import nl.andrewl.aos_core.model.item.*;
import nl.andrewl.aos_core.net.client.*;
import nl.andrewl.aos_core.net.connect.DatagramInit;
import nl.andrewl.record_net.Message;
@ -47,7 +44,7 @@ public class PlayerManager {
joinMessage = username + " joined the game.";
}
player.setPosition(getBestSpawnPoint(player));
player.setMode(PlayerMode.NORMAL);
setMode(player, PlayerMode.NORMAL);
// Tell all other players that this one has joined.
broadcastTcpMessageToAllBut(new PlayerJoinMessage(
player.getId(), player.getUsername(), player.getTeam() == null ? -1 : player.getTeam().getId(),
@ -201,6 +198,19 @@ public class PlayerManager {
handler.sendTcpMessage(ChatMessage.privateMessage("You've been resupplied at your team base."));
}
public void setMode(ServerPlayer player, PlayerMode mode) {
player.setMode(mode);
var inv = player.getInventory();
inv.clear();
if (mode == PlayerMode.NORMAL || mode == PlayerMode.CREATIVE) {
inv.getItemStacks().add(new GunItemStack(ItemTypes.RIFLE));
inv.getItemStacks().add(new GunItemStack(ItemTypes.AK_47));
inv.getItemStacks().add(new GunItemStack(ItemTypes.WINCHESTER));
inv.getItemStacks().add(new BlockItemStack(ItemTypes.BLOCK, 50, (byte) 1));
inv.setSelectedIndex(0);
}
}
public void handleUdpInit(DatagramInit init, DatagramPacket packet) {
var handler = getHandler(init.clientId());
if (handler != null) {

View File

@ -6,6 +6,7 @@ import nl.andrewl.aos2_server.cli.ingame.PlayerCommand;
import nl.andrewl.aos2_server.model.ServerPlayer;
import nl.andrewl.aos_core.model.PlayerMode;
import nl.andrewl.aos_core.net.client.ChatMessage;
import nl.andrewl.aos_core.net.client.ClientInventoryMessage;
public class PlayerModeCommand implements PlayerCommand {
@Override
@ -17,7 +18,8 @@ public class PlayerModeCommand implements PlayerCommand {
String modeText = args[0].trim().toUpperCase();
try {
PlayerMode mode = PlayerMode.valueOf(modeText);
player.setMode(mode);
server.getPlayerManager().setMode(player, mode);
handler.sendTcpMessage(new ClientInventoryMessage(player.getInventory()));
server.getPlayerManager().broadcastUdpMessage(player.getUpdateMessage(System.currentTimeMillis()));
} catch (IllegalArgumentException e) {
handler.sendTcpMessage(ChatMessage.privateMessage("Invalid mode. Should be NORMAL, CREATIVE, or SPECTATOR."));

View File

@ -65,27 +65,30 @@ public class PlayerActionManager {
public void tick(long now, float dt, World world, Server server) {
updated = false; // Reset the updated flag. This will be set to true if the player was updated in this tick.
if (player.getInventory().getSelectedIndex() != input.selectedInventoryIndex()) {
player.getInventory().setSelectedIndex(input.selectedInventoryIndex());
// Tell the client that their inventory slot has been updated properly.
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new InventorySelectedStackMessage(player.getInventory().getSelectedIndex()));
updated = true; // Tell everyone else that this player's selected item has changed.
}
ItemStack selectedStack = player.getInventory().getSelectedItemStack();
if (selectedStack instanceof BlockItemStack b) {
tickBlockAction(now, server, world, b);
} else if (selectedStack instanceof GunItemStack g) {
tickGunAction(now, server, g);
}
if (player.getMode() != PlayerMode.SPECTATOR) {
if (player.getInventory().getSelectedIndex() != input.selectedInventoryIndex()) {
player.getInventory().setSelectedIndex(input.selectedInventoryIndex());
// Tell the client that their inventory slot has been updated properly.
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new InventorySelectedStackMessage(player.getInventory().getSelectedIndex()));
updated = true; // Tell everyone else that this player's selected item has changed.
}
if (
now - lastResupplyAt > server.getConfig().actions.resupplyCooldown * 1000 &&
player.getTeam() != null &&
player.getPosition().distance(player.getTeam().getSpawnPoint()) < server.getConfig().actions.resupplyRadius
) {
server.getPlayerManager().resupply(player);
lastResupplyAt = now;
ItemStack selectedStack = player.getInventory().getSelectedItemStack();
if (selectedStack instanceof BlockItemStack b) {
tickBlockAction(now, server, world, b);
} else if (selectedStack instanceof GunItemStack g) {
tickGunAction(now, server, g);
}
if (
now - lastResupplyAt > server.getConfig().actions.resupplyCooldown * 1000 &&
player.getTeam() != null &&
player.getPosition().distance(player.getTeam().getSpawnPoint()) < server.getConfig().actions.resupplyRadius
) {
server.getPlayerManager().resupply(player);
lastResupplyAt = now;
}
}
if (player.getMode() == PlayerMode.NORMAL && server.getConfig().actions.healthRegenPerSecond != 0 && player.getHealth() < 1) {

View File

@ -2,10 +2,7 @@ package nl.andrewl.aos2_server.model;
import nl.andrewl.aos2_server.logic.PlayerActionManager;
import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.item.BlockItemStack;
import nl.andrewl.aos_core.model.item.GunItemStack;
import nl.andrewl.aos_core.model.item.Inventory;
import nl.andrewl.aos_core.model.item.ItemTypes;
import nl.andrewl.aos_core.net.client.PlayerUpdateMessage;
import java.util.ArrayList;
@ -32,10 +29,6 @@ public class ServerPlayer extends Player {
this.inventory = new Inventory(new ArrayList<>(), 0);
this.health = 1f;
this.actionManager = new PlayerActionManager(this);
inventory.getItemStacks().add(new GunItemStack(ItemTypes.RIFLE));
inventory.getItemStacks().add(new GunItemStack(ItemTypes.AK_47));
inventory.getItemStacks().add(new GunItemStack(ItemTypes.WINCHESTER));
inventory.getItemStacks().add(new BlockItemStack(ItemTypes.BLOCK, 50, (byte) 1));
}
public PlayerActionManager getActionManager() {
@ -84,7 +77,7 @@ public class ServerPlayer extends Player {
velocity.x, velocity.y, velocity.z,
orientation.x, orientation.y,
actionManager.getInput().crouching(),
inventory.getSelectedItemStack().getType().getId(),
inventory.getSelectedItemStack() == null ? -1 : inventory.getSelectedItemStack().getType().getId(),
mode
);
}