mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 10:25:06 -04:00
refactor tab list
This commit is contained in:
parent
4c1a9ba223
commit
804a49f319
@ -19,7 +19,7 @@ public enum Gamemodes {
|
||||
ADVENTURE,
|
||||
SPECTATOR;
|
||||
|
||||
private static final Gamemodes[] GAME_MODES = values();
|
||||
public static final Gamemodes[] GAME_MODES = values();
|
||||
|
||||
public static Gamemodes byId(int id) {
|
||||
return GAME_MODES[id];
|
||||
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2021 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.data.player.tab;
|
||||
|
||||
import de.bixilon.minosoft.data.Gamemodes;
|
||||
import de.bixilon.minosoft.data.player.PlayerProperties;
|
||||
import de.bixilon.minosoft.data.player.PlayerProperty;
|
||||
import de.bixilon.minosoft.data.text.ChatComponent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
// The holder for the data on <tab>
|
||||
public class PlayerListItem {
|
||||
// required fields
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
private final boolean legacy;
|
||||
int ping;
|
||||
// optional fields
|
||||
Gamemodes gamemode;
|
||||
ChatComponent displayName;
|
||||
HashMap<PlayerProperties, PlayerProperty> properties;
|
||||
|
||||
/**
|
||||
* Legacy (1.7.10)
|
||||
*
|
||||
* @param name Player name
|
||||
* @param ping Ping in milliseconds
|
||||
*/
|
||||
public PlayerListItem(UUID uuid, String name, int ping) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.ping = ping;
|
||||
this.legacy = true;
|
||||
}
|
||||
|
||||
public PlayerListItem(UUID uuid, String name, int ping, Gamemodes gamemode, ChatComponent displayName, HashMap<PlayerProperties, PlayerProperty> properties) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.ping = ping;
|
||||
this.gamemode = gamemode;
|
||||
this.displayName = displayName;
|
||||
this.properties = properties;
|
||||
this.legacy = false;
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public int getPing() {
|
||||
return this.ping;
|
||||
}
|
||||
|
||||
public void setPing(int ping) {
|
||||
this.ping = ping;
|
||||
}
|
||||
|
||||
public Gamemodes getGamemode() {
|
||||
return this.gamemode;
|
||||
}
|
||||
|
||||
public void setGamemode(Gamemodes gamemode) {
|
||||
this.gamemode = gamemode;
|
||||
}
|
||||
|
||||
public ChatComponent getDisplayName() {
|
||||
return (hasDisplayName() ? this.displayName : ChatComponent.valueOf(this.name));
|
||||
}
|
||||
|
||||
public void setDisplayName(ChatComponent displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public boolean hasDisplayName() {
|
||||
return this.displayName != null;
|
||||
}
|
||||
|
||||
public HashMap<PlayerProperties, PlayerProperty> getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
public PlayerProperty getProperty(PlayerProperties property) {
|
||||
return this.properties.get(property);
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return this.legacy;
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2021 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.data.player.tab;
|
||||
|
||||
import de.bixilon.minosoft.data.Gamemodes;
|
||||
import de.bixilon.minosoft.data.player.PlayerProperties;
|
||||
import de.bixilon.minosoft.data.player.PlayerProperty;
|
||||
import de.bixilon.minosoft.data.text.ChatComponent;
|
||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketPlayerListItem;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
// The holder for the data on <tab>
|
||||
public class PlayerListItemBulk {
|
||||
// required fieldsp
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
private final boolean legacy;
|
||||
private final int ping;
|
||||
// optional fields
|
||||
private final Gamemodes gamemode;
|
||||
private final ChatComponent displayName;
|
||||
private final HashMap<PlayerProperties, PlayerProperty> properties;
|
||||
private final PacketPlayerListItem.PlayerListItemActions action;
|
||||
|
||||
public PlayerListItemBulk(String name, int ping, PacketPlayerListItem.PlayerListItemActions action) {
|
||||
this.action = action;
|
||||
this.uuid = UUID.randomUUID();
|
||||
this.name = name;
|
||||
this.ping = ping;
|
||||
this.gamemode = null;
|
||||
this.displayName = null;
|
||||
this.properties = null;
|
||||
this.legacy = true;
|
||||
}
|
||||
|
||||
public PlayerListItemBulk(UUID uuid, String name, int ping, Gamemodes gamemode, ChatComponent displayName, HashMap<PlayerProperties, PlayerProperty> properties, PacketPlayerListItem.PlayerListItemActions action) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.ping = ping;
|
||||
this.gamemode = gamemode;
|
||||
this.displayName = displayName;
|
||||
this.properties = properties;
|
||||
this.action = action;
|
||||
this.legacy = false;
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public int getPing() {
|
||||
return this.ping;
|
||||
}
|
||||
|
||||
public Gamemodes getGamemode() {
|
||||
return this.gamemode;
|
||||
}
|
||||
|
||||
public ChatComponent getDisplayName() {
|
||||
return (hasDisplayName() ? this.displayName : ChatComponent.valueOf(this.name));
|
||||
}
|
||||
|
||||
public boolean hasDisplayName() {
|
||||
return this.displayName != null;
|
||||
}
|
||||
|
||||
public HashMap<PlayerProperties, PlayerProperty> getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
public PlayerProperty getProperty(PlayerProperties property) {
|
||||
return this.properties.get(property);
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return this.legacy;
|
||||
}
|
||||
|
||||
public PacketPlayerListItem.PlayerListItemActions getAction() {
|
||||
return this.action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("uuid=%s, action=%s, name=%s, gamemode=%s, ping=%d, displayName=%s", getUUID(), getAction(), getName(), getGamemode(), getPing(), getDisplayName());
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import java.util.*
|
||||
|
||||
class TabList {
|
||||
val playerList: MutableMap<UUID, PlayerListItem> = mutableMapOf()
|
||||
val tabListItems: MutableMap<UUID, TabListItem> = mutableMapOf()
|
||||
var header = ChatComponent.valueOf("")!!
|
||||
var footer = ChatComponent.valueOf("")!!
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2021 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.data.player.tab
|
||||
|
||||
import de.bixilon.minosoft.data.Gamemodes
|
||||
import de.bixilon.minosoft.data.player.PlayerProperties
|
||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
|
||||
data class TabListItem(
|
||||
var name: String,
|
||||
var ping: Int = -1,
|
||||
var gamemode: Gamemodes = Gamemodes.SURVIVAL,
|
||||
var displayName: ChatComponent = ChatComponent.valueOf(name),
|
||||
var properties: Map<PlayerProperties, PlayerProperty> = mutableMapOf(),
|
||||
) {
|
||||
|
||||
fun merge(data: TabListItemData) {
|
||||
data.name?.let { name = it }
|
||||
data.ping?.let { ping = it }
|
||||
data.gamemode?.let { gamemode = it }
|
||||
data.hasDisplayName?.let {
|
||||
displayName = if (it) {
|
||||
data.displayName!!
|
||||
} else {
|
||||
ChatComponent.valueOf(name)
|
||||
}
|
||||
}
|
||||
data.properties?.let { properties = it }
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2021 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.data.player.tab
|
||||
|
||||
import de.bixilon.minosoft.data.Gamemodes
|
||||
import de.bixilon.minosoft.data.player.PlayerProperties
|
||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
|
||||
data class TabListItemData(
|
||||
val name: String? = null,
|
||||
var ping: Int? = null,
|
||||
var gamemode: Gamemodes? = null,
|
||||
var hasDisplayName: Boolean? = null,
|
||||
var displayName: ChatComponent? = null,
|
||||
val properties: Map<PlayerProperties, PlayerProperty>? = null,
|
||||
var remove: Boolean = false, // used for legacy tab list
|
||||
)
|
@ -13,26 +13,27 @@
|
||||
|
||||
package de.bixilon.minosoft.modding.event.events;
|
||||
|
||||
import de.bixilon.minosoft.data.player.tab.PlayerListItemBulk;
|
||||
import de.bixilon.minosoft.data.player.tab.TabListItemData;
|
||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection;
|
||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketPlayerListItem;
|
||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketTabListItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerListItemChangeEvent extends CancelableEvent {
|
||||
private final ArrayList<PlayerListItemBulk> playerList;
|
||||
private final Map<UUID, TabListItemData> items;
|
||||
|
||||
public PlayerListItemChangeEvent(PlayConnection connection, ArrayList<PlayerListItemBulk> playerList) {
|
||||
public PlayerListItemChangeEvent(PlayConnection connection, Map<UUID, TabListItemData> items) {
|
||||
super(connection);
|
||||
this.playerList = playerList;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public PlayerListItemChangeEvent(PlayConnection connection, PacketPlayerListItem pkg) {
|
||||
public PlayerListItemChangeEvent(PlayConnection connection, PacketTabListItem pkg) {
|
||||
super(connection);
|
||||
this.playerList = pkg.getPlayerList();
|
||||
this.items = pkg.getItems();
|
||||
}
|
||||
|
||||
public ArrayList<PlayerListItemBulk> getPlayerList() {
|
||||
return this.playerList;
|
||||
public Map<UUID, TabListItemData> getItems() {
|
||||
return this.items;
|
||||
}
|
||||
}
|
||||
|
@ -1,151 +0,0 @@
|
||||
/*
|
||||
* 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.data.Gamemodes;
|
||||
import de.bixilon.minosoft.data.player.PlayerProperties;
|
||||
import de.bixilon.minosoft.data.player.PlayerProperty;
|
||||
import de.bixilon.minosoft.data.player.tab.PlayerListItem;
|
||||
import de.bixilon.minosoft.data.player.tab.PlayerListItemBulk;
|
||||
import de.bixilon.minosoft.data.text.ChatComponent;
|
||||
import de.bixilon.minosoft.modding.event.events.PlayerListItemChangeEvent;
|
||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection;
|
||||
import de.bixilon.minosoft.protocol.packets.clientbound.PlayClientboundPacket;
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer;
|
||||
import de.bixilon.minosoft.util.logging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_14W04A;
|
||||
import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_14W19A;
|
||||
|
||||
public class PacketPlayerListItem extends PlayClientboundPacket {
|
||||
private final ArrayList<PlayerListItemBulk> playerList = new ArrayList<>();
|
||||
|
||||
|
||||
public PacketPlayerListItem(PlayInByteBuffer buffer) {
|
||||
if (buffer.getVersionId() < V_14W19A) { // ToDo: 19?
|
||||
String name = buffer.readString();
|
||||
int ping;
|
||||
if (buffer.getVersionId() < V_14W04A) {
|
||||
ping = buffer.readUnsignedShort();
|
||||
} else {
|
||||
ping = buffer.readVarInt();
|
||||
}
|
||||
PlayerListItemActions action = (buffer.readBoolean() ? PlayerListItemActions.UPDATE_LATENCY : PlayerListItemActions.REMOVE_PLAYER);
|
||||
this.playerList.add(new PlayerListItemBulk(name, ping, action));
|
||||
return;
|
||||
}
|
||||
PlayerListItemActions action = PlayerListItemActions.byId(buffer.readVarInt());
|
||||
int count = buffer.readVarInt();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UUID uuid = buffer.readUUID();
|
||||
PlayerListItemBulk listItemBulk;
|
||||
// UUID uuid, String name, int ping, GameMode gamemode, TextComponent displayName, HashMap< PlayerProperties, PlayerProperty > properties, PacketPlayerInfo.PlayerInfoAction action) {
|
||||
switch (action) {
|
||||
case ADD -> {
|
||||
String name = buffer.readString();
|
||||
int propertiesCount = buffer.readVarInt();
|
||||
HashMap<PlayerProperties, PlayerProperty> playerProperties = new HashMap<>();
|
||||
for (int p = 0; p < propertiesCount; p++) {
|
||||
PlayerProperty property = new PlayerProperty(PlayerProperties.byName(buffer.readString()), buffer.readString(), (buffer.readBoolean() ? buffer.readString() : null));
|
||||
playerProperties.put(property.getProperty(), property);
|
||||
}
|
||||
Gamemodes gamemode = Gamemodes.byId(buffer.readVarInt());
|
||||
int ping = buffer.readVarInt();
|
||||
ChatComponent displayName = (buffer.readBoolean() ? buffer.readChatComponent() : null);
|
||||
listItemBulk = new PlayerListItemBulk(uuid, name, ping, gamemode, displayName, playerProperties, action);
|
||||
}
|
||||
case UPDATE_GAMEMODE -> listItemBulk = new PlayerListItemBulk(uuid, null, 0, Gamemodes.byId(buffer.readVarInt()), null, null, action);
|
||||
case UPDATE_LATENCY -> listItemBulk = new PlayerListItemBulk(uuid, null, buffer.readVarInt(), null, null, null, action);
|
||||
case UPDATE_DISPLAY_NAME -> listItemBulk = new PlayerListItemBulk(uuid, null, 0, null, (buffer.readBoolean() ? buffer.readChatComponent() : null), null, action);
|
||||
case REMOVE_PLAYER -> listItemBulk = new PlayerListItemBulk(uuid, null, 0, null, null, null, action);
|
||||
default -> listItemBulk = null;
|
||||
}
|
||||
this.playerList.add(listItemBulk);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(PlayConnection connection) {
|
||||
if (connection.fireEvent(new PlayerListItemChangeEvent(connection, this))) {
|
||||
return;
|
||||
}
|
||||
for (PlayerListItemBulk bulk : getPlayerList()) {
|
||||
PlayerListItem item = connection.getTabList().getPlayerList().get(bulk.getUUID());
|
||||
if (bulk.getAction() != PlayerListItemActions.ADD && item == null && !bulk.isLegacy()) {
|
||||
// Aaaaah. Fuck this shit. The server sends us bullshit!
|
||||
continue;
|
||||
}
|
||||
switch (bulk.getAction()) {
|
||||
case ADD -> connection.getTabList().getPlayerList().put(bulk.getUUID(), new PlayerListItem(bulk.getUUID(), bulk.getName(), bulk.getPing(), bulk.getGamemode(), bulk.getDisplayName(), bulk.getProperties()));
|
||||
case UPDATE_LATENCY -> {
|
||||
if (bulk.isLegacy()) {
|
||||
// add or update
|
||||
if (item == null) {
|
||||
// create
|
||||
UUID uuid = UUID.randomUUID();
|
||||
connection.getTabList().getPlayerList().put(uuid, new PlayerListItem(uuid, bulk.getName(), bulk.getPing()));
|
||||
} else {
|
||||
// update ping
|
||||
item.setPing(bulk.getPing());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
connection.getTabList().getPlayerList().get(bulk.getUUID()).setPing(bulk.getPing());
|
||||
}
|
||||
case REMOVE_PLAYER -> {
|
||||
if (bulk.isLegacy()) {
|
||||
if (item == null) {
|
||||
// not initialized yet
|
||||
continue;
|
||||
}
|
||||
// ToDo: connection.getTabList().getPlayerList().remove(connection.getTabList().getPlayerList(bulk.getName()).getUUID());
|
||||
continue;
|
||||
}
|
||||
connection.getTabList().getPlayerList().remove(bulk.getUUID());
|
||||
}
|
||||
case UPDATE_GAMEMODE -> item.setGamemode(bulk.getGamemode());
|
||||
case UPDATE_DISPLAY_NAME -> item.setDisplayName(bulk.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log() {
|
||||
for (PlayerListItemBulk property : this.playerList) {
|
||||
Log.protocol(String.format("[IN] Received player list item bulk (%s)", property));
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<PlayerListItemBulk> getPlayerList() {
|
||||
return this.playerList;
|
||||
}
|
||||
|
||||
public enum PlayerListItemActions {
|
||||
ADD,
|
||||
UPDATE_GAMEMODE,
|
||||
UPDATE_LATENCY,
|
||||
UPDATE_DISPLAY_NAME,
|
||||
REMOVE_PLAYER;
|
||||
|
||||
private static final PlayerListItemActions[] PLAYER_LIST_ITEM_ACTIONS = values();
|
||||
|
||||
public static PlayerListItemActions byId(int id) {
|
||||
return PLAYER_LIST_ITEM_ACTIONS[id];
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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.data.Gamemodes
|
||||
import de.bixilon.minosoft.data.player.PlayerProperties
|
||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
||||
import de.bixilon.minosoft.data.player.tab.TabListItem
|
||||
import de.bixilon.minosoft.data.player.tab.TabListItemData
|
||||
import de.bixilon.minosoft.modding.event.events.PlayerListItemChangeEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.clientbound.PlayClientboundPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.*
|
||||
|
||||
|
||||
class PacketTabListItem(buffer: PlayInByteBuffer) : PlayClientboundPacket() {
|
||||
val items: MutableMap<UUID, TabListItemData> = mutableMapOf()
|
||||
|
||||
init {
|
||||
if (buffer.versionId < ProtocolVersions.V_14W19A) { // ToDo: 19?
|
||||
val name: String = buffer.readString()
|
||||
val ping: Int = if (buffer.versionId < ProtocolVersions.V_14W04A) {
|
||||
buffer.readUnsignedShort()
|
||||
} else {
|
||||
buffer.readVarInt()
|
||||
}
|
||||
val action = if (buffer.readBoolean()) {
|
||||
PlayerListItemActions.UPDATE_LATENCY
|
||||
} else {
|
||||
PlayerListItemActions.REMOVE_PLAYER
|
||||
}
|
||||
val uuid: UUID = UUID.nameUUIDFromBytes(name.toByteArray(StandardCharsets.UTF_8))
|
||||
val item = TabListItemData(name = name, ping = ping, remove = action == PlayerListItemActions.REMOVE_PLAYER)
|
||||
items[uuid] = item
|
||||
} else {
|
||||
val action = PlayerListItemActions.VALUES[buffer.readVarInt()]
|
||||
val count: Int = buffer.readVarInt()
|
||||
for (i in 0 until count) {
|
||||
val uuid: UUID = buffer.readUUID()
|
||||
val data: TabListItemData
|
||||
when (action) {
|
||||
PlayerListItemActions.ADD -> {
|
||||
val name = buffer.readString()
|
||||
val playerProperties: MutableMap<PlayerProperties, PlayerProperty> = mutableMapOf()
|
||||
for (index in 0 until buffer.readVarInt()) {
|
||||
val property = PlayerProperty(
|
||||
PlayerProperties.byName(buffer.readString()),
|
||||
buffer.readString(),
|
||||
if (buffer.readBoolean()) {
|
||||
buffer.readString()
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
playerProperties[property.property] = property
|
||||
}
|
||||
val gamemode = Gamemodes.GAME_MODES[buffer.readVarInt()]
|
||||
val ping = buffer.readVarInt()
|
||||
val hasDisplayName = buffer.readBoolean()
|
||||
val displayName = if (hasDisplayName) {
|
||||
buffer.readChatComponent()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
data = TabListItemData(
|
||||
name = name,
|
||||
properties = playerProperties,
|
||||
gamemode = gamemode,
|
||||
ping = ping,
|
||||
hasDisplayName = hasDisplayName,
|
||||
displayName = displayName,
|
||||
)
|
||||
}
|
||||
PlayerListItemActions.UPDATE_GAMEMODE -> {
|
||||
data = TabListItemData(gamemode = Gamemodes.GAME_MODES[buffer.readVarInt()])
|
||||
}
|
||||
PlayerListItemActions.UPDATE_LATENCY -> {
|
||||
data = TabListItemData(ping = buffer.readVarInt())
|
||||
}
|
||||
PlayerListItemActions.UPDATE_DISPLAY_NAME -> {
|
||||
val hasDisplayName = buffer.readBoolean()
|
||||
val displayName = if (hasDisplayName) {
|
||||
buffer.readChatComponent()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
data = TabListItemData(
|
||||
hasDisplayName = hasDisplayName,
|
||||
displayName = displayName,
|
||||
)
|
||||
}
|
||||
PlayerListItemActions.REMOVE_PLAYER -> {
|
||||
data = TabListItemData(remove = true)
|
||||
}
|
||||
}
|
||||
items[uuid] = data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(connection: PlayConnection) {
|
||||
if (connection.fireEvent(PlayerListItemChangeEvent(connection, this))) {
|
||||
return
|
||||
}
|
||||
for ((uuid, data) in items) {
|
||||
// legacy
|
||||
if (connection.version.versionId < ProtocolVersions.V_14W19A) { // ToDo: 19?
|
||||
val item: TabListItem = if (data.remove) {
|
||||
// add or remove
|
||||
connection.tabList.tabListItems[uuid]?.let {
|
||||
connection.tabList.tabListItems.remove(uuid)
|
||||
it
|
||||
} ?: let {
|
||||
// add
|
||||
val itemToAdd = TabListItem(name = data.name!!)
|
||||
connection.tabList.tabListItems[uuid] = itemToAdd
|
||||
itemToAdd
|
||||
}
|
||||
} else {
|
||||
connection.tabList.tabListItems[uuid]!!
|
||||
}
|
||||
|
||||
item.merge(data)
|
||||
continue
|
||||
}
|
||||
if (data.remove) {
|
||||
connection.tabList.tabListItems.remove(uuid)
|
||||
continue
|
||||
}
|
||||
val tabListItem = connection.tabList.tabListItems[uuid] ?: run {
|
||||
if (data.name == null) {
|
||||
// item not yet created
|
||||
return@run null
|
||||
}
|
||||
val item = TabListItem(name = data.name)
|
||||
connection.tabList.tabListItems[uuid] = item
|
||||
item
|
||||
} ?: continue
|
||||
|
||||
tabListItem.merge(data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun log() {
|
||||
Log.protocol("[IN] Received tab list items: $items")
|
||||
}
|
||||
|
||||
|
||||
enum class PlayerListItemActions {
|
||||
ADD,
|
||||
UPDATE_GAMEMODE,
|
||||
UPDATE_LATENCY,
|
||||
UPDATE_DISPLAY_NAME,
|
||||
REMOVE_PLAYER,
|
||||
;
|
||||
|
||||
companion object {
|
||||
val VALUES = values()
|
||||
}
|
||||
}
|
||||
}
|
@ -193,7 +193,7 @@ class PacketTypes {
|
||||
PLAY_CRAFT_RECIPE_RESPONSE({ PacketCraftRecipeResponse(it) }),
|
||||
PLAY_PLAYER_ABILITIES({ PacketPlayerAbilitiesReceiving(it) }),
|
||||
PLAY_COMBAT_EVENT({ CombatEventPacketFactory.createPacket(it) }),
|
||||
PLAY_PLAYER_LIST_ITEM({ PacketPlayerListItem(it) }),
|
||||
PLAY_TAB_LIST_ITEM({ PacketTabListItem(it) }),
|
||||
PLAY_FACE_PLAYER({ PacketFacePlayer(it) }),
|
||||
PLAY_PLAYER_POSITION_AND_ROTATION({ PacketPlayerPositionAndRotation(it) }),
|
||||
PLAY_UNLOCK_RECIPES({ PacketUnlockRecipes(it) }),
|
||||
|
@ -17,7 +17,7 @@ import com.github.freva.asciitable.AsciiTable;
|
||||
import de.bixilon.minosoft.data.commands.CommandLiteralNode;
|
||||
import de.bixilon.minosoft.data.commands.CommandNode;
|
||||
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity;
|
||||
import de.bixilon.minosoft.data.player.tab.PlayerListItem;
|
||||
import de.bixilon.minosoft.data.player.tab.TabListItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@ -31,7 +31,7 @@ public class CommandTabList extends Command {
|
||||
new CommandLiteralNode("list", (connection, stack) -> {
|
||||
print(connection.getTabList().getHeader().getANSIColoredMessage());
|
||||
|
||||
int entries = connection.getTabList().getPlayerList().size();
|
||||
int entries = connection.getTabList().getTabListItems().size();
|
||||
int columns = (entries / 20) + 1;
|
||||
if (columns > 4) {
|
||||
columns = 4;
|
||||
@ -43,7 +43,7 @@ public class CommandTabList extends Command {
|
||||
|
||||
ArrayList<Object[]> tableData = new ArrayList<>();
|
||||
|
||||
Iterator<PlayerListItem> playerListItems = connection.getTabList().getPlayerList().values().iterator();
|
||||
Iterator<TabListItem> playerListItems = connection.getTabList().getTabListItems().values().iterator();
|
||||
for (int row = 0; row < rows; row++) {
|
||||
ArrayList<Object> current = new ArrayList<>();
|
||||
for (int column = 0; column < columns; column++) {
|
||||
@ -68,8 +68,8 @@ public class CommandTabList extends Command {
|
||||
|
||||
ArrayList<Object[]> tableData = new ArrayList<>();
|
||||
|
||||
for (var entry : connection.getTabList().getPlayerList().entrySet()) {
|
||||
PlayerEntity playerEntity = (PlayerEntity) connection.getWorld().getEntity(entry.getValue().getUUID());
|
||||
for (var entry : connection.getTabList().getTabListItems().entrySet()) {
|
||||
PlayerEntity playerEntity = (PlayerEntity) connection.getWorld().getEntity(entry.getKey());
|
||||
Integer entityId = playerEntity != null ? connection.getWorld().getEntityIdMap().inverse().get(playerEntity) : null;
|
||||
tableData.add(new Object[]{entry.getKey(), entityId, entry.getValue().getName(), entry.getValue().getDisplayName(), entry.getValue().getGamemode(), entry.getValue().getPing() + "ms"});
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user