Scoreboard implementation

This commit is contained in:
Bixilon 2020-06-20 23:52:52 +02:00
parent 200476c3dd
commit 7bbfdf638b
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 701 additions and 0 deletions

View File

@ -19,6 +19,7 @@ import de.bixilon.minosoft.game.datatypes.inventory.Inventory;
import de.bixilon.minosoft.game.datatypes.inventory.InventoryProperties; import de.bixilon.minosoft.game.datatypes.inventory.InventoryProperties;
import de.bixilon.minosoft.game.datatypes.inventory.InventorySlots; import de.bixilon.minosoft.game.datatypes.inventory.InventorySlots;
import de.bixilon.minosoft.game.datatypes.inventory.Slot; import de.bixilon.minosoft.game.datatypes.inventory.Slot;
import de.bixilon.minosoft.game.datatypes.scoreboard.ScoreboardManager;
import de.bixilon.minosoft.game.datatypes.world.World; import de.bixilon.minosoft.game.datatypes.world.World;
import de.bixilon.minosoft.mojang.api.MojangAccount; import de.bixilon.minosoft.mojang.api.MojangAccount;
@ -29,6 +30,7 @@ import static de.bixilon.minosoft.protocol.protocol.ProtocolDefinition.PLAYER_IN
public class Player { public class Player {
final MojangAccount acc; final MojangAccount acc;
final ScoreboardManager scoreboardManager = new ScoreboardManager();
float health; float health;
short food; short food;
float saturation; float saturation;
@ -194,4 +196,8 @@ public class Player {
public void setSpawnConfirmed(boolean spawnConfirmed) { public void setSpawnConfirmed(boolean spawnConfirmed) {
this.spawnConfirmed = spawnConfirmed; this.spawnConfirmed = spawnConfirmed;
} }
public ScoreboardManager getScoreboardManager() {
return scoreboardManager;
}
} }

View File

@ -0,0 +1,51 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.game.datatypes.scoreboard;
import java.util.HashMap;
public class ScoreboardManager {
final HashMap<String, ScoreboardTeam> teams;
final HashMap<String, ScoreboardObjective> objectives;
public ScoreboardManager() {
teams = new HashMap<>();
objectives = new HashMap<>();
}
public void addTeam(ScoreboardTeam team) {
teams.put(team.getName(), team);
}
public ScoreboardTeam getTeam(String name) {
return teams.get(name);
}
public void removeTeam(String name) {
teams.remove(name);
}
public void addObjective(ScoreboardObjective objective) {
objectives.put(objective.getObjectiveName(), objective);
}
public void removeObjective(String name) {
objectives.remove(name);
}
public ScoreboardObjective getObjective(String objective) {
return objectives.get(objective);
}
}

View File

@ -0,0 +1,62 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.game.datatypes.scoreboard;
import java.util.HashMap;
public class ScoreboardObjective {
final String objectiveName;
final HashMap<String, ScoreboardScore> scores;
String objectiveValue;
public ScoreboardObjective(String objectiveName, String objectiveValue) {
this.objectiveName = objectiveName;
this.objectiveValue = objectiveValue;
this.scores = new HashMap<>();
}
public String getObjectiveName() {
return objectiveName;
}
public String getObjectiveValue() {
return objectiveValue;
}
public HashMap<String, ScoreboardScore> getScores() {
return scores;
}
public void addScore(ScoreboardScore score) {
if (scores.containsKey(score.getItemName())) {
// update
scores.get(score.getItemName()).setScoreName(score.getScoreName());
scores.get(score.getItemName()).setScore(score.getScore());
return;
}
scores.put(score.getItemName(), score);
}
public void removeScore(String itemName) {
scores.remove(itemName);
}
public ScoreboardScore getScore(String itemName) {
return scores.get(itemName);
}
public void setValue(String value) {
objectiveValue = value;
}
}

View File

@ -0,0 +1,46 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.game.datatypes.scoreboard;
public class ScoreboardScore {
final String itemName;
String scoreName;
int score;
public ScoreboardScore(String itemName, String scoreName, int score) {
this.itemName = itemName;
this.scoreName = scoreName;
this.score = score;
}
public String getItemName() {
return itemName;
}
public String getScoreName() {
return scoreName;
}
public void setScoreName(String scoreName) {
this.scoreName = scoreName;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}

View File

@ -0,0 +1,84 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.game.datatypes.scoreboard;
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketScoreboardTeams;
import java.util.Arrays;
import java.util.List;
public class ScoreboardTeam {
final String name;
String displayName;
String prefix;
String suffix;
PacketScoreboardTeams.ScoreboardFriendlyFire friendlyFire;
List<String> players;
public ScoreboardTeam(String name, String displayName, String prefix, String suffix, PacketScoreboardTeams.ScoreboardFriendlyFire friendlyFire, String[] players) {
this.name = name;
this.displayName = displayName;
this.prefix = prefix;
this.suffix = suffix;
this.friendlyFire = friendlyFire;
this.players = Arrays.asList(players);
}
public void updateInformation(String displayName, String prefix, String suffix, PacketScoreboardTeams.ScoreboardFriendlyFire friendlyFire) {
this.displayName = displayName;
this.prefix = prefix;
this.suffix = suffix;
this.friendlyFire = friendlyFire;
}
public String getName() {
return name;
}
public String getDisplayName() {
return displayName;
}
public String getPrefix() {
return prefix;
}
public String getSuffix() {
return suffix;
}
public PacketScoreboardTeams.ScoreboardFriendlyFire getFriendlyFire() {
return friendlyFire;
}
public void addPlayers(List<String> list) {
players.addAll(list);
}
public void addPlayer(String name) {
players.add(name);
}
public void removePlayers(List<String> list) {
players.removeAll(list);
}
public void removePlayer(String name) {
players.remove(name);
}
public List<String> getPlayers() {
return players;
}
}

View File

@ -0,0 +1,72 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.packets.clientbound.play;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketScoreboardDisplayScoreboard implements ClientboundPacket {
ScoreboardAnimation action;
String scoreName;
@Override
public void read(InPacketBuffer buffer, ProtocolVersion v) {
switch (v) {
case VERSION_1_7_10:
action = ScoreboardAnimation.byId(buffer.readByte());
scoreName = buffer.readString();
break;
}
}
@Override
public void log() {
Log.protocol(String.format("Received display scoreboard packet (position=%s, scoreName=\"%s\"", action.name(), scoreName));
}
@Override
public void handle(PacketHandler h) {
h.handle(this);
}
public enum ScoreboardAnimation {
LIST(0),
SIDEBAR(1),
BELOW_NAME(2);
final int id;
ScoreboardAnimation(int id) {
this.id = id;
}
public static ScoreboardAnimation byId(int id) {
for (ScoreboardAnimation a : values()) {
if (a.getId() == id) {
return a;
}
}
return null;
}
public int getId() {
return id;
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.packets.clientbound.play;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketScoreboardObjective implements ClientboundPacket {
String name;
String value;
ScoreboardObjectiveAction action;
@Override
public void read(InPacketBuffer buffer, ProtocolVersion v) {
switch (v) {
case VERSION_1_7_10:
name = buffer.readString();
value = buffer.readString();
action = ScoreboardObjectiveAction.byId(buffer.readByte());
break;
}
}
@Override
public void log() {
Log.protocol(String.format("Received scoreboard objective action (action=%s, name=\"%s\", value=\"%s\"", action.name(), name, value));
}
@Override
public void handle(PacketHandler h) {
h.handle(this);
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
public ScoreboardObjectiveAction getAction() {
return action;
}
public enum ScoreboardObjectiveAction {
CREATE(0),
REMOVE(1),
UPDATE(2);
final int id;
ScoreboardObjectiveAction(int id) {
this.id = id;
}
public static ScoreboardObjectiveAction byId(int id) {
for (ScoreboardObjectiveAction a : values()) {
if (a.getId() == id) {
return a;
}
}
return null;
}
public int getId() {
return id;
}
}
}

View File

@ -0,0 +1,144 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.packets.clientbound.play;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketScoreboardTeams implements ClientboundPacket {
String name;
ScoreboardTeamAction action;
String displayName;
String prefix;
String suffix;
ScoreboardFriendlyFire friendlyFire;
String[] playerNames;
@Override
public void read(InPacketBuffer buffer, ProtocolVersion v) {
switch (v) {
case VERSION_1_7_10:
name = buffer.readString();
action = ScoreboardTeamAction.byId(buffer.readByte());
if (action == ScoreboardTeamAction.CREATE || action == ScoreboardTeamAction.INFORMATION_UPDATE) {
displayName = buffer.readString();
prefix = buffer.readString();
suffix = buffer.readString();
friendlyFire = ScoreboardFriendlyFire.byId(buffer.readByte());
}
if (action == ScoreboardTeamAction.CREATE || action == ScoreboardTeamAction.PLAYER_ADD || action == ScoreboardTeamAction.PLAYER_REMOVE) {
short playerCount = buffer.readShort();
playerNames = new String[playerCount];
for (int i = 0; i < playerCount; i++) {
playerNames[i] = buffer.readString();
}
}
break;
}
}
@Override
public void log() {
Log.protocol(String.format("Received scoreboard Team update (name=\"%s\", action=%s, displayName=\"%s\", prefix=\"%s\", suffix=\"%s\", friendlyFire=%s, playerCount=%s)", name, action.name(), displayName, prefix, suffix, friendlyFire.name(), ((playerNames == null) ? "null" : playerNames.length)));
}
@Override
public void handle(PacketHandler h) {
h.handle(this);
}
public String getName() {
return name;
}
public ScoreboardTeamAction getAction() {
return action;
}
public String getDisplayName() {
return displayName;
}
public String getPrefix() {
return prefix;
}
public String getSuffix() {
return suffix;
}
public ScoreboardFriendlyFire getFriendlyFire() {
return friendlyFire;
}
public String[] getPlayerNames() {
return playerNames;
}
public enum ScoreboardTeamAction {
CREATE(0),
REMOVE(1),
INFORMATION_UPDATE(2),
PLAYER_ADD(3),
PLAYER_REMOVE(4);
final int id;
ScoreboardTeamAction(int id) {
this.id = id;
}
public static ScoreboardTeamAction byId(int id) {
for (ScoreboardTeamAction a : values()) {
if (a.getId() == id) {
return a;
}
}
return null;
}
public int getId() {
return id;
}
}
public enum ScoreboardFriendlyFire {
OFF(0),
ON(1),
SEE_FRIENDLY_INVISIBLES(3);
final int id;
ScoreboardFriendlyFire(int id) {
this.id = id;
}
public static ScoreboardFriendlyFire byId(int id) {
for (ScoreboardFriendlyFire f : values()) {
if (f.getId() == id) {
return f;
}
}
return null;
}
public int getId() {
return id;
}
}
}

View File

@ -0,0 +1,94 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.packets.clientbound.play;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketScoreboardUpdateScore implements ClientboundPacket {
String itemName;
ScoreboardUpdateScoreAction action;
String scoreName;
int scoreValue;
@Override
public void read(InPacketBuffer buffer, ProtocolVersion v) {
switch (v) {
case VERSION_1_7_10:
itemName = buffer.readString();
action = ScoreboardUpdateScoreAction.byId(buffer.readByte());
if (action == ScoreboardUpdateScoreAction.REMOVE) {
break;
}
// not present id action == REMOVE
scoreName = buffer.readString();
scoreValue = buffer.readInteger();
break;
}
}
@Override
public void log() {
Log.protocol(String.format("Received scoreboard score update (itemName=\"%s\", action=%s, scoreName=\"%s\", scoreValue=%d", itemName, action.name(), scoreName, scoreValue));
}
@Override
public void handle(PacketHandler h) {
h.handle(this);
}
public String getItemName() {
return itemName;
}
public ScoreboardUpdateScoreAction getAction() {
return action;
}
public String getScoreName() {
return scoreName;
}
public int getScoreValue() {
return scoreValue;
}
public enum ScoreboardUpdateScoreAction {
CREATE_UPDATE(0),
REMOVE(1);
final int id;
ScoreboardUpdateScoreAction(int id) {
this.id = id;
}
public static ScoreboardUpdateScoreAction byId(int id) {
for (ScoreboardUpdateScoreAction a : values()) {
if (a.getId() == id) {
return a;
}
}
return null;
}
public int getId() {
return id;
}
}
}

View File

@ -16,6 +16,9 @@ package de.bixilon.minosoft.protocol.protocol;
import de.bixilon.minosoft.game.datatypes.GameMode; import de.bixilon.minosoft.game.datatypes.GameMode;
import de.bixilon.minosoft.game.datatypes.blocks.Blocks; import de.bixilon.minosoft.game.datatypes.blocks.Blocks;
import de.bixilon.minosoft.game.datatypes.entities.meta.HumanMetaData; import de.bixilon.minosoft.game.datatypes.entities.meta.HumanMetaData;
import de.bixilon.minosoft.game.datatypes.scoreboard.ScoreboardObjective;
import de.bixilon.minosoft.game.datatypes.scoreboard.ScoreboardScore;
import de.bixilon.minosoft.game.datatypes.scoreboard.ScoreboardTeam;
import de.bixilon.minosoft.game.datatypes.world.BlockPosition; import de.bixilon.minosoft.game.datatypes.world.BlockPosition;
import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.protocol.network.Connection;
@ -32,6 +35,7 @@ import de.bixilon.minosoft.protocol.packets.serverbound.play.PacketPlayerPositio
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.Arrays;
public class PacketHandler { public class PacketHandler {
final Connection connection; final Connection connection;
@ -359,4 +363,54 @@ public class PacketHandler {
public void handle(PacketEffect pkg) { public void handle(PacketEffect pkg) {
//ToDo //ToDo
} }
public void handle(PacketScoreboardObjective pkg) {
switch (pkg.getAction()) {
case CREATE:
connection.getPlayer().getScoreboardManager().addObjective(new ScoreboardObjective(pkg.getName(), pkg.getValue()));
break;
case UPDATE:
connection.getPlayer().getScoreboardManager().getObjective(pkg.getName()).setValue(pkg.getValue());
break;
case REMOVE:
connection.getPlayer().getScoreboardManager().removeObjective(pkg.getName());
break;
}
}
public void handle(PacketScoreboardUpdateScore pkg) {
switch (pkg.getAction()) {
case CREATE_UPDATE:
connection.getPlayer().getScoreboardManager().getObjective(pkg.getItemName()).addScore(new ScoreboardScore(pkg.getItemName(), pkg.getScoreName(), pkg.getScoreValue()));
break;
case REMOVE:
connection.getPlayer().getScoreboardManager().getObjective(pkg.getItemName()).removeScore(pkg.getItemName());
break;
}
}
public void handle(PacketScoreboardDisplayScoreboard pkg) {
//ToDo
}
public void handle(PacketScoreboardTeams pkg) {
switch (pkg.getAction()) {
case CREATE:
connection.getPlayer().getScoreboardManager().addTeam(new ScoreboardTeam(pkg.getName(), pkg.getDisplayName(), pkg.getPrefix(), pkg.getSuffix(), pkg.getFriendlyFire(), pkg.getPlayerNames()));
break;
case INFORMATION_UPDATE:
connection.getPlayer().getScoreboardManager().getTeam(pkg.getName()).updateInformation(pkg.getDisplayName(), pkg.getPrefix(), pkg.getSuffix(), pkg.getFriendlyFire());
break;
case REMOVE:
connection.getPlayer().getScoreboardManager().removeTeam(pkg.getName());
break;
case PLAYER_ADD:
connection.getPlayer().getScoreboardManager().getTeam(pkg.getName()).addPlayers(Arrays.asList(pkg.getPlayerNames()));
break;
case PLAYER_REMOVE:
connection.getPlayer().getScoreboardManager().getTeam(pkg.getName()).removePlayers(Arrays.asList(pkg.getPlayerNames()));
break;
}
}
} }

View File

@ -107,6 +107,9 @@ public abstract class Protocol implements ProtocolInterface {
packetClassMapping.put(Packets.Clientbound.PLAY_SPAWN_PAINTING, PacketSpawnPainting.class); packetClassMapping.put(Packets.Clientbound.PLAY_SPAWN_PAINTING, PacketSpawnPainting.class);
packetClassMapping.put(Packets.Clientbound.PLAY_PARTICLE, PacketParticle.class); packetClassMapping.put(Packets.Clientbound.PLAY_PARTICLE, PacketParticle.class);
packetClassMapping.put(Packets.Clientbound.PLAY_EFFECT, PacketEffect.class); packetClassMapping.put(Packets.Clientbound.PLAY_EFFECT, PacketEffect.class);
packetClassMapping.put(Packets.Clientbound.PLAY_SCOREBOARD_OBJECTIVE, PacketScoreboardObjective.class);
packetClassMapping.put(Packets.Clientbound.PLAY_UPDATE_SCORE, PacketScoreboardUpdateScore.class);
packetClassMapping.put(Packets.Clientbound.PLAY_TEAMS, PacketScoreboardTeams.class);
} }
public static ProtocolVersion getLowestVersionSupported() { public static ProtocolVersion getLowestVersionSupported() {