Refactored party system commands. Simplified logic and improved readability.

This commit is contained in:
IM23a-spirgif
2025-06-07 20:42:52 +02:00
parent 6c7f997fcb
commit 8f046ded11
@@ -18,55 +18,25 @@ import net.neoforged.neoforge.event.entity.player.AttackEntityEvent;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/**
* Party/”comrade” handler.
*
* Commands:
* /comrade party create
* /comrade invite <player>
* /comrade accept <leader>
* /comrade remove <member>
* /comrade list
*
* Only the party “leader” can remove others. Invites must be accepted by the target.
* If you invite someone but you arent yet in a party, you automatically become leader of a new party.
*/
@EventBusSubscriber( @EventBusSubscriber(
modid = Stalinium.MODID, modid = Stalinium.MODID,
bus = EventBusSubscriber.Bus.GAME bus = EventBusSubscriber.Bus.GAME
) )
public class ComradeHandler { public class ComradeHandler {
/** Maps each party leader → Party object. Only the leaders UUID is the key. */
public static final Map<UUID, Party> PARTIES = new ConcurrentHashMap<>(); public static final Map<UUID, Party> PARTIES = new ConcurrentHashMap<>();
/** If player X has been invited by leader Y, pendingInvites maps X → Y. */
private static final Map<UUID, UUID> PENDING_INVITES = new ConcurrentHashMap<>(); private static final Map<UUID, UUID> PENDING_INVITES = new ConcurrentHashMap<>();
/** A small helper class to store party data. */
public static class Party { public static class Party {
final UUID leader; public final UUID leader;
public final Set<UUID> members = ConcurrentHashMap.newKeySet(); public final Set<UUID> members = ConcurrentHashMap.newKeySet();
public Party(UUID leader) {
Party(UUID leader) {
this.leader = leader; this.leader = leader;
this.members.add(leader); this.members.add(leader);
} }
public boolean isMember(UUID u) { return members.contains(u); }
public boolean isMember(UUID uuid) { public boolean isLeader(UUID u) { return leader.equals(u); }
return members.contains(uuid); public void addMember(UUID u) { members.add(u); }
} public void removeMember(UUID u) { members.remove(u); }
void addMember(UUID uuid) {
members.add(uuid);
}
void removeMember(UUID uuid) {
members.remove(uuid);
}
boolean isLeader(UUID uuid) {
return leader.equals(uuid);
}
} }
public static Optional<Party> findPartyOf(UUID uuid) { public static Optional<Party> findPartyOf(UUID uuid) {
@@ -75,10 +45,10 @@ public class ComradeHandler {
.findAny(); .findAny();
} }
private static Optional<Party> findPartyByLeader(UUID leaderUuid) { private static Optional<Party> findPartyByLeader(UUID leader) {
return Optional.ofNullable(PARTIES.get(leaderUuid)); return Optional.ofNullable(PARTIES.get(leader));
} }
@SubscribeEvent @SubscribeEvent
public static void onRegisterCommands(RegisterCommandsEvent event) { public static void onRegisterCommands(RegisterCommandsEvent event) {
event.getDispatcher().register( event.getDispatcher().register(
@@ -87,224 +57,193 @@ public class ComradeHandler {
.then(Commands.literal("create") .then(Commands.literal("create")
.executes(ctx -> { .executes(ctx -> {
ServerPlayer sender = ctx.getSource().getPlayerOrException(); ServerPlayer sender = ctx.getSource().getPlayerOrException();
UUID senderId = sender.getUUID(); UUID me = sender.getUUID();
if (findPartyOf(me).isPresent()) {
// If sender is already in a party, do nothing. ctx.getSource().sendFailure(Component.literal("§eYou are already in a party."));
if (findPartyOf(senderId).isPresent()) {
ctx.getSource().sendFailure(
Component.literal("§eYou are already in a party.")
);
return 0; return 0;
} }
Party newParty = new Party(senderId); PARTIES.put(me, new Party(me));
PARTIES.put(senderId, newParty); ctx.getSource().sendSuccess(() -> Component.literal("§aParty created. You are now the leader."), false);
ctx.getSource().sendSuccess(
() -> Component.literal("§aParty created. You are now the leader."),
false
);
return 1; return 1;
}) })
) )
) .then(Commands.literal("invite")
.then(Commands.literal("invite") .then(Commands.argument("player", EntityArgument.player())
.then(Commands.argument("player", EntityArgument.player()) .executes(ctx -> {
.executes(ctx -> { ServerPlayer leader = ctx.getSource().getPlayerOrException();
ServerPlayer sender = ctx.getSource().getPlayerOrException(); ServerPlayer target = EntityArgument.getPlayer(ctx, "player");
ServerPlayer target = EntityArgument.getPlayer(ctx, "player"); UUID lid = leader.getUUID(), tid = target.getUUID();
UUID senderId = sender.getUUID(); if (lid.equals(tid)) {
UUID targetId = target.getUUID(); ctx.getSource().sendFailure(Component.literal("§eYou cannot invite yourself."));
if (senderId.equals(targetId)) { return 0;
ctx.getSource().sendFailure( }
Component.literal("§eYou cannot invite yourself.") // ensure party exists & you are leader
); Party party = findPartyOf(lid).orElseGet(() -> {
return 0; Party auto = new Party(lid);
} PARTIES.put(lid, auto);
Optional<Party> senderPartyOpt = findPartyOf(senderId); ctx.getSource().sendSuccess(() -> Component.literal("§aNo existing party—one was created for you."), false);
if (senderPartyOpt.isPresent()) { return auto;
Party party = senderPartyOpt.get();
if (party.isMember(targetId)) {
ctx.getSource().sendFailure(
Component.literal("§eThat player is already in your party.")
);
return 0;
}
} else {
Party auto = new Party(senderId);
PARTIES.put(senderId, auto);
senderPartyOpt = Optional.of(auto);
ctx.getSource().sendSuccess(
() -> Component.literal("§aNo party found, so one was automatically created. You are now leader."),
false
);
}
Party party = senderPartyOpt.get();
if (!party.isLeader(senderId)) {
ctx.getSource().sendFailure(
Component.literal("§eOnly the party leader can invite new comrades.")
);
return 0;
}
PENDING_INVITES.put(targetId, senderId);
target.sendSystemMessage(
Component.literal("§6" + sender.getName().getString()
+ " §awants you to join their party. Type §e/comrade accept "
+ sender.getName().getString() + " §ato accept.")
);
ctx.getSource().sendSuccess(
() -> Component.literal("§aInvitation sent to §6" + target.getName().getString() + "§a."),
false
);
return 1;
})
)
)
.then(Commands.literal("accept")
.then(Commands.argument("leader", EntityArgument.player())
.executes(ctx -> {
ServerPlayer accepter = ctx.getSource().getPlayerOrException();
ServerPlayer leader = EntityArgument.getPlayer(ctx, "leader");
UUID accepterId = accepter.getUUID();
UUID leaderId = leader.getUUID();
UUID expected = PENDING_INVITES.get(accepterId);
if (expected == null || !expected.equals(leaderId)) {
ctx.getSource().sendFailure(
Component.literal("§eNo invitation found from that leader.")
);
return 0;
}
// Find (or create) the leaders party:
Party party = findPartyByLeader(leaderId)
.orElseGet(() -> {
Party brandNew = new Party(leaderId);
PARTIES.put(leaderId, brandNew);
return brandNew;
}); });
if (!party.isLeader(lid)) {
// Add this player to that party: ctx.getSource().sendFailure(Component.literal("§eOnly the party leader can invite."));
party.addMember(accepterId); return 0;
PENDING_INVITES.remove(accepterId); }
if (party.isMember(tid)) {
accepter.sendSystemMessage( ctx.getSource().sendFailure(Component.literal("§eThat player is already in your party."));
Component.literal("§aYou have joined §6" + leader.getName().getString() + "§as party.") return 0;
); }
leader.sendSystemMessage( PENDING_INVITES.put(tid, lid);
Component.literal("§a" + accepter.getName().getString() + " §ais now your comrade.") target.sendSystemMessage(Component.literal(
); "§6" + leader.getName().getString()
return 1; + " §awants you to join their party! Type §e/comrade party accept "
}) + leader.getName().getString() + "§a."
));
ctx.getSource().sendSuccess(() ->
Component.literal("§aInvitation sent to §6" + target.getName().getString()), false);
return 1;
})
)
) )
) .then(Commands.literal("accept")
.then(Commands.literal("remove") .then(Commands.argument("leader", EntityArgument.player())
.then(Commands.argument("player", EntityArgument.player()) .executes(ctx -> {
ServerPlayer you = ctx.getSource().getPlayerOrException();
ServerPlayer leader= EntityArgument.getPlayer(ctx,"leader");
UUID yid = you.getUUID(), lid = leader.getUUID();
if (!Objects.equals(PENDING_INVITES.get(yid), lid)) {
ctx.getSource().sendFailure(Component.literal("§eNo invitation found from that leader."));
return 0;
}
Party party = findPartyByLeader(lid)
.orElseGet(() -> {
Party p = new Party(lid);
PARTIES.put(lid, p);
return p;
});
party.addMember(yid);
PENDING_INVITES.remove(yid);
you.sendSystemMessage(Component.literal("§aYou joined §6" + leader.getName().getString() + "§as party."));
leader.sendSystemMessage(Component.literal("§a" + you.getName().getString() + " §ais now your comrade."));
return 1;
})
)
)
.then(Commands.literal("remove")
.then(Commands.argument("player", EntityArgument.player())
.executes(ctx -> {
ServerPlayer leader = ctx.getSource().getPlayerOrException();
ServerPlayer target = EntityArgument.getPlayer(ctx,"player");
UUID lid = leader.getUUID(), tid = target.getUUID();
Optional<Party> opt = findPartyOf(lid);
if (opt.isEmpty()) {
ctx.getSource().sendFailure(Component.literal("§eYou have no party."));
return 0;
}
Party party = opt.get();
if (!party.isLeader(lid)) {
ctx.getSource().sendFailure(Component.literal("§eOnly the leader can remove."));
return 0;
}
if (!party.isMember(tid)) {
ctx.getSource().sendFailure(Component.literal("§eThat player is not in your party."));
return 0;
}
party.removeMember(tid);
target.sendSystemMessage(Component.literal(
"§cYou have been removed from §6" + leader.getName().getString() + "§cs party."
));
ctx.getSource().sendSuccess(() ->
Component.literal("§aRemoved “" + target.getName().getString() + "”."), false);
return 1;
})
)
)
.then(Commands.literal("leave")
.executes(ctx -> { .executes(ctx -> {
ServerPlayer sender = ctx.getSource().getPlayerOrException(); ServerPlayer you = ctx.getSource().getPlayerOrException();
ServerPlayer toRemove = EntityArgument.getPlayer(ctx, "player"); UUID youId = you.getUUID();
UUID senderId = sender.getUUID(); Optional<Party> opt = findPartyOf(youId);
UUID removeId = toRemove.getUUID(); if (opt.isEmpty()) {
Optional<Party> maybeParty = findPartyOf(senderId); ctx.getSource().sendFailure(Component.literal("§eYou are not in a party."));
if (maybeParty.isEmpty()) {
ctx.getSource().sendFailure(
Component.literal("§eYou are not comrades with anyone.")
);
return 0; return 0;
} }
Party party = maybeParty.get(); Party party = opt.get();
if (!party.isLeader(senderId)) { if (party.isLeader(youId)) {
ctx.getSource().sendFailure( ctx.getSource().sendFailure(Component.literal(
Component.literal("§eOnly the party leader may remove members.") "§eYou are the leader — use /comrade party disband to tear it down."));
);
return 0; return 0;
} }
if (removeId.equals(senderId)) { party.removeMember(youId);
ctx.getSource().sendFailure( you.sendSystemMessage(Component.literal("§cYou left the party."));
Component.literal("§eYou cannot remove yourself from your own party.") MinecraftServer srv = ctx.getSource().getServer();
); ServerPlayer leader = srv.getPlayerList().getPlayer(party.leader);
return 0; if (leader != null) {
} leader.sendSystemMessage(Component.literal(
if (!party.isMember(removeId)) { "§e" + you.getName().getString() + " has left your party."));
ctx.getSource().sendFailure(
Component.literal("§eThat player is not one of your comrades.")
);
return 0;
}
party.removeMember(removeId);
toRemove.sendSystemMessage(
Component.literal("§cYou are no longer "
+ sender.getName().getString() + "'s comrade.")
);
ctx.getSource().sendSuccess(
() -> Component.literal("§a“" + toRemove.getName().getString()
+ "” is no longer your comrade."),
false
);
if (party.members.size() == 1 && party.isLeader(senderId)) {
PARTIES.remove(senderId);
sender.sendSystemMessage(
Component.literal("§6Your party was disbanded (no more members).")
);
} }
return 1; return 1;
}) })
) )
) .then(Commands.literal("disband")
.then(Commands.literal("list") .executes(ctx -> {
.executes(ctx -> { ServerPlayer leader = ctx.getSource().getPlayerOrException();
ServerPlayer sender = ctx.getSource().getPlayerOrException(); UUID lid = leader.getUUID();
UUID senderId = sender.getUUID(); Optional<Party> opt = findPartyByLeader(lid);
Optional<Party> maybeParty = findPartyOf(senderId); if (opt.isEmpty()) {
if (maybeParty.isEmpty()) { ctx.getSource().sendFailure(Component.literal("§eYou are not leading any party."));
ctx.getSource().sendSuccess( return 0;
() -> Component.literal("§eYou are not in a party."), }
false Party party = opt.get();
); MinecraftServer srv = ctx.getSource().getServer();
return 0; party.members.forEach(m -> {
} ServerPlayer p = srv.getPlayerList().getPlayer(m);
Party party = maybeParty.get(); if (p != null) {
MinecraftServer server = ctx.getSource().getServer(); p.sendSystemMessage(Component.literal("§cYour party has been disbanded."));
List<String> displayNames = new ArrayList<>(); }
for (UUID memberUuid : party.members) { });
ServerPlayer online = server.getPlayerList().getPlayer(memberUuid); PENDING_INVITES.entrySet().removeIf(e -> e.getValue().equals(lid));
if (online != null) { PARTIES.remove(lid);
displayNames.add(online.getName().getString());
} else { return 1;
displayNames.add(memberUuid.toString()); })
} )
} .then(Commands.literal("list")
String joined = String.join(", ", displayNames); .executes(ctx -> {
ctx.getSource().sendSuccess( ServerPlayer you = ctx.getSource().getPlayerOrException();
() -> Component.literal("§6Party members: §f" + joined), UUID youId = you.getUUID();
false Optional<Party> opt = findPartyOf(youId);
); if (opt.isEmpty()) {
return 1; ctx.getSource().sendSuccess(() -> Component.literal("§eYou are not in a party."), false);
}) return 0;
}
Party party = opt.get();
MinecraftServer srv = ctx.getSource().getServer();
List<String> names = new ArrayList<>();
for(UUID m : party.members){
ServerPlayer p = srv.getPlayerList().getPlayer(m);
names.add(p != null ? p.getName().getString() : m.toString());
}
String out = String.join(", ", names);
ctx.getSource().sendSuccess(() -> Component.literal("§6Party: §f" + out), false);
return 1;
})
)
) )
); );
} }
@SubscribeEvent @SubscribeEvent
public static void onPlayerAttackEntity(AttackEntityEvent event) { public static void onPlayerAttackEntity(AttackEntityEvent event) {
LivingEntity source = event.getEntity(); LivingEntity src = event.getEntity();
if (source.level().isClientSide) return; if (src.level().isClientSide || !(src instanceof Player)) return;
if (!(source instanceof Player)) return; if (!(event.getTarget() instanceof ServerPlayer victim)) return;
UUID a = src.getUUID(), b = victim.getUUID();
if (event.getTarget() instanceof ServerPlayer targetPlayer) { Optional<Party> opt = findPartyOf(a);
UUID sourceId = source.getUUID(); if (opt.isPresent() && opt.get().isMember(b)) {
UUID targetId = targetPlayer.getUUID(); event.setCanceled(true);
src.sendSystemMessage(Component.literal(
// If both are in the same party, cancel damage: "§cYou cannot hurt your comrade “" + victim.getName().getString() + "”!"
Optional<Party> maybeParty = findPartyOf(sourceId); ));
if (maybeParty.isPresent()) {
Party party = maybeParty.get();
if (party.isMember(targetId)) {
event.setCanceled(true);
source.sendSystemMessage(
Component.literal("§cYou cannot hurt your comrade “"
+ targetPlayer.getName().getString() + "”!")
);
}
}
} }
} }
} }