Skip to content

Commit

Permalink
Add an event for building waiting lobby user interface layouts
Browse files Browse the repository at this point in the history
  • Loading branch information
haykam821 committed Nov 6, 2024
1 parent 9992d78 commit ead3133
Show file tree
Hide file tree
Showing 16 changed files with 603 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package xyz.nucleoid.plasmid.game.common;

import com.mojang.authlib.GameProfile;
import eu.pb4.polymer.core.api.utils.PolymerUtils;
import net.minecraft.entity.boss.BossBar;
import net.minecraft.screen.ScreenTexts;
import net.minecraft.server.network.ServerPlayerEntity;
Expand All @@ -16,6 +17,7 @@
import xyz.nucleoid.plasmid.game.GameSpace;
import xyz.nucleoid.plasmid.game.GameTexts;
import xyz.nucleoid.plasmid.game.common.config.PlayerConfig;
import xyz.nucleoid.plasmid.game.common.ui.WaitingLobbyUi;
import xyz.nucleoid.plasmid.game.common.widget.BossBarWidget;
import xyz.nucleoid.plasmid.game.common.widget.SidebarWidget;
import xyz.nucleoid.plasmid.game.config.GameConfig;
Expand Down Expand Up @@ -90,6 +92,7 @@ public static GameWaitingLobby addTo(GameActivity activity, PlayerConfig playerC
activity.listen(GameActivityEvents.TICK, lobby::onTick);
activity.listen(GameActivityEvents.REQUEST_START, lobby::requestStart);
activity.listen(GamePlayerEvents.OFFER, lobby::offerPlayer);
activity.listen(GamePlayerEvents.ADD, lobby::onAddPlayer);
activity.listen(GamePlayerEvents.REMOVE, lobby::onRemovePlayer);


Expand Down Expand Up @@ -150,6 +153,11 @@ private void onTick() {
this.started = false;
this.startRequested = false;
this.countdownStart = -1;
} else {
for (var player : this.gameSpace.getPlayers()) {
player.closeHandledScreen();
PolymerUtils.reloadInventory(player);
}
}
}
}
Expand Down Expand Up @@ -180,6 +188,11 @@ private JoinOfferResult offerPlayer(JoinOffer offer) {
return offer.pass();
}

private void onAddPlayer(ServerPlayerEntity player) {
var ui = new WaitingLobbyUi(player, this.gameSpace);
ui.open();
}

private void onRemovePlayer(ServerPlayerEntity player) {
this.updateCountdown();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
package xyz.nucleoid.plasmid.game.common.team;

import com.mojang.serialization.Codec;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMaps;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.NbtComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtOps;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import xyz.nucleoid.plasmid.Plasmid;
import xyz.nucleoid.plasmid.game.GameActivity;
import xyz.nucleoid.plasmid.game.event.GamePlayerEvents;
import xyz.nucleoid.plasmid.game.common.ui.WaitingLobbyUiLayout;
import xyz.nucleoid.plasmid.game.common.ui.element.TeamSelectionWaitingLobbyUiElement;
import xyz.nucleoid.plasmid.game.event.GameWaitingLobbyEvents;
import xyz.nucleoid.plasmid.game.player.PlayerIterable;
import xyz.nucleoid.plasmid.util.ColoredBlocks;
import xyz.nucleoid.stimuli.event.item.ItemUseEvent;

import java.util.Map;
import java.util.UUID;
Expand All @@ -39,8 +29,6 @@
* @see xyz.nucleoid.plasmid.game.common.GameWaitingLobby
*/
public final class TeamSelectionLobby {
private static final String TEAM_KEY = Plasmid.ID + ":team";

private final GameTeamList teams;

private final Reference2IntMap<GameTeamKey> maxTeamSize = new Reference2IntOpenHashMap<>();
Expand All @@ -60,8 +48,7 @@ private TeamSelectionLobby(GameTeamList teams) {
*/
public static TeamSelectionLobby addTo(GameActivity activity, GameTeamList teams) {
var lobby = new TeamSelectionLobby(teams);
activity.listen(GamePlayerEvents.ADD, lobby::onAddPlayer);
activity.listen(ItemUseEvent.EVENT, lobby::onUseItem);
activity.listen(GameWaitingLobbyEvents.BUILD_UI_LAYOUT, lobby::onBuildUiLayout);

return lobby;
}
Expand All @@ -76,30 +63,8 @@ public void setSizeForTeam(GameTeamKey team, int size) {
this.maxTeamSize.put(team, size);
}

private void onAddPlayer(ServerPlayerEntity player) {
int index = 0;

for (var team : this.teams) {
var config = team.config();
var name = Text.translatable("text.plasmid.team_selection.request_team", config.name())
.formatted(Formatting.BOLD, config.chatFormatting());

var stack = new ItemStack(ColoredBlocks.wool(config.blockDyeColor()));
stack.set(DataComponentTypes.ITEM_NAME, name);

stack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT.with(NbtOps.INSTANCE, Codec.STRING.fieldOf(TEAM_KEY), team.key().id()).getOrThrow());

player.getInventory().setStack(index++, stack);
}
}

private ActionResult onUseItem(ServerPlayerEntity player, Hand hand) {
var stack = player.getStackInHand(hand);

if (stack.isIn(ItemTags.WOOL)) {
var key = new GameTeamKey(stack.getOrDefault(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT)
.get(Codec.STRING.fieldOf(TEAM_KEY)).getOrThrow());

private void onBuildUiLayout(WaitingLobbyUiLayout layout, ServerPlayerEntity player) {
layout.addLeft(new TeamSelectionWaitingLobbyUiElement(teams, key -> {
var team = this.teams.byKey(key);
if (team != null) {
var config = team.config();
Expand All @@ -110,12 +75,8 @@ private ActionResult onUseItem(ServerPlayerEntity player, Hand hand) {
Text.translatable("text.plasmid.team_selection.suffixed_team", config.name()).formatted(config.chatFormatting()));

player.sendMessage(message, false);

return ActionResult.SUCCESS;
}
}

return ActionResult.PASS;
}));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package xyz.nucleoid.plasmid.game.common.ui;

import eu.pb4.sgui.api.gui.HotbarGui;
import net.minecraft.server.network.ServerPlayerEntity;
import xyz.nucleoid.plasmid.game.GameSpace;
import xyz.nucleoid.plasmid.game.event.GameWaitingLobbyEvents;
import xyz.nucleoid.stimuli.Stimuli;

public class WaitingLobbyUi extends HotbarGui {
public WaitingLobbyUi(ServerPlayerEntity player, GameSpace gameSpace) {
super(player);

var layout = new WaitingLobbyUiLayout();

try (var invokers = Stimuli.select().forEntity(player)) {
invokers.get(GameWaitingLobbyEvents.BUILD_UI_LAYOUT).onBuildUiLayout(layout, player);
}

int index = 0;

for (var element : layout.build()) {
this.setSlot(index, element);
index += 1;
}
}

@Override
public boolean canPlayerClose() {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package xyz.nucleoid.plasmid.game.common.ui;

import eu.pb4.sgui.api.elements.GuiElement;
import eu.pb4.sgui.api.elements.GuiElementInterface;
import eu.pb4.sgui.api.gui.HotbarGui;
import xyz.nucleoid.plasmid.game.common.ui.element.WaitingLobbyUiElement;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

public final class WaitingLobbyUiLayout {
private static final int SIZE = 9;

private final List<WaitingLobbyUiElement> leftElements = new ArrayList<>();
private final List<WaitingLobbyUiElement> rightElements = new ArrayList<>();

public void addLeft(WaitingLobbyUiElement element) {
this.add(element, this.leftElements);
}

public void addRight(WaitingLobbyUiElement element) {
this.add(element, this.rightElements);
}

private void add(WaitingLobbyUiElement element, List<WaitingLobbyUiElement> elements) {
Objects.requireNonNull(element);

if (this.leftElements.contains(element) || this.rightElements.contains(element)) {
throw new IllegalArgumentException("Element " + element + " has already been added to the layout");
} else if (this.leftElements.size() + this.rightElements.size() >= SIZE) {
throw new IllegalStateException("Cannot have more than " + SIZE + " elements in the layout");
}

elements.add(element);
}

public GuiElementInterface[] build() {
var elements = new GuiElementInterface[SIZE];
Arrays.fill(elements, GuiElement.EMPTY);

if (this.leftElements.isEmpty() && this.rightElements.isEmpty()) {
return elements;
}

var elementsToEntries = new HashMap<WaitingLobbyUiElement, WaitingLobbyUiLayoutEntry>(this.leftElements.size() + this.rightElements.size());

for (var element : this.leftElements) {
elementsToEntries.put(element, new WaitingLobbyUiLayoutEntry(element));
}

for (var element : this.rightElements) {
elementsToEntries.put(element, new WaitingLobbyUiLayoutEntry(element));
}

var entries = new ArrayList<>(elementsToEntries.values());
entries.sort(Comparator.comparingInt(WaitingLobbyUiLayoutEntry::size));

int shrinkIndex = 0;

while (WaitingLobbyUiLayoutEntry.getTotalSize(entries) > SIZE) {
var entry = entries.get(shrinkIndex);
entry.shrink();

shrinkIndex += 1;
}

int index = 0;

for (var element : this.leftElements) {
var entry = elementsToEntries.get(element);

for (var guiElement : entry.getGuiElements()) {
elements[index] = guiElement;
index += 1;
}
}

index = SIZE - 1;

for (var element : this.rightElements) {
var entry = elementsToEntries.get(element);

for (var guiElement : entry.getGuiElements()) {
elements[index] = guiElement;
index -= 1;
}
}

return elements;
}

@Override
public String toString() {
return "WaitingLobbyUiLayout{leftElements=" + this.leftElements + ", rightElements=" + this.rightElements + "}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package xyz.nucleoid.plasmid.game.common.ui;

import eu.pb4.sgui.api.elements.GuiElementInterface;
import xyz.nucleoid.plasmid.game.common.ui.element.WaitingLobbyUiElement;

import java.util.List;
import java.util.SequencedCollection;

class WaitingLobbyUiLayoutEntry {
private final WaitingLobbyUiElement element;

private SequencedCollection<GuiElementInterface> guiElements;

protected WaitingLobbyUiLayoutEntry(WaitingLobbyUiElement element) {
this.element = element;

this.guiElements = element.createExtendedElements();
}

public SequencedCollection<GuiElementInterface> getGuiElements() {
return this.guiElements;
}

public void shrink() {
this.guiElements = List.of(this.element.createMainElement());
}

public int size() {
return this.guiElements.size();
}

@Override
public String toString() {
return "WaitingLobbyUiLayoutEntry{element=" + element + ", guiElements=" + guiElements + "}";
}

protected static int getTotalSize(Iterable<WaitingLobbyUiLayoutEntry> entries) {
int size = 0;

for (var entry : entries) {
size += entry.size();
}

return size;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package xyz.nucleoid.plasmid.game.common.ui.element;

import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.elements.GuiElementInterface;
import net.minecraft.item.Items;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import xyz.nucleoid.plasmid.game.common.team.GameTeamKey;
import xyz.nucleoid.plasmid.game.common.team.GameTeamList;
import xyz.nucleoid.plasmid.util.ColoredBlocks;

import java.util.ArrayList;
import java.util.SequencedCollection;
import java.util.function.Consumer;

public class TeamSelectionWaitingLobbyUiElement implements WaitingLobbyUiElement {
private final GameTeamList teams;
private final Consumer<GameTeamKey> selectCallback;

public TeamSelectionWaitingLobbyUiElement(GameTeamList teams, Consumer<GameTeamKey> selectCallback) {
this.teams = teams;
this.selectCallback = selectCallback;
}

@Override
public GuiElementInterface createMainElement() {
return new GuiElementBuilder(Items.PAPER)
.setItemName(Text.translatable("text.plasmid.team_selection.teams"))
.build();
}

@Override
public SequencedCollection<GuiElementInterface> createExtendedElements() {
var extendedElements = new ArrayList<GuiElementInterface>(this.teams.list().size());

for (var team : this.teams) {
var key = team.key();
var config = team.config();

var name = Text.translatable("text.plasmid.team_selection.request_team", config.name())
.formatted(Formatting.BOLD, config.chatFormatting());

var element = new GuiElementBuilder(ColoredBlocks.wool(config.blockDyeColor()).asItem())
.setItemName(name)
.setCallback((index, type, action) -> {
if (type.isRight) {
this.selectCallback.accept(key);
}
})
.build();

extendedElements.add(element);
}

return extendedElements;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package xyz.nucleoid.plasmid.game.common.ui.element;

import java.util.SequencedCollection;

import eu.pb4.sgui.api.elements.GuiElementInterface;

public interface WaitingLobbyUiElement {
GuiElementInterface createMainElement();

SequencedCollection<GuiElementInterface> createExtendedElements();
}
Loading

0 comments on commit ead3133

Please sign in to comment.