Added ability to change teams, and removed teams from creative and spectator players.
This commit is contained in:
parent
352faff005
commit
20295596fa
|
@ -156,6 +156,14 @@ public class Client implements Runnable {
|
||||||
});
|
});
|
||||||
} else if (msg instanceof PlayerLeaveMessage leaveMessage) {
|
} else if (msg instanceof PlayerLeaveMessage leaveMessage) {
|
||||||
runLater(() -> players.remove(leaveMessage.id()));
|
runLater(() -> players.remove(leaveMessage.id()));
|
||||||
|
} else if (msg instanceof PlayerTeamUpdateMessage teamUpdateMessage) {
|
||||||
|
runLater(() -> {
|
||||||
|
OtherPlayer op = players.get(teamUpdateMessage.playerId());
|
||||||
|
Team team = teamUpdateMessage.teamId() == -1 ? null : teams.get(teamUpdateMessage.teamId());
|
||||||
|
if (op != null) {
|
||||||
|
op.setTeam(team);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (msg instanceof SoundMessage soundMessage) {
|
} else if (msg instanceof SoundMessage soundMessage) {
|
||||||
if (soundManager != null) {
|
if (soundManager != null) {
|
||||||
soundManager.play(
|
soundManager.play(
|
||||||
|
|
|
@ -26,29 +26,37 @@ public final class Net {
|
||||||
|
|
||||||
private static final Serializer serializer = new Serializer();
|
private static final Serializer serializer = new Serializer();
|
||||||
static {
|
static {
|
||||||
serializer.registerType(1, ConnectRequestMessage.class);
|
int i = 1;
|
||||||
serializer.registerType(2, ConnectAcceptMessage.class);
|
// Basic protocol messages.
|
||||||
serializer.registerType(3, ConnectRejectMessage.class);
|
serializer.registerType(i++, ConnectRequestMessage.class);
|
||||||
serializer.registerType(4, DatagramInit.class);
|
serializer.registerType(i++, ConnectAcceptMessage.class);
|
||||||
serializer.registerType(5, ChunkHashMessage.class);
|
serializer.registerType(i++, ConnectRejectMessage.class);
|
||||||
serializer.registerType(6, ChunkDataMessage.class);
|
serializer.registerType(i++, DatagramInit.class);
|
||||||
serializer.registerType(7, ChunkUpdateMessage.class);
|
|
||||||
serializer.registerType(8, ClientInputState.class);
|
// World messages.
|
||||||
serializer.registerType(9, ClientOrientationState.class);
|
serializer.registerType(i++, ChunkHashMessage.class);
|
||||||
serializer.registerType(10, PlayerUpdateMessage.class);
|
serializer.registerType(i++, ChunkDataMessage.class);
|
||||||
serializer.registerType(11, PlayerJoinMessage.class);
|
serializer.registerType(i++, ChunkUpdateMessage.class);
|
||||||
serializer.registerType(12, PlayerLeaveMessage.class);
|
serializer.registerType(i++, ProjectileMessage.class);
|
||||||
|
|
||||||
|
// Player/client messages.
|
||||||
|
serializer.registerType(i++, ClientInputState.class);
|
||||||
|
serializer.registerType(i++, ClientOrientationState.class);
|
||||||
|
serializer.registerType(i++, ClientHealthMessage.class);
|
||||||
|
serializer.registerType(i++, PlayerUpdateMessage.class);
|
||||||
|
serializer.registerType(i++, PlayerJoinMessage.class);
|
||||||
|
serializer.registerType(i++, PlayerLeaveMessage.class);
|
||||||
|
serializer.registerType(i++, PlayerTeamUpdateMessage.class);
|
||||||
|
serializer.registerType(i++, BlockColorMessage.class);
|
||||||
|
serializer.registerType(i++, InventorySelectedStackMessage.class);
|
||||||
|
serializer.registerType(i++, ChatMessage.class);
|
||||||
|
serializer.registerType(i++, ChatWrittenMessage.class);
|
||||||
|
serializer.registerType(i++, ClientRecoilMessage.class);
|
||||||
// Separate serializers for client inventory messages.
|
// Separate serializers for client inventory messages.
|
||||||
serializer.registerTypeSerializer(13, new InventorySerializer());
|
serializer.registerTypeSerializer(i++, new InventorySerializer());
|
||||||
serializer.registerTypeSerializer(14, new ItemStackSerializer());
|
serializer.registerTypeSerializer(i++, new ItemStackSerializer());
|
||||||
serializer.registerType(15, InventorySelectedStackMessage.class);
|
|
||||||
serializer.registerType(16, SoundMessage.class);
|
serializer.registerType(i++, SoundMessage.class);
|
||||||
serializer.registerType(17, ProjectileMessage.class);
|
|
||||||
serializer.registerType(18, ClientHealthMessage.class);
|
|
||||||
serializer.registerType(19, BlockColorMessage.class);
|
|
||||||
serializer.registerType(20, ChatMessage.class);
|
|
||||||
serializer.registerType(21, ChatWrittenMessage.class);
|
|
||||||
serializer.registerType(22, ClientRecoilMessage.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExtendedDataInputStream getInputStream(InputStream in) {
|
public static ExtendedDataInputStream getInputStream(InputStream in) {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package nl.andrewl.aos_core.net.client;
|
||||||
|
|
||||||
|
import nl.andrewl.record_net.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message that's sent by the server to announce that a player has changed to
|
||||||
|
* a specified team. Both the player and team should already be recognized by
|
||||||
|
* all clients; otherwise they can ignore this.
|
||||||
|
*/
|
||||||
|
public record PlayerTeamUpdateMessage(
|
||||||
|
int playerId,
|
||||||
|
int teamId
|
||||||
|
) implements Message {}
|
|
@ -30,21 +30,26 @@ public class PlayerManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized ServerPlayer register(ClientCommunicationHandler handler, String username) {
|
public synchronized ServerPlayer register(ClientCommunicationHandler handler, String username) {
|
||||||
ServerPlayer player = new ServerPlayer(nextClientId++, username);
|
Team team = findBestTeamForNewPlayer();
|
||||||
|
ServerPlayer player = new ServerPlayer(nextClientId++, username, team, PlayerMode.NORMAL);
|
||||||
|
var inv = player.getInventory();
|
||||||
|
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);
|
||||||
|
|
||||||
System.out.printf("Registered player \"%s\" with id %d.%n", player.getUsername(), player.getId());
|
System.out.printf("Registered player \"%s\" with id %d.%n", player.getUsername(), player.getId());
|
||||||
players.put(player.getId(), player);
|
players.put(player.getId(), player);
|
||||||
clientHandlers.put(player.getId(), handler);
|
clientHandlers.put(player.getId(), handler);
|
||||||
String joinMessage;
|
String joinMessage;
|
||||||
Team team = findBestTeamForNewPlayer();
|
if (player.getTeam() != null) {
|
||||||
if (team != null) {
|
System.out.printf("Player \"%s\" joined the \"%s\" team.%n", player.getUsername(), player.getTeam().getName());
|
||||||
player.setTeam(team);
|
joinMessage = String.format("%s joined the %s team.", username, player.getTeam().getName());
|
||||||
System.out.printf("Player \"%s\" joined the \"%s\" team.%n", player.getUsername(), team.getName());
|
|
||||||
joinMessage = String.format("%s joined the %s team.", username, team.getName());
|
|
||||||
} else {
|
} else {
|
||||||
joinMessage = username + " joined the game.";
|
joinMessage = username + " joined the game.";
|
||||||
}
|
}
|
||||||
player.setPosition(getBestSpawnPoint(player));
|
player.setPosition(getBestSpawnPoint(player));
|
||||||
setMode(player, PlayerMode.NORMAL);
|
|
||||||
// Tell all other players that this one has joined.
|
// Tell all other players that this one has joined.
|
||||||
broadcastTcpMessageToAllBut(new PlayerJoinMessage(
|
broadcastTcpMessageToAllBut(new PlayerJoinMessage(
|
||||||
player.getId(), player.getUsername(), player.getTeam() == null ? -1 : player.getTeam().getId(),
|
player.getId(), player.getUsername(), player.getTeam() == null ? -1 : player.getTeam().getId(),
|
||||||
|
@ -163,12 +168,9 @@ public class PlayerManager {
|
||||||
*/
|
*/
|
||||||
public void playerKilled(ServerPlayer player, ServerPlayer killedBy) {
|
public void playerKilled(ServerPlayer player, ServerPlayer killedBy) {
|
||||||
Vector3f deathPosition = new Vector3f(player.getPosition());
|
Vector3f deathPosition = new Vector3f(player.getPosition());
|
||||||
player.setPosition(getBestSpawnPoint(player));
|
|
||||||
player.setVelocity(new Vector3f(0));
|
|
||||||
player.incrementDeathCount();
|
player.incrementDeathCount();
|
||||||
resupply(player);
|
|
||||||
broadcastUdpMessage(player.getUpdateMessage(System.currentTimeMillis()));
|
|
||||||
broadcastUdpMessage(new SoundMessage("death", 1, deathPosition));
|
broadcastUdpMessage(new SoundMessage("death", 1, deathPosition));
|
||||||
|
respawn(player);
|
||||||
String deathMessage;
|
String deathMessage;
|
||||||
if (killedBy != null) {
|
if (killedBy != null) {
|
||||||
killedBy.incrementKillCount();
|
killedBy.incrementKillCount();
|
||||||
|
@ -198,8 +200,16 @@ public class PlayerManager {
|
||||||
handler.sendTcpMessage(ChatMessage.privateMessage("You've been resupplied at your team base."));
|
handler.sendTcpMessage(ChatMessage.privateMessage("You've been resupplied at your team base."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void respawn(ServerPlayer player) {
|
||||||
|
player.setPosition(getBestSpawnPoint(player));
|
||||||
|
player.setVelocity(new Vector3f(0));
|
||||||
|
broadcastUdpMessage(player.getUpdateMessage(System.currentTimeMillis()));
|
||||||
|
resupply(player);
|
||||||
|
}
|
||||||
|
|
||||||
public void setMode(ServerPlayer player, PlayerMode mode) {
|
public void setMode(ServerPlayer player, PlayerMode mode) {
|
||||||
player.setMode(mode);
|
player.setMode(mode);
|
||||||
|
var handler = getHandler(player);
|
||||||
var inv = player.getInventory();
|
var inv = player.getInventory();
|
||||||
inv.clear();
|
inv.clear();
|
||||||
if (mode == PlayerMode.NORMAL || mode == PlayerMode.CREATIVE) {
|
if (mode == PlayerMode.NORMAL || mode == PlayerMode.CREATIVE) {
|
||||||
|
@ -208,7 +218,31 @@ public class PlayerManager {
|
||||||
inv.getItemStacks().add(new GunItemStack(ItemTypes.WINCHESTER));
|
inv.getItemStacks().add(new GunItemStack(ItemTypes.WINCHESTER));
|
||||||
inv.getItemStacks().add(new BlockItemStack(ItemTypes.BLOCK, 50, (byte) 1));
|
inv.getItemStacks().add(new BlockItemStack(ItemTypes.BLOCK, 50, (byte) 1));
|
||||||
inv.setSelectedIndex(0);
|
inv.setSelectedIndex(0);
|
||||||
|
handler.sendTcpMessage(new ClientInventoryMessage(inv));
|
||||||
|
broadcastUdpMessage(player.getUpdateMessage(System.currentTimeMillis()));
|
||||||
}
|
}
|
||||||
|
if (mode != PlayerMode.NORMAL) {
|
||||||
|
player.setTeam(null);
|
||||||
|
broadcastTcpMessage(new PlayerTeamUpdateMessage(player.getId(), -1));
|
||||||
|
} else {
|
||||||
|
player.setTeam(findBestTeamForNewPlayer());
|
||||||
|
broadcastTcpMessage(new PlayerTeamUpdateMessage(player.getId(), player.getTeam() == null ? -1 : player.getTeam().getId()));
|
||||||
|
}
|
||||||
|
handler.sendTcpMessage(ChatMessage.privateMessage("Your mode has been updated to " + mode.name() + "."));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTeam(ServerPlayer player, Team team) {
|
||||||
|
if (Objects.equals(team, player.getTeam()) || player.getMode() != PlayerMode.NORMAL) return;
|
||||||
|
player.setTeam(team);
|
||||||
|
broadcastUdpMessage(new PlayerTeamUpdateMessage(player.getId(), team == null ? -1 : team.getId()));
|
||||||
|
respawn(player);
|
||||||
|
String chatMessage;
|
||||||
|
if (team != null) {
|
||||||
|
chatMessage = "%s has changed to the %s team.".formatted(player.getUsername(), team.getName());
|
||||||
|
} else {
|
||||||
|
chatMessage = "%s has changed to not be on a team.".formatted(player.getUsername());
|
||||||
|
}
|
||||||
|
broadcastTcpMessage(ChatMessage.announce(chatMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleUdpInit(DatagramInit init, DatagramPacket packet) {
|
public void handleUdpInit(DatagramInit init, DatagramPacket packet) {
|
||||||
|
|
|
@ -33,6 +33,9 @@ public class TeamManager {
|
||||||
for (var team : teams.values()) {
|
for (var team : teams.values()) {
|
||||||
if (team.getName().equals(ident)) return Optional.of(team);
|
if (team.getName().equals(ident)) return Optional.of(team);
|
||||||
}
|
}
|
||||||
|
for (var team : teams.values()) {// Try again ignoring case.
|
||||||
|
if (team.getName().equalsIgnoreCase(ident)) return Optional.of(team);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
int id = Integer.parseInt(ident);
|
int id = Integer.parseInt(ident);
|
||||||
for (var team : teams.values()) {
|
for (var team : teams.values()) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import nl.andrewl.aos2_server.Server;
|
||||||
import nl.andrewl.aos2_server.cli.ingame.commands.KillCommand;
|
import nl.andrewl.aos2_server.cli.ingame.commands.KillCommand;
|
||||||
import nl.andrewl.aos2_server.cli.ingame.commands.KillDeathRatioCommand;
|
import nl.andrewl.aos2_server.cli.ingame.commands.KillDeathRatioCommand;
|
||||||
import nl.andrewl.aos2_server.cli.ingame.commands.PlayerModeCommand;
|
import nl.andrewl.aos2_server.cli.ingame.commands.PlayerModeCommand;
|
||||||
|
import nl.andrewl.aos2_server.cli.ingame.commands.TeamsCommand;
|
||||||
import nl.andrewl.aos2_server.model.ServerPlayer;
|
import nl.andrewl.aos2_server.model.ServerPlayer;
|
||||||
import nl.andrewl.aos_core.net.client.ChatMessage;
|
import nl.andrewl.aos_core.net.client.ChatMessage;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ public class PlayerCommandHandler {
|
||||||
commands.put("kd", new KillDeathRatioCommand());
|
commands.put("kd", new KillDeathRatioCommand());
|
||||||
commands.put("kill", new KillCommand());
|
commands.put("kill", new KillCommand());
|
||||||
commands.put("mode", new PlayerModeCommand());
|
commands.put("mode", new PlayerModeCommand());
|
||||||
|
commands.put("teams", new TeamsCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(String rawCommand, ServerPlayer player, ClientCommunicationHandler handler) {
|
public void handle(String rawCommand, ServerPlayer player, ClientCommunicationHandler handler) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import nl.andrewl.aos2_server.cli.ingame.PlayerCommand;
|
||||||
import nl.andrewl.aos2_server.model.ServerPlayer;
|
import nl.andrewl.aos2_server.model.ServerPlayer;
|
||||||
import nl.andrewl.aos_core.model.PlayerMode;
|
import nl.andrewl.aos_core.model.PlayerMode;
|
||||||
import nl.andrewl.aos_core.net.client.ChatMessage;
|
import nl.andrewl.aos_core.net.client.ChatMessage;
|
||||||
import nl.andrewl.aos_core.net.client.ClientInventoryMessage;
|
|
||||||
|
|
||||||
public class PlayerModeCommand implements PlayerCommand {
|
public class PlayerModeCommand implements PlayerCommand {
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,9 +18,6 @@ public class PlayerModeCommand implements PlayerCommand {
|
||||||
try {
|
try {
|
||||||
PlayerMode mode = PlayerMode.valueOf(modeText);
|
PlayerMode mode = PlayerMode.valueOf(modeText);
|
||||||
server.getPlayerManager().setMode(player, mode);
|
server.getPlayerManager().setMode(player, mode);
|
||||||
handler.sendTcpMessage(new ClientInventoryMessage(player.getInventory()));
|
|
||||||
server.getPlayerManager().broadcastUdpMessage(player.getUpdateMessage(System.currentTimeMillis()));
|
|
||||||
handler.sendTcpMessage(ChatMessage.privateMessage("Your mode has been updated to " + mode.name() + "."));
|
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
handler.sendTcpMessage(ChatMessage.privateMessage("Invalid mode. Should be NORMAL, CREATIVE, or SPECTATOR."));
|
handler.sendTcpMessage(ChatMessage.privateMessage("Invalid mode. Should be NORMAL, CREATIVE, or SPECTATOR."));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package nl.andrewl.aos2_server.cli.ingame.commands;
|
||||||
|
|
||||||
|
import nl.andrewl.aos2_server.ClientCommunicationHandler;
|
||||||
|
import nl.andrewl.aos2_server.Server;
|
||||||
|
import nl.andrewl.aos2_server.cli.ingame.PlayerCommand;
|
||||||
|
import nl.andrewl.aos2_server.model.ServerPlayer;
|
||||||
|
import nl.andrewl.aos_core.model.Team;
|
||||||
|
import nl.andrewl.aos_core.net.client.ChatMessage;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TeamsCommand implements PlayerCommand {
|
||||||
|
@Override
|
||||||
|
public void handle(String[] args, ServerPlayer player, ClientCommunicationHandler handler, Server server) {
|
||||||
|
if (args.length == 0) {
|
||||||
|
String teamsString = server.getTeamManager().getTeams().stream()
|
||||||
|
.map(Team::getName).collect(Collectors.joining(", "));
|
||||||
|
handler.sendTcpMessage(ChatMessage.privateMessage(teamsString));
|
||||||
|
} else {
|
||||||
|
String cmd = args[0].trim().toLowerCase();
|
||||||
|
if (cmd.equals("set")) {
|
||||||
|
if (args.length >= 2) {
|
||||||
|
String teamIdent = args[1].trim();
|
||||||
|
server.getTeamManager().findByIdOrName(teamIdent)
|
||||||
|
.ifPresentOrElse(
|
||||||
|
team -> server.getPlayerManager().setTeam(player, team),
|
||||||
|
() -> handler.sendTcpMessage(ChatMessage.privateMessage("Unknown team."))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
handler.sendTcpMessage(ChatMessage.privateMessage("Missing required team identifier."));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handler.sendTcpMessage(ChatMessage.privateMessage("Unknown subcommand."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ package nl.andrewl.aos2_server.model;
|
||||||
|
|
||||||
import nl.andrewl.aos2_server.logic.PlayerActionManager;
|
import nl.andrewl.aos2_server.logic.PlayerActionManager;
|
||||||
import nl.andrewl.aos_core.model.Player;
|
import nl.andrewl.aos_core.model.Player;
|
||||||
|
import nl.andrewl.aos_core.model.PlayerMode;
|
||||||
|
import nl.andrewl.aos_core.model.Team;
|
||||||
import nl.andrewl.aos_core.model.item.Inventory;
|
import nl.andrewl.aos_core.model.item.Inventory;
|
||||||
import nl.andrewl.aos_core.net.client.PlayerUpdateMessage;
|
import nl.andrewl.aos_core.net.client.PlayerUpdateMessage;
|
||||||
|
|
||||||
|
@ -24,8 +26,8 @@ public class ServerPlayer extends Player {
|
||||||
private int deathCount;
|
private int deathCount;
|
||||||
private int killCount;
|
private int killCount;
|
||||||
|
|
||||||
public ServerPlayer(int id, String username) {
|
public ServerPlayer(int id, String username, Team team, PlayerMode mode) {
|
||||||
super(id, username);
|
super(id, username, team, mode);
|
||||||
this.inventory = new Inventory(new ArrayList<>(), 0);
|
this.inventory = new Inventory(new ArrayList<>(), 0);
|
||||||
this.health = 1f;
|
this.health = 1f;
|
||||||
this.actionManager = new PlayerActionManager(this);
|
this.actionManager = new PlayerActionManager(this);
|
||||||
|
|
Loading…
Reference in New Issue