mirror of
https://github.com/GeyserMC/Geyser.git
synced 2026-01-04 15:31:36 +00:00
Scoreboard rework (#4947)
* Initial version of the great scoreboard rework * Fixed some issues and added some initial tests * Addressed review * Added CubeCraft's scoreboard as a test, and fixed a discovered bug * Removed var usage for primitives and String, removed star imports
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockAndAddPlayerEntity;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetPlayerTeamTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.CollisionRule;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.NameTagVisibility;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetPlayerTeamPacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class NameVisibilityScoreboardTest {
|
||||
@Test
|
||||
void playerVisibilityNever() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team1",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.NEVER,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_RED,
|
||||
new String[]{"player1"}
|
||||
)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void playerVisibilityHideForOtherTeam() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team1",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.HIDE_FOR_OTHER_TEAMS,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_RED,
|
||||
new String[]{"player1"}
|
||||
)
|
||||
);
|
||||
// only hidden if session player (Tim203) is in a team as well
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// create another team and add Tim203 to it
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team2",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.NEVER,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_RED,
|
||||
new String[]{"Tim203"}
|
||||
)
|
||||
);
|
||||
// Tim203 is now in another team, so it should be hidden
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// add Tim203 to same team as player1, score should be visible again
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("team1", TeamAction.ADD_PLAYER, new String[]{"Tim203"})
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void playerVisibilityHideForOwnTeam() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team1",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.HIDE_FOR_OWN_TEAM,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_RED,
|
||||
new String[]{"player1"}
|
||||
)
|
||||
);
|
||||
// Tim203 is not in a team (let alone the same team), so should be visible
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// Tim203 is now in the same team as player1, so should be hidden
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("team1", TeamAction.ADD_PLAYER, new String[]{"Tim203"})
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// create another team and add Tim203 to there, score should be visible again
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team2",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.NEVER,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_RED,
|
||||
new String[]{"Tim203"}
|
||||
)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void playerVisibilityAlways() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team1",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_RED,
|
||||
new String[]{"player1"}
|
||||
)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// adding self to another team shouldn't make a difference
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team2",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_RED,
|
||||
new String[]{"Tim203"}
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// adding self to player1 team shouldn't matter
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("team1", TeamAction.ADD_PLAYER, new String[]{"Tim203"})
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.belowname;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockAndAddPlayerEntity;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetDisplayObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetObjectiveTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ObjectiveAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetObjectivePacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class BasicBelownameScoreboardTests {
|
||||
@Test
|
||||
void displayWithNoPlayersAndRemove() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective")
|
||||
);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "")
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void displayColorWithOnePlayer() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective", NamedTextColor.BLUE),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "0 §r§9objective");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void displayWithOnePlayerAndRemove() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "0 §robjective");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void overrideAndRemove() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective1",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective1"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective2",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective2"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective2")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "0 §robjective2");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective1")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "0 §robjective1");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.playerlist;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ScoreInfo;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RemoveObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetDisplayObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetScorePacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetDisplayObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetScoreTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ObjectiveAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/*
|
||||
Identical to sidebar
|
||||
*/
|
||||
public class BasicPlayerlistScoreboardTests {
|
||||
@Test
|
||||
void display() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void displayNameColors() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective", Style.style(NamedTextColor.AQUA, TextDecoration.BOLD)),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("§b§lobjective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void overrideWithOneScore() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective1",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective1"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective2",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective2"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("Tim203", "objective1", 1));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("Tim203", "objective2", 2));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective2")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective2");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
// session player name is Tim203
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, ScoreInfo.ScorerType.PLAYER, 1)));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective1")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("2");
|
||||
packet.setDisplayName("objective1");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
// session player name is Tim203
|
||||
packet.setInfos(List.of(new ScoreInfo(3, "2", 1, ScoreInfo.ScorerType.PLAYER, 1)));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,756 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.server;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockAndAddPlayerEntity;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ScoreInfo;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RemoveObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetDisplayObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetScorePacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetDisplayObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetPlayerTeamTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetScoreTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.CollisionRule;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.NameTagVisibility;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ObjectiveAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetPlayerTeamPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class CubecraftScoreboardTest {
|
||||
@Test
|
||||
void test() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
|
||||
// unused
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("SB_NoName", Component.text("SB_NoName"), Component.empty(), Component.empty(), true, true, NameTagVisibility.NEVER, CollisionRule.NEVER, TeamColor.RESET, new String[0]));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"sidebar",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("sidebar"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "sidebar")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("sidebar");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
|
||||
// Now they're going to create a bunch of teams and add players to those teams in a very inefficient way.
|
||||
// Presumably this is a leftover from an old system, as these don't seem to do anything but hide their nametags.
|
||||
// For which you could just use a single team.
|
||||
|
||||
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", Component.text("2i|1"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.RESET, new String[0]));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", Component.text("2i|1"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.DARK_GRAY));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", Component.text("2i|1"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.DARK_GRAY));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", Component.text("2i|1"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.DARK_GRAY));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", Component.text("2i|1"), Component.empty(), Component.empty(), false, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.DARK_GRAY));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", Component.text("2i|1"), Component.empty(), Component.empty(), false, false, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.DARK_GRAY));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", Component.text("2i|1"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.ALWAYS, TeamColor.DARK_GRAY));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", Component.text("2i|1"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.NEVER, TeamColor.DARK_GRAY));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "A_Player" }));
|
||||
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", Component.text("1y|11"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.RESET, new String[0]));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", Component.text("1y|11"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", Component.text("1y|11"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", Component.text("1y|11"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", Component.text("1y|11"), Component.empty(), Component.empty(), false, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", Component.text("1y|11"), Component.empty(), Component.empty(), false, false, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", Component.text("1y|11"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", Component.text("1y|11"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.NEVER, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", TeamAction.ADD_PLAYER, new String[] { "B_Player" }));
|
||||
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "C_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "D_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1y|11", TeamAction.ADD_PLAYER, new String[] { "E_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "F_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "G_Player" }));
|
||||
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", Component.text("2e|3"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.RESET, new String[0]));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", Component.text("2e|3"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.BLUE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", Component.text("2e|3"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.BLUE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", Component.text("2e|3"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.BLUE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", Component.text("2e|3"), Component.empty(), Component.empty(), false, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.BLUE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", Component.text("2e|3"), Component.empty(), Component.empty(), false, false, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.BLUE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", Component.text("2e|3"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.ALWAYS, TeamColor.BLUE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", Component.text("2e|3"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.NEVER, TeamColor.BLUE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", TeamAction.ADD_PLAYER, new String[] { "H_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "I_Player" }));
|
||||
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", Component.text("22|9"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.RESET, new String[0]));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", Component.text("22|9"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", Component.text("22|9"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", Component.text("22|9"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", Component.text("22|9"), Component.empty(), Component.empty(), false, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", Component.text("22|9"), Component.empty(), Component.empty(), false, false, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", Component.text("22|9"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", Component.text("22|9"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.NEVER, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("22|9", TeamAction.ADD_PLAYER, new String[] { "J_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "K_Player" }));
|
||||
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", Component.text("26|7"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.RESET, new String[0]));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", Component.text("26|7"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", Component.text("26|7"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", Component.text("26|7"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", Component.text("26|7"), Component.empty(), Component.empty(), false, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", Component.text("26|7"), Component.empty(), Component.empty(), false, false, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", Component.text("26|7"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.ALWAYS, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", Component.text("26|7"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.NEVER, TeamColor.AQUA));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("26|7", TeamAction.ADD_PLAYER, new String[] { "L_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2e|3", TeamAction.ADD_PLAYER, new String[] { "M_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "N_Player" }));
|
||||
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", Component.text("1u|13"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.RESET, new String[0]));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", Component.text("1u|13"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", Component.text("1u|13"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", Component.text("1u|13"), Component.empty(), Component.empty(), true, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", Component.text("1u|13"), Component.empty(), Component.empty(), false, true, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", Component.text("1u|13"), Component.empty(), Component.empty(), false, false, NameTagVisibility.ALWAYS, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", Component.text("1u|13"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.ALWAYS, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", Component.text("1u|13"), Component.empty(), Component.empty(), false, false, NameTagVisibility.NEVER, CollisionRule.NEVER, TeamColor.LIGHT_PURPLE));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("1u|13", TeamAction.ADD_PLAYER, new String[] { "O_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "P_Player" }));
|
||||
context.translate(setTeamTranslator, new ClientboundSetPlayerTeamPacket("2i|1", TeamAction.ADD_PLAYER, new String[] { "Q_Player" }));
|
||||
|
||||
assertNoNextPacket(context);
|
||||
|
||||
|
||||
// Now that those teams are created and people added to it, they set the final sidebar name and add the lines to it.
|
||||
// They're also not doing this efficiently, because they don't add the players when the team is created.
|
||||
// Instead, they send an additional packet.
|
||||
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"sidebar",
|
||||
ObjectiveAction.UPDATE,
|
||||
Component.empty()
|
||||
.append(Component.text(
|
||||
"CubeCraft", Style.style(NamedTextColor.WHITE, TextDecoration.BOLD))),
|
||||
ScoreType.INTEGER,
|
||||
null));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("§f§lCubeCraft");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-0",
|
||||
Component.text("SB_l-0"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-0", TeamAction.ADD_PLAYER, new String[] {"§0§0"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-0",
|
||||
Component.text("SB_l-0"),
|
||||
Component.empty().append(Component.text("", Style.style(NamedTextColor.BLACK))),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§0", "sidebar", 10));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 10, "§r§0§0§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-1",
|
||||
Component.text("SB_l-1"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-1", TeamAction.ADD_PLAYER, new String[] {"§0§1"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-1",
|
||||
Component.text("SB_l-1"),
|
||||
Component.empty()
|
||||
.append(Component.textOfChildren(
|
||||
Component.text("User: ", TextColor.color(0x3aa9ff)),
|
||||
Component.text("Tim203", NamedTextColor.WHITE))),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§1", "sidebar", 9));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(2, "0", 9, "§bUser: §r§fTim203§r§0§1§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-2",
|
||||
Component.text("SB_l-2"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-2", TeamAction.ADD_PLAYER, new String[] {"§0§2"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-2",
|
||||
Component.text("SB_l-2"),
|
||||
Component.empty()
|
||||
.append(Component.textOfChildren(
|
||||
Component.text("Rank: ", TextColor.color(0x3aa9ff)),
|
||||
Component.text("\uE1AB ", NamedTextColor.WHITE))),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§2", "sidebar", 8));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(3, "0", 8, "§bRank: §r§f\uE1AB §r§0§2§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-3",
|
||||
Component.text("SB_l-3"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-3", TeamAction.ADD_PLAYER, new String[] {"§0§3"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-3",
|
||||
Component.text("SB_l-3"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§3", "sidebar", 7));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(4, "0", 7, "§r§0§3§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-4",
|
||||
Component.text("SB_l-4"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-4", TeamAction.ADD_PLAYER, new String[] {"§0§4"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-4",
|
||||
Component.text("SB_l-4"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§4", "sidebar", 6));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(5, "0", 6, "§r§0§4§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-5",
|
||||
Component.text("SB_l-5"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-5", TeamAction.ADD_PLAYER, new String[] {"§0§5"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-5",
|
||||
Component.text("SB_l-5"),
|
||||
Component.empty().append(Component.text("", NamedTextColor.DARK_BLUE)),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§5", "sidebar", 5));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(6, "0", 5, "§r§0§5§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-6",
|
||||
Component.text("SB_l-6"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-6", TeamAction.ADD_PLAYER, new String[] {"§0§6"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-6",
|
||||
Component.text("SB_l-6"),
|
||||
Component.empty()
|
||||
.append(Component.textOfChildren(
|
||||
Component.text("Lobby: ", TextColor.color(0x3aa9ff)),
|
||||
Component.text("EU #10", NamedTextColor.WHITE))),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§6", "sidebar", 4));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(7, "0", 4, "§bLobby: §r§fEU #10§r§0§6§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-7",
|
||||
Component.text("SB_l-7"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-7", TeamAction.ADD_PLAYER, new String[] {"§0§7"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-7",
|
||||
Component.text("SB_l-7"),
|
||||
Component.empty()
|
||||
.append(Component.textOfChildren(
|
||||
Component.text("Players: ", TextColor.color(0x3aa9ff)),
|
||||
Component.text("783", NamedTextColor.WHITE))),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§7", "sidebar", 3));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(8, "0", 3, "§bPlayers: §r§f783§r§0§7§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-8",
|
||||
Component.text("SB_l-8"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-8", TeamAction.ADD_PLAYER, new String[] {"§0§8"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-8",
|
||||
Component.text("SB_l-8"),
|
||||
Component.empty().append(Component.text("", NamedTextColor.DARK_GREEN)),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§8", "sidebar", 2));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(9, "0", 2, "§r§0§8§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-9",
|
||||
Component.text("SB_l-9"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-9", TeamAction.ADD_PLAYER, new String[] {"§0§9"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-9",
|
||||
Component.text("SB_l-9"),
|
||||
Component.empty().append(Component.text("24/09/24 (g2208)", TextColor.color(0x777777))),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§9", "sidebar", 1));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(10, "0", 1, "§824/09/24 (g2208)§r§0§9§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-10",
|
||||
Component.text("SB_l-10"),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET,
|
||||
new String[0]));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("SB_l-10", TeamAction.ADD_PLAYER, new String[] {"§0§a"}));
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-10",
|
||||
Component.text("SB_l-10"),
|
||||
Component.empty().append(Component.text("play.cubecraft.net", NamedTextColor.GOLD)),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.ALWAYS,
|
||||
TeamColor.RESET));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§a", "sidebar", 0));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(11, "0", 0, "§6play.cubecraft.net§r§0§a§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
// after this we get a ClientboundPlayerInfoUpdatePacket with the action UPDATE_DISPLAY_NAME,
|
||||
// but that one is only shown in the tablist so we don't have to handle that.
|
||||
// And after that we get each player's ClientboundPlayerInfoUpdatePacket with also a UPDATE_DISPLAY_NAME,
|
||||
// which is also not interesting for us.
|
||||
// CubeCraft seems to use two armor stands per player: 1 for the rank badge and 1 for the player name.
|
||||
// So the only thing we have to verify is that the nametag is hidden
|
||||
|
||||
mockAndAddPlayerEntity(context, "A_Player", 2);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
mockAndAddPlayerEntity(context, "B_Player", 3);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(3);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
mockAndAddPlayerEntity(context, "E_Player", 4);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(4);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
mockAndAddPlayerEntity(context, "H_Player", 5);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(5);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
mockAndAddPlayerEntity(context, "J_Player", 6);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(6);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
mockAndAddPlayerEntity(context, "K_Player", 7);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(7);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
mockAndAddPlayerEntity(context, "L_Player", 8);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(8);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
|
||||
mockAndAddPlayerEntity(context, "O_Player", 9);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(9);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.sidebar;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ScoreInfo;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RemoveObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetDisplayObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetScorePacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetDisplayObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetScoreTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ObjectiveAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/*
|
||||
Identical to playerlist
|
||||
*/
|
||||
public class BasicSidebarScoreboardTests {
|
||||
@Test
|
||||
void displayAndRemove() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void displayNameColors() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective", Style.style(NamedTextColor.AQUA, TextDecoration.BOLD)),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("§b§lobjective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void override() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective1",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective1"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective2",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective2"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("Tim203", "objective1", 1));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("Tim203", "objective2", 2));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective2")
|
||||
);
|
||||
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective2");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, "Tim203")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective1")
|
||||
);
|
||||
|
||||
assertNextPacket(() -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("2");
|
||||
packet.setDisplayName("objective1");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(3, "2", 1, "Tim203")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.sidebar;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ScoreInfo;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetDisplayObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetScorePacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaResetScorePacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetDisplayObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetPlayerTeamTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetScoreTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.CollisionRule;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.NameTagVisibility;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ObjectiveAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundResetScorePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetPlayerTeamPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class OrderAndLimitSidebarScoreboardTests {
|
||||
@Test
|
||||
void aboveDisplayLimit() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
var resetScoreTranslator = new JavaResetScorePacket();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
|
||||
// some are in an odd order to make sure that there is no bias for which score is send first,
|
||||
// and to make sure that the score value also doesn't influence the order
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("a", "objective", 1));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("b", "objective", 2));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("c", "objective", 3));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("d", "objective", 5));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("e", "objective", 4));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("f", "objective", 6));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("g", "objective", 9));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("h", "objective", 8));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("i", "objective", 7));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("p", "objective", 10));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("o", "objective", 11));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("n", "objective", 12));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("m", "objective", 13));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("k", "objective", 14));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("l", "objective", 15));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("j", "objective", 16));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("q", "objective", 17));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(1, "0", 17, "q"),
|
||||
new ScoreInfo(2, "0", 16, "j"),
|
||||
new ScoreInfo(3, "0", 15, "l"),
|
||||
new ScoreInfo(4, "0", 14, "k"),
|
||||
new ScoreInfo(5, "0", 13, "m"),
|
||||
new ScoreInfo(6, "0", 12, "n"),
|
||||
new ScoreInfo(7, "0", 11, "o"),
|
||||
new ScoreInfo(8, "0", 10, "p"),
|
||||
new ScoreInfo(9, "0", 9, "g"),
|
||||
new ScoreInfo(10, "0", 8, "h"),
|
||||
new ScoreInfo(11, "0", 7, "i"),
|
||||
new ScoreInfo(12, "0", 6, "f"),
|
||||
new ScoreInfo(13, "0", 5, "d"),
|
||||
new ScoreInfo(14, "0", 4, "e"),
|
||||
new ScoreInfo(15, "0", 3, "c")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// remove a score
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("m", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(5, "0", 13, "m")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(16, "0", 2, "b")));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// add a score
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("aa", "objective", 13)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(16, "0", 2, "b")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(17, "0", 13, "aa")));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// add score with same score value (after)
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("ga", "objective", 9)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(15, "0", 3, "c"),
|
||||
new ScoreInfo(9, "0", 9, "§0§rg")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(9, "0", 9, "§0§rg"),
|
||||
new ScoreInfo(18, "0", 9, "§1§rga")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// add another score with same score value (before all)
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("ag", "objective", 9)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(14, "0", 4, "e"),
|
||||
new ScoreInfo(9, "0", 9, "§1§rg"),
|
||||
new ScoreInfo(18, "0", 9, "§2§rga")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(19, "0", 9, "§0§rag"),
|
||||
new ScoreInfo(9, "0", 9, "§1§rg"),
|
||||
new ScoreInfo(18, "0", 9, "§2§rga")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// remove score with same value
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("g", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(9, "0", 9, "§1§rg"),
|
||||
new ScoreInfo(18, "0", 9, "§1§rga")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(18, "0", 9, "§1§rga"),
|
||||
new ScoreInfo(20, "0", 4, "e")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// remove the other score with the same value
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("ga", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(18, "0", 9, "§1§rga"),
|
||||
new ScoreInfo(19, "0", 9, "ag")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(19, "0", 9, "ag"),
|
||||
new ScoreInfo(21, "0", 3, "c")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void aboveDisplayLimitWithTeam() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
var resetScoreTranslator = new JavaResetScorePacket();
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
|
||||
// some are in an odd order to make sure that there is no bias for which score is send first,
|
||||
// and to make sure that the score value also doesn't influence the order
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("a", "objective", 1));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("b", "objective", 2));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("c", "objective", 3));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("d", "objective", 5));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("e", "objective", 4));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("f", "objective", 6));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("g", "objective", 9));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("h", "objective", 8));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("i", "objective", 7));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("p", "objective", 10));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("o", "objective", 11));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("n", "objective", 12));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("m", "objective", 13));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("k", "objective", 14));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("l", "objective", 15));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("j", "objective", 16));
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("q", "objective", 17));
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team1",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_RED,
|
||||
new String[]{ "f", "o" }
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(1, "0", 17, "q"),
|
||||
new ScoreInfo(2, "0", 16, "j"),
|
||||
new ScoreInfo(3, "0", 15, "l"),
|
||||
new ScoreInfo(4, "0", 14, "k"),
|
||||
new ScoreInfo(5, "0", 13, "m"),
|
||||
new ScoreInfo(6, "0", 12, "n"),
|
||||
new ScoreInfo(7, "0", 11, "§4prefix§r§4o§r§4suffix"),
|
||||
new ScoreInfo(8, "0", 10, "p"),
|
||||
new ScoreInfo(9, "0", 9, "g"),
|
||||
new ScoreInfo(10, "0", 8, "h"),
|
||||
new ScoreInfo(11, "0", 7, "i"),
|
||||
new ScoreInfo(12, "0", 6, "§4prefix§r§4f§r§4suffix"),
|
||||
new ScoreInfo(13, "0", 5, "d"),
|
||||
new ScoreInfo(14, "0", 4, "e"),
|
||||
new ScoreInfo(15, "0", 3, "c")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// remove a score
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("m", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(5, "0", 13, "m")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(16, "0", 2, "b")));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// add a score
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("aa", "objective", 13)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(16, "0", 2, "b")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(17, "0", 13, "aa")));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// add some teams for the upcoming score adds
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team2",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_AQUA,
|
||||
new String[]{ "oa" }
|
||||
)
|
||||
);
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"team3",
|
||||
Component.text("displayName"),
|
||||
Component.text("prefix"),
|
||||
Component.text("suffix"),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.ALWAYS,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.DARK_PURPLE,
|
||||
new String[]{ "ao" }
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// add a score that on Java should be after 'o', but would be before on Bedrock without manual order
|
||||
// due to the team color
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("oa", "objective", 11)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(15, "0", 3, "c"),
|
||||
new ScoreInfo(7, "0", 11, "§0§r§4prefix§r§4o§r§4suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(7, "0", 11, "§0§r§4prefix§r§4o§r§4suffix"),
|
||||
new ScoreInfo(18, "0", 11, "§1§r§3prefix§r§3oa§r§3suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// add a score that on Java should be before 'o', but would be after on Bedrock without manual order
|
||||
// due to the team color
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("ao", "objective", 11)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(14, "0", 4, "e"),
|
||||
new ScoreInfo(7, "0", 11, "§1§r§4prefix§r§4o§r§4suffix"),
|
||||
new ScoreInfo(18, "0", 11, "§2§r§3prefix§r§3oa§r§3suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(19, "0", 11, "§0§r§5prefix§r§5ao§r§5suffix"),
|
||||
new ScoreInfo(7, "0", 11, "§1§r§4prefix§r§4o§r§4suffix"),
|
||||
new ScoreInfo(18, "0", 11, "§2§r§3prefix§r§3oa§r§3suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// remove original 'o' score
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("o", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(7, "0", 11, "§1§r§4prefix§r§4o§r§4suffix"),
|
||||
new ScoreInfo(18, "0", 11, "§1§r§3prefix§r§3oa§r§3suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(18, "0", 11, "§1§r§3prefix§r§3oa§r§3suffix"),
|
||||
new ScoreInfo(20, "0", 4, "e")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
|
||||
// remove the other score with the same value as 'o'
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("oa", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(18, "0", 11, "§1§r§3prefix§r§3oa§r§3suffix"),
|
||||
new ScoreInfo(19, "0", 11, "§5prefix§r§5ao§r§5suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
new ScoreInfo(19, "0", 11, "§5prefix§r§5ao§r§5suffix"),
|
||||
new ScoreInfo(21, "0", 3, "c")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.sidebar;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ScoreInfo;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetDisplayObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetScorePacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetDisplayObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetScoreTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ObjectiveAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetObjectivePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetScorePacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class VanillaSidebarScoreboardTests {
|
||||
@Test
|
||||
void displayAndAddScore() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("owner", "objective", 1));
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void displayAndChangeScoreValue() {
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("owner", "objective", 1));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("owner", "objective", 2));
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void displayAndChangeScoreDisplayName() {
|
||||
// this ensures that MCPE-143063 is properly handled
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("owner", "objective", 1));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("owner", "objective", 1).withDisplay(Component.text("hi"))
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "hi")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "hi")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void displayAndChangeScoreDisplayNameAndValue() {
|
||||
// this ensures that MCPE-143063 is properly handled
|
||||
mockContextScoreboard(context -> {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
var setScoreTranslator = new JavaSetScoreTranslator();
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective"),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
);
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("owner", "objective", 1));
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("owner", "objective", 2).withDisplay(Component.text("hi"))
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, "hi")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, "hi")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Supplier;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
||||
public class AssertUtils {
|
||||
public static <T> void assertContextEquals(Supplier<? extends T> expected, T actual) {
|
||||
if (actual == null) {
|
||||
Assertions.fail("Expected another packet! " + expected.get());
|
||||
}
|
||||
Assertions.assertEquals(expected.get(), actual);
|
||||
}
|
||||
|
||||
public static void assertNextPacket(Supplier<BedrockPacket> expected, GeyserMockContext context) {
|
||||
assertContextEquals(expected, context.nextPacket());
|
||||
}
|
||||
|
||||
public static void assertNoNextPacket(GeyserMockContext context) {
|
||||
Assertions.assertEquals(
|
||||
Collections.emptyList(),
|
||||
context.packets(),
|
||||
"Expected no remaining packets, got " + context.packetCount()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.util;
|
||||
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
|
||||
public class EmptyGeyserLogger implements GeyserLogger {
|
||||
@Override
|
||||
public void severe(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void severe(String message, Throwable error) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, Throwable error) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDebug(boolean debug) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebug() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.util;
|
||||
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public class GeyserMockContext {
|
||||
private final List<Object> mocksAndSpies = new ArrayList<>();
|
||||
private final List<Object> storedObjects = new ArrayList<>();
|
||||
private final List<BedrockPacket> packets = Collections.synchronizedList(new ArrayList<>());
|
||||
private MockedStatic<GeyserImpl> geyserImplMock;
|
||||
|
||||
public static void mockContext(Consumer<GeyserMockContext> geyserContext) {
|
||||
var context = new GeyserMockContext();
|
||||
|
||||
var geyserImpl = context.mock(GeyserImpl.class);
|
||||
var config = context.mock(GeyserConfiguration.class);
|
||||
|
||||
when(config.getScoreboardPacketThreshold()).thenReturn(1_000);
|
||||
|
||||
when(geyserImpl.getConfig()).thenReturn(config);
|
||||
|
||||
var logger = context.storeObject(new EmptyGeyserLogger());
|
||||
when(geyserImpl.getLogger()).thenReturn(logger);
|
||||
|
||||
try (var mocked = mockStatic(GeyserImpl.class)) {
|
||||
mocked.when(GeyserImpl::getInstance).thenReturn(geyserImpl);
|
||||
context.geyserImplMock = mocked;
|
||||
geyserContext.accept(context);
|
||||
}
|
||||
}
|
||||
|
||||
public static void mockContext(Runnable runnable) {
|
||||
mockContext(context -> runnable.run());
|
||||
}
|
||||
|
||||
public <T> T mock(Class<T> type) {
|
||||
return addMockOrSpy(Mockito.mock(type));
|
||||
}
|
||||
|
||||
public <T> T spy(T object) {
|
||||
return addMockOrSpy(Mockito.spy(object));
|
||||
}
|
||||
|
||||
private <T> T addMockOrSpy(T mockOrSpy) {
|
||||
mocksAndSpies.add(mockOrSpy);
|
||||
return mockOrSpy;
|
||||
}
|
||||
|
||||
public <T> T storeObject(T object) {
|
||||
storedObjects.add(object);
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retries the mock or spy that is an instance of the specified type.
|
||||
* This is only really intended for classes where you only need a single instance of.
|
||||
*/
|
||||
public <T> T mockOrSpy(Class<T> type) {
|
||||
for (Object mock : mocksAndSpies) {
|
||||
if (type.isInstance(mock)) {
|
||||
return type.cast(mock);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T storedObject(Class<T> type) {
|
||||
for (Object storedObject : storedObjects) {
|
||||
if (type.isInstance(storedObject)) {
|
||||
return type.cast(storedObject);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public GeyserSession session() {
|
||||
return mockOrSpy(GeyserSession.class);
|
||||
}
|
||||
|
||||
void addPacket(BedrockPacket packet) {
|
||||
packets.add(packet);
|
||||
}
|
||||
|
||||
public int packetCount() {
|
||||
return packets.size();
|
||||
}
|
||||
|
||||
public BedrockPacket nextPacket() {
|
||||
if (packets.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return packets.remove(0);
|
||||
}
|
||||
|
||||
public List<BedrockPacket> packets() {
|
||||
return Collections.unmodifiableList(packets);
|
||||
}
|
||||
|
||||
public <T> void translate(PacketTranslator<T> translator, T packet) {
|
||||
translator.translate(session(), packet);
|
||||
}
|
||||
|
||||
public MockedStatic<GeyserImpl> geyserImplMock() {
|
||||
return geyserImplMock;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.util;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContext.mockContext;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataMap;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.EntityCache;
|
||||
import org.geysermc.geyser.session.cache.WorldCache;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
public class GeyserMockContextScoreboard {
|
||||
public static void mockContextScoreboard(Consumer<GeyserMockContext> geyserContext) {
|
||||
mockContext(context -> {
|
||||
createSessionSpy(context);
|
||||
geyserContext.accept(context);
|
||||
|
||||
assertNoNextPacket(context);
|
||||
});
|
||||
}
|
||||
|
||||
private static void createSessionSpy(GeyserMockContext context) {
|
||||
// GeyserSession has so many dependencies, it's easier to just mock it
|
||||
var session = context.mock(GeyserSession.class);
|
||||
|
||||
when(session.locale()).thenReturn("en_US");
|
||||
doAnswer((Answer<Void>) invocation -> {
|
||||
context.addPacket(invocation.getArgument(0, BedrockPacket.class));
|
||||
return null;
|
||||
}).when(session).sendUpstreamPacket(any());
|
||||
|
||||
// SessionPlayerEntity loads stuff in like blocks, which is not what we want
|
||||
var playerEntity = context.mock(SessionPlayerEntity.class);
|
||||
when(playerEntity.getGeyserId()).thenReturn(1L);
|
||||
when(playerEntity.getUsername()).thenReturn("Tim203");
|
||||
when(session.getPlayerEntity()).thenReturn(playerEntity);
|
||||
|
||||
var entityCache = context.spy(new EntityCache(session));
|
||||
when(session.getEntityCache()).thenReturn(entityCache);
|
||||
|
||||
var worldCache = context.spy(new WorldCache(session));
|
||||
when(session.getWorldCache()).thenReturn(worldCache);
|
||||
|
||||
// disable global scoreboard updater
|
||||
when(worldCache.increaseAndGetScoreboardPacketsPerSecond()).thenReturn(0);
|
||||
}
|
||||
|
||||
public static PlayerEntity mockAndAddPlayerEntity(GeyserMockContext context, String username, long geyserId) {
|
||||
var playerEntity = spy(new PlayerEntity(context.session(), geyserId, UUID.randomUUID(), username));
|
||||
// fake the player being spawned
|
||||
when(playerEntity.isValid()).thenReturn(true);
|
||||
|
||||
var entityCache = context.mockOrSpy(EntityCache.class);
|
||||
entityCache.addPlayerEntity(playerEntity);
|
||||
// called when the player spawns
|
||||
entityCache.cacheEntity(playerEntity);
|
||||
return playerEntity;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user