From fd8d8645d0b241573b42fb05d51967d97e68ab92 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 3 Jul 2022 22:21:30 +0200 Subject: [PATCH 01/20] Permission-based power modifiers --- build.gradle | 1 + gradle.properties | 1 + .../factions/api/persistents/Faction.java | 18 +++++--- .../icker/factions/api/persistents/User.java | 46 ++++++++++++++++++- .../factions/command/SettingsCommand.java | 16 +++---- .../icker/factions/util/PermissionUtil.java | 37 +++++++++++++++ .../factions/util/PlaceholdersWrapper.java | 28 +++++++++-- 7 files changed, 128 insertions(+), 19 deletions(-) create mode 100644 src/main/java/io/icker/factions/util/PermissionUtil.java diff --git a/build.gradle b/build.gradle index 7633b9c0..77ce7a68 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ dependencies { modImplementation "me.lucko:fabric-permissions-api:${project.lucko_permissions_version}" modImplementation include("eu.pb4:placeholder-api:${project.papi_version}") include "me.lucko:fabric-permissions-api:${project.lucko_permissions_version}" + compileOnly "net.luckperms:api:${project.lpapi_version}" compileOnly "us.dynmap:DynmapCoreAPI:${project.dynmap_api_version}" implementation(include("com.h2database:h2:${project.h2_version}")) } diff --git a/gradle.properties b/gradle.properties index 6d5bbe56..5815c62e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,5 +14,6 @@ archives_base_name = factions h2_version=1.4.200 fabric_version=0.55.2+1.19 lucko_permissions_version=0.1-SNAPSHOT +lpapi_version = 5.4 dynmap_api_version=3.4-beta-3 papi_version=2.0.0-beta.6+1.19 \ No newline at end of file diff --git a/src/main/java/io/icker/factions/api/persistents/Faction.java b/src/main/java/io/icker/factions/api/persistents/Faction.java index 974f3310..3a65abf4 100644 --- a/src/main/java/io/icker/factions/api/persistents/Faction.java +++ b/src/main/java/io/icker/factions/api/persistents/Faction.java @@ -1,6 +1,5 @@ package io.icker.factions.api.persistents; -import io.icker.factions.FactionsMod; import io.icker.factions.api.events.FactionEvents; import io.icker.factions.database.Database; import io.icker.factions.database.Field; @@ -11,6 +10,8 @@ import java.util.*; +import static io.icker.factions.FactionsMod.CONFIG; + @Name("Faction") public class Faction { private static final HashMap STORE = Database.load(Faction.class, Faction::getID); @@ -102,8 +103,8 @@ public String getName() { } public Message getTruncatedName() { - boolean overLength = FactionsMod.CONFIG.NAME_MAX_LENGTH > -1 && name.length() > FactionsMod.CONFIG.NAME_MAX_LENGTH; - Message displayName = new Message(overLength ? name.substring(0, FactionsMod.CONFIG.NAME_MAX_LENGTH - 1) + "..." : name); + boolean overLength = CONFIG.NAME_MAX_LENGTH > -1 && name.length() > CONFIG.NAME_MAX_LENGTH; + Message displayName = new Message(overLength ? name.substring(0, CONFIG.NAME_MAX_LENGTH - 1) + "..." : name); if (overLength) { displayName = displayName.hover(name); } @@ -165,8 +166,7 @@ public void setOpen(boolean open) { } public int adjustPower(int adjustment) { - int maxPower = calculateMaxPower(); - int newPower = Math.min(Math.max(0, power + adjustment), maxPower); + int newPower = Math.min(Math.max(0, power + adjustment), calculateMaxPower()); int oldPower = this.power; if (newPower == oldPower) return 0; @@ -184,6 +184,7 @@ public List getClaims() { return Claim.getByFaction(id); } + @SuppressWarnings("all") public void removeAllClaims() { Claim.getByFaction(id) .stream() @@ -261,8 +262,11 @@ public static void save() { Database.save(Faction.class, STORE.values().stream().toList()); } -// TODO(samu): import per-player power patch public int calculateMaxPower(){ - return FactionsMod.CONFIG.POWER.BASE + (getUsers().size() * FactionsMod.CONFIG.POWER.MEMBER); + int maxPower = CONFIG.POWER.BASE; // + (faction.getMembers().size() * Config.MEMBER_POWER); + for (final User user : getUsers()) { + maxPower += user.getMaxPower(); + } + return maxPower; } } \ No newline at end of file diff --git a/src/main/java/io/icker/factions/api/persistents/User.java b/src/main/java/io/icker/factions/api/persistents/User.java index 5e01185f..ad866f48 100644 --- a/src/main/java/io/icker/factions/api/persistents/User.java +++ b/src/main/java/io/icker/factions/api/persistents/User.java @@ -4,6 +4,7 @@ import io.icker.factions.database.Database; import io.icker.factions.database.Field; import io.icker.factions.database.Name; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.HashMap; @@ -11,6 +12,9 @@ import java.util.UUID; import java.util.stream.Collectors; +import static io.icker.factions.FactionsMod.CONFIG; +import static io.icker.factions.util.PermissionUtil.getPermissionPower; + @Name("User") public class User { private static final HashMap STORE = Database.load(User.class, User::getID); @@ -44,6 +48,9 @@ public enum SoundMode { @Field("Rank") public Rank rank; +// @Field("Power") +// private int power = CONFIG.POWER.MEMBER + getPermissionPower(getID()); + @Field("Radar") public boolean radar = false; @@ -63,7 +70,8 @@ public User(UUID id) { this.id = id; } - public User() {} +// NOTE(CamperSamu): why does this exist?? +// public User() {} @SuppressWarnings("unused") public String getKey() { @@ -146,4 +154,40 @@ public static void save() { Database.save(User.class, STORE.values().stream().toList()); } + //region Power Management + public static int getMaxPower(final @NotNull UUID userUUID) { + final var user = get(userUUID); + return user != null ? user.getMaxPower() : 0; + } + + public int getMaxPower() { + return CONFIG.POWER.MEMBER + getPermissionPower(getID()); + } + +// public static int getPower(final @NotNull UUID userUUID) { +// return get(userUUID).getPower(); +// } + +// public int getPower() { +// return power; +// } + +// @SuppressWarnings("unused") +// public static void setPower(final @NotNull UUID userUUID, final int newPower) { +// get(userUUID).setPower(newPower); +// } + +// public void setPower(final int newPower) { +// power = newPower; +// } + +// @SuppressWarnings("unused") +// public static void addPower(final @NotNull UUID userUUID, final int powerModifier) { +// get(userUUID).addPower(powerModifier); +// } + +// public void addPower(final int powerModifier) { +// power += powerModifier; +// } + //endregion } \ No newline at end of file diff --git a/src/main/java/io/icker/factions/command/SettingsCommand.java b/src/main/java/io/icker/factions/command/SettingsCommand.java index 88f4e0fe..bbf204c0 100644 --- a/src/main/java/io/icker/factions/command/SettingsCommand.java +++ b/src/main/java/io/icker/factions/command/SettingsCommand.java @@ -1,9 +1,7 @@ package io.icker.factions.command; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; - import io.icker.factions.api.persistents.User; import io.icker.factions.util.Command; import io.icker.factions.util.Message; @@ -12,8 +10,10 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Formatting; +import static io.icker.factions.util.Command.Requires.hasPerms; + public class SettingsCommand implements Command{ - private int setChat(CommandContext context, User.ChatMode option) throws CommandSyntaxException { + private int setChat(CommandContext context, User.ChatMode option) { ServerPlayerEntity player = context.getSource().getPlayer(); User user = User.get(player.getUuid()); user.chat = option; @@ -45,7 +45,7 @@ private int setSounds(CommandContext context, User.SoundMod return 1; } - private int radar(CommandContext context) throws CommandSyntaxException { + private int radar(CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); @@ -67,22 +67,22 @@ private int radar(CommandContext context) throws CommandSyn public LiteralCommandNode getNode() { return CommandManager .literal("settings") - .requires(Requires.hasPerms("factions.settings", 0)) + .requires(hasPerms("factions.settings", 0)) .then( CommandManager.literal("chat") - .requires(Requires.hasPerms("factions.settings.chat", 0)) + .requires(hasPerms("factions.settings.chat", 0)) .then(CommandManager.literal("global").executes(context -> setChat(context, User.ChatMode.GLOBAL))) .then(CommandManager.literal("faction").executes(context -> setChat(context, User.ChatMode.FACTION))) .then(CommandManager.literal("focus").executes(context -> setChat(context, User.ChatMode.FOCUS))) ) .then( CommandManager.literal("radar") - .requires(Requires.hasPerms("factions.settings.radar", 0)) + .requires(hasPerms("factions.settings.radar", 0)) .executes(this::radar) ) .then( CommandManager.literal("sounds") - .requires(Requires.hasPerms("factions.settings.sounds", 0)) + .requires(hasPerms("factions.settings.sounds", 0)) .then(CommandManager.literal("none").executes(context -> setSounds(context, User.SoundMode.NONE))) .then(CommandManager.literal("warnings").executes(context -> setSounds(context, User.SoundMode.WARNINGS))) .then(CommandManager.literal("faction").executes(context -> setSounds(context, User.SoundMode.FACTION))) diff --git a/src/main/java/io/icker/factions/util/PermissionUtil.java b/src/main/java/io/icker/factions/util/PermissionUtil.java new file mode 100644 index 00000000..1ab4b753 --- /dev/null +++ b/src/main/java/io/icker/factions/util/PermissionUtil.java @@ -0,0 +1,37 @@ +package io.icker.factions.util; + +import net.luckperms.api.LuckPermsProvider; +import net.luckperms.api.model.group.Group; +import net.luckperms.api.node.Node; +import net.luckperms.api.query.QueryOptions; + +import java.util.UUID; + +public abstract class PermissionUtil { + public static int getPermissionPower(UUID uuid){ + int power = 0; + try { + + var user = LuckPermsProvider.get().getUserManager().getUser(uuid); + if (user == null) return 0; + for (Group inheritedGroup : user.getInheritedGroups(QueryOptions.nonContextual())) { + for (Node node : inheritedGroup.getNodes()) { + var perm = node.getKey(); + if (perm.contains("factions.power.modifier.")) { + int value = getNumberFromPermission(node.getKey()); + power+=value; + } + } + } + } catch (Exception ignored) {} + return power; + } + + public static int getNumberFromPermission(String permission) { + try { + return Integer.parseInt(permission.substring(permission.lastIndexOf(".")+1)); + } catch (Exception ignored) { + return 0; + } + } +} diff --git a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java index 4272c348..31091400 100644 --- a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java +++ b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java @@ -21,7 +21,8 @@ public class PlaceholdersWrapper { public static final Identifier FACTION_POWER_ID = new Identifier(MODID, "power"); public static final Identifier FACTION_POWER_FORMATTED_ID = new Identifier(MODID, "power_formatted"); public static final Identifier FACTION_MAX_POWER_ID = new Identifier(MODID, "max_power"); - public static final Identifier FACTION_PLAYER_POWER_ID = new Identifier(MODID, "player_power"); +// public static final Identifier FACTION_PLAYER_POWER_ID = new Identifier(MODID, "player_power"); + public static final Identifier FACTION_PLAYER_MAX_POWER_ID = new Identifier(MODID, "player_max_power"); public static final Identifier FACTION_REQUIRED_POWER_ID = new Identifier(MODID, "required_power"); public static final Identifier FACTION_REQUIRED_POWER_FORMATTED_ID = new Identifier(MODID, "required_power_formatted"); public static final String NULL_STRING = "N/A"; @@ -133,8 +134,29 @@ public static void init() { return value(r); }); - register(FACTION_PLAYER_POWER_ID, (ctx, argument) -> { - String r = "" + FactionsMod.CONFIG.POWER.MEMBER; +// register(FACTION_PLAYER_POWER_ID, (ctx, argument) -> { +// if (!ctx.hasPlayer()) return invalid("No Player!"); +// assert ctx.player() != null; +// +// final var member = User.get(ctx.player().getUuid()); +//// if (member == null) return value("" + User.getPower(ctx.player().getUuid())); +// if (member == null) return value("" + User.getMaxPower(ctx.player().getUuid())); +// +//// String r = "" + member.getPower(); +// String r = "" + member.getMaxPower(); +// +// return value(r); +// }); + + register(FACTION_PLAYER_MAX_POWER_ID, (ctx, argument) -> { + if (!ctx.hasPlayer()) return invalid("No Player!"); + assert ctx.player() != null; + + final var member = User.get(ctx.player().getUuid()); + if (member == null) return value("" + User.getMaxPower(ctx.player().getUuid())); + + String r = "" + member.getMaxPower(); + return value(r); }); From 62740048a04ad7ec23edb4be375a9273b21cf2e5 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Mon, 4 Jul 2022 02:01:17 +0200 Subject: [PATCH 02/20] Fix imports --- src/main/java/io/icker/factions/api/persistents/Faction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/icker/factions/api/persistents/Faction.java b/src/main/java/io/icker/factions/api/persistents/Faction.java index 304915e9..aa09d201 100644 --- a/src/main/java/io/icker/factions/api/persistents/Faction.java +++ b/src/main/java/io/icker/factions/api/persistents/Faction.java @@ -103,8 +103,8 @@ public String getName() { } public Message getTruncatedName() { - boolean overLength = FactionsMod.CONFIG.DISPLAY.NAME_MAX_LENGTH > -1 && name.length() > FactionsMod.CONFIG.DISPLAY.NAME_MAX_LENGTH; - Message displayName = new Message(overLength ? name.substring(0, FactionsMod.CONFIG.DISPLAY.NAME_MAX_LENGTH - 1) + "..." : name); + boolean overLength = CONFIG.DISPLAY.NAME_MAX_LENGTH > -1 && name.length() > CONFIG.DISPLAY.NAME_MAX_LENGTH; + Message displayName = new Message(overLength ? name.substring(0, CONFIG.DISPLAY.NAME_MAX_LENGTH - 1) + "..." : name); if (overLength) { displayName = displayName.hover(name); } From 384539b0497719e6f38b8ea45806ddc85dbc8af0 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Wed, 6 Jul 2022 20:11:13 +0200 Subject: [PATCH 03/20] This _should_ work, backing up. Signed-off-by: Camper_Samu --- .../factions/api/persistents/Faction.java | 107 ++++++++---------- .../icker/factions/api/persistents/User.java | 51 +++++---- .../icker/factions/command/AdminCommand.java | 52 +++++---- .../icker/factions/command/CreateCommand.java | 6 +- .../icker/factions/command/InfoCommand.java | 19 ++-- .../icker/factions/command/JoinCommand.java | 14 +-- .../icker/factions/command/LeaveCommand.java | 7 +- .../icker/factions/command/MemberCommand.java | 22 ++-- .../icker/factions/core/FactionsManager.java | 85 ++++++++------ .../java/io/icker/factions/util/Message.java | 10 +- .../java/io/icker/factions/util/Migrator.java | 26 ++--- .../factions/util/PlaceholdersWrapper.java | 26 ++--- 12 files changed, 214 insertions(+), 211 deletions(-) diff --git a/src/main/java/io/icker/factions/api/persistents/Faction.java b/src/main/java/io/icker/factions/api/persistents/Faction.java index 6f712770..793e61fc 100644 --- a/src/main/java/io/icker/factions/api/persistents/Faction.java +++ b/src/main/java/io/icker/factions/api/persistents/Faction.java @@ -6,6 +6,7 @@ import io.icker.factions.database.Name; import net.minecraft.inventory.SimpleInventory; import net.minecraft.util.Formatting; +import org.jetbrains.annotations.NotNull; import java.util.*; @@ -14,6 +15,8 @@ @Name("Faction") public class Faction { private static final HashMap STORE = Database.load(Faction.class, Faction::getID); + @Field("Invites") + public ArrayList invites = new ArrayList<>(); @Field("ID") private UUID id; @@ -33,36 +36,25 @@ public class Faction { @Field("Open") private boolean open; - @Field("Power") - private int power; - @Field("Home") private Home home; @Field("Safe") private SimpleInventory safe = new SimpleInventory(54); - @Field("Invites") - public ArrayList invites = new ArrayList<>(); - @Field("Relationships") private ArrayList relationships = new ArrayList<>(); - public Faction(String name, String description, String motd, Formatting color, boolean open, int power) { + public Faction(String name, String description, String motd, Formatting color, boolean open) { this.id = UUID.randomUUID(); this.name = name; this.motd = motd; this.description = description; this.color = color.getName(); this.open = open; - this.power = power; } - public Faction() {} - - @SuppressWarnings("unused") - public String getKey() { - return id.toString(); + public Faction() { } public static Faction get(UUID id) { @@ -71,10 +63,10 @@ public static Faction get(UUID id) { public static Faction getByName(String name) { return STORE.values() - .stream() - .filter(f -> f.name.equals(name)) - .findFirst() - .orElse(null); + .stream() + .filter(f -> f.name.equals(name)) + .findFirst() + .orElse(null); } public static void add(Faction faction) { @@ -88,9 +80,18 @@ public static Collection all() { @SuppressWarnings("unused") public static List allBut(UUID id) { return STORE.values() - .stream() - .filter(f -> f.id != id) - .toList(); + .stream() + .filter(f -> f.id != id) + .toList(); + } + + public static void save() { + Database.save(Faction.class, STORE.values().stream().toList()); + } + + @SuppressWarnings("unused") + public String getKey() { + return id.toString(); } public UUID getID() { @@ -101,20 +102,40 @@ public String getName() { return name; } + public void setName(String name) { + this.name = name; + FactionEvents.MODIFY.invoker().onModify(this); + } + public Formatting getColor() { return Formatting.byName(color); } + public void setColor(Formatting color) { + this.color = color.getName(); + FactionEvents.MODIFY.invoker().onModify(this); + } + public String getDescription() { return description; } + public void setDescription(String description) { + this.description = description; + FactionEvents.MODIFY.invoker().onModify(this); + } + public String getMOTD() { return motd; } + public void setMOTD(String motd) { + this.motd = motd; + FactionEvents.MODIFY.invoker().onModify(this); + } + public int getPower() { - return power; + return getUsers().stream().mapToInt(User::getPower).sum(); } public SimpleInventory getSafe() { @@ -130,42 +151,11 @@ public boolean isOpen() { return open; } - public void setName(String name) { - this.name = name; - FactionEvents.MODIFY.invoker().onModify(this); - } - - public void setDescription(String description) { - this.description = description; - FactionEvents.MODIFY.invoker().onModify(this); - } - - public void setMOTD(String motd) { - this.motd = motd; - FactionEvents.MODIFY.invoker().onModify(this); - } - - public void setColor(Formatting color) { - this.color = color.getName(); - FactionEvents.MODIFY.invoker().onModify(this); - } - public void setOpen(boolean open) { this.open = open; FactionEvents.MODIFY.invoker().onModify(this); } - public int adjustPower(int adjustment) { - int newPower = Math.min(Math.max(0, power + adjustment), calculateMaxPower()); - int oldPower = this.power; - - if (newPower == oldPower) return 0; - - power = newPower; - FactionEvents.POWER_CHANGE.invoker().onPowerChange(this, oldPower); - return Math.abs(newPower - oldPower); - } - public List getUsers() { return User.getByFaction(id); } @@ -174,11 +164,9 @@ public List getClaims() { return Claim.getByFaction(id); } - @SuppressWarnings("all") public void removeAllClaims() { Claim.getByFaction(id) - .stream() - .forEach(Claim::remove); + .forEach(Claim::remove); FactionEvents.REMOVE_ALL_CLAIMS.invoker().onRemoveAllClaims(this); } @@ -220,6 +208,7 @@ public List getEnemiesWith() { return relationships.stream().filter(rel -> rel.status == Relationship.Status.ENEMY).toList(); } + @SuppressWarnings("unused") //util public List getEnemiesOf() { return relationships.stream().filter(rel -> getReverse(rel).status == Relationship.Status.ENEMY).toList(); } @@ -228,7 +217,7 @@ public void removeRelationship(UUID target) { relationships = new ArrayList<>(relationships.stream().filter(rel -> !rel.target.equals(target)).toList()); } - public void setRelationship(Relationship relationship) { + public void setRelationship(@NotNull Relationship relationship) { if (getRelationship(relationship.target) != null) { removeRelationship(relationship.target); } @@ -248,11 +237,7 @@ public void remove() { FactionEvents.DISBAND.invoker().onDisband(this); } - public static void save() { - Database.save(Faction.class, STORE.values().stream().toList()); - } - - public int calculateMaxPower(){ + public int calculateMaxPower() { int maxPower = CONFIG.POWER.BASE; // + (faction.getMembers().size() * Config.MEMBER_POWER); for (final User user : getUsers()) { maxPower += user.getMaxPower(); diff --git a/src/main/java/io/icker/factions/api/persistents/User.java b/src/main/java/io/icker/factions/api/persistents/User.java index ad866f48..808ccd71 100644 --- a/src/main/java/io/icker/factions/api/persistents/User.java +++ b/src/main/java/io/icker/factions/api/persistents/User.java @@ -40,7 +40,7 @@ public enum SoundMode { } @Field("ID") - private UUID id; + private final UUID id; @Field("FactionID") private UUID factionID; @@ -48,9 +48,10 @@ public enum SoundMode { @Field("Rank") public Rank rank; -// @Field("Power") -// private int power = CONFIG.POWER.MEMBER + getPermissionPower(getID()); + @Field("Power") + private int power; +// NOTE(CamperSamu): This should be private and have getters and setters with events in the API @Field("Radar") public boolean radar = false; @@ -68,12 +69,13 @@ public enum SoundMode { public User(UUID id) { this.id = id; + power = getMaxPower(); } // NOTE(CamperSamu): why does this exist?? // public User() {} - @SuppressWarnings("unused") + @SuppressWarnings("unused") //util public String getKey() { return id.toString(); } @@ -96,6 +98,7 @@ public static void add(User user) { STORE.put(user.id, user); } +// NOTE(CamperSamu): Consider refactoring this to uuid(), following the record-like naming convention public UUID getID() { return id; } @@ -164,30 +167,30 @@ public int getMaxPower() { return CONFIG.POWER.MEMBER + getPermissionPower(getID()); } -// public static int getPower(final @NotNull UUID userUUID) { -// return get(userUUID).getPower(); -// } + public static int getPower(final @NotNull UUID userUUID) { + return get(userUUID).getPower(); + } -// public int getPower() { -// return power; -// } + public int getPower() { + return power; + } -// @SuppressWarnings("unused") -// public static void setPower(final @NotNull UUID userUUID, final int newPower) { -// get(userUUID).setPower(newPower); -// } + @SuppressWarnings("unused") //util + public static int setPower(final @NotNull UUID userUUID, final int newPower) { + return get(userUUID).setPower(newPower); + } -// public void setPower(final int newPower) { -// power = newPower; -// } + public int setPower(final int newPower) { + return power = newPower; + } -// @SuppressWarnings("unused") -// public static void addPower(final @NotNull UUID userUUID, final int powerModifier) { -// get(userUUID).addPower(powerModifier); -// } + @SuppressWarnings("unused") //util + public static int addPower(final @NotNull UUID userUUID, final int powerModifier) { + return get(userUUID).addPower(powerModifier); + } -// public void addPower(final int powerModifier) { -// power += powerModifier; -// } + public int addPower(final int powerModifier) { + return power += powerModifier; + } //endregion } \ No newline at end of file diff --git a/src/main/java/io/icker/factions/command/AdminCommand.java b/src/main/java/io/icker/factions/command/AdminCommand.java index 348652d1..1b6b19d8 100644 --- a/src/main/java/io/icker/factions/command/AdminCommand.java +++ b/src/main/java/io/icker/factions/command/AdminCommand.java @@ -1,13 +1,10 @@ package io.icker.factions.command; import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; - import io.icker.factions.FactionsMod; -import io.icker.factions.api.persistents.Faction; import io.icker.factions.api.persistents.User; import io.icker.factions.util.Command; import io.icker.factions.util.Message; @@ -15,47 +12,53 @@ import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Formatting; +import org.jetbrains.annotations.NotNull; + +import static io.icker.factions.api.persistents.User.get; +import static net.minecraft.text.Text.of; +import static net.minecraft.util.Formatting.GREEN; +import static net.minecraft.util.Formatting.RED; public class AdminCommand implements Command { - private int bypass(CommandContext context) throws CommandSyntaxException { + private int bypass(@NotNull CommandContext context) { ServerPlayerEntity player = context.getSource().getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute - User user = User.get(player.getUuid()); - boolean bypass = !user.bypass; - user.bypass = bypass; + User user = get(player.getUuid()); + user.bypass = !user.bypass; new Message("Successfully toggled claim bypass") .filler("ยท") .add( new Message(user.bypass ? "ON" : "OFF") - .format(user.bypass ? Formatting.GREEN : Formatting.RED) + .format(user.bypass ? GREEN : RED) ) .send(player, false); return 1; } - private int reload(CommandContext context) throws CommandSyntaxException { + private int reload(@NotNull CommandContext context) { FactionsMod.dynmap.reloadAll(); - new Message("Reloaded dynmap marker").send(context.getSource().getPlayer(), false); + context.getSource().sendFeedback(of("Reloaded dynmap marker"), true); //NOTE(CamperSamu): Avoid locking a reload command to be player-only, use the vanilla feedback function. return 1; } - private int power(CommandContext context) throws CommandSyntaxException { + private int power(@NotNull CommandContext context) throws CommandSyntaxException { ServerPlayerEntity player = context.getSource().getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute - Faction target = Faction.getByName(StringArgumentType.getString(context, "faction")); - int power = IntegerArgumentType.getInteger(context, "power"); + final User target = get(EntityArgumentType.getPlayer(context, "player").getUuid()); + final int power = IntegerArgumentType.getInteger(context, "power"); - int adjusted = target.adjustPower(power); + int adjusted = target.addPower(power); if (adjusted != 0) { if (power > 0) { new Message( "Admin %s added %d power", player.getName().getString(), adjusted - ).send(target); + ).send(player, false); new Message( "Added %d power", adjusted @@ -65,7 +68,7 @@ private int power(CommandContext context) throws CommandSyn "Admin %s removed %d power", player.getName().getString(), adjusted - ).send(target); + ).send(player, false); new Message( "Removed %d power", adjusted @@ -78,25 +81,27 @@ private int power(CommandContext context) throws CommandSyn return 1; } - private int spoof(CommandContext context) throws CommandSyntaxException { + private int spoof(@NotNull CommandContext context) throws CommandSyntaxException { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute - User user = User.get(player.getUuid()); + User user = get(player.getUuid()); ServerPlayerEntity targetEntity = EntityArgumentType.getPlayer(context, "player"); - User target = User.get(targetEntity.getUuid()); + User target = get(targetEntity.getUuid()); user.setSpoof(target); return 1; } - private int clearSpoof(CommandContext context) throws CommandSyntaxException { + private int clearSpoof(@NotNull CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute - User user = User.get(player.getUuid()); + User user = get(player.getUuid()); user.setSpoof(null); @@ -122,8 +127,7 @@ public LiteralCommandNode getNode() { .then( CommandManager.argument("power", IntegerArgumentType.integer()) .then( - CommandManager.argument("faction", StringArgumentType.greedyString()) - .suggests(Suggests.allFactions()) + CommandManager.argument("player", EntityArgumentType.player()) .executes(this::power) ) ) diff --git a/src/main/java/io/icker/factions/command/CreateCommand.java b/src/main/java/io/icker/factions/command/CreateCommand.java index bb44581a..2982542c 100644 --- a/src/main/java/io/icker/factions/command/CreateCommand.java +++ b/src/main/java/io/icker/factions/command/CreateCommand.java @@ -2,7 +2,6 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; import io.icker.factions.FactionsMod; import io.icker.factions.api.persistents.Faction; @@ -17,11 +16,12 @@ import java.util.Locale; public class CreateCommand implements Command { - private int run(CommandContext context) throws CommandSyntaxException { + private int run(CommandContext context) { String name = StringArgumentType.getString(context, "name"); ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute if (FactionsMod.CONFIG.DISPLAY.NAME_BLACKLIST.contains(name.toLowerCase(Locale.ROOT))) { new Message("Cannot create a faction with this name as it is on the blacklist").fail().send(player, false); @@ -38,7 +38,7 @@ private int run(CommandContext context) throws CommandSynta return 0; } - Faction faction = new Faction(name, "No description set", "No faction MOTD set", Formatting.WHITE, false, FactionsMod.CONFIG.POWER.BASE + FactionsMod.CONFIG.POWER.MEMBER); + Faction faction = new Faction(name, "No description set", "No faction MOTD set", Formatting.WHITE, false); Faction.add(faction); Command.getUser(player).joinFaction(faction.getID(), User.Rank.OWNER); diff --git a/src/main/java/io/icker/factions/command/InfoCommand.java b/src/main/java/io/icker/factions/command/InfoCommand.java index 5938c5a0..1b61d2c1 100644 --- a/src/main/java/io/icker/factions/command/InfoCommand.java +++ b/src/main/java/io/icker/factions/command/InfoCommand.java @@ -3,7 +3,6 @@ import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; import io.icker.factions.FactionsMod; import io.icker.factions.api.persistents.Faction; @@ -21,9 +20,10 @@ import java.util.stream.Collectors; public class InfoCommand implements Command { - private int self(CommandContext context) throws CommandSyntaxException { + private int self(CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute User user = Command.getUser(player); if (!user.isInFaction()) { @@ -34,11 +34,12 @@ private int self(CommandContext context) throws CommandSynt return info(player, user.getFaction()); } - private int any(CommandContext context) throws CommandSyntaxException { + private int any(CommandContext context) { String factionName = StringArgumentType.getString(context, "faction"); ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute Faction faction = Faction.getByName(factionName); if (faction == null) { @@ -52,7 +53,9 @@ private int any(CommandContext context) throws CommandSynta public static int info(ServerPlayerEntity player, Faction faction) { List users = faction.getUsers(); + if (player.getServer() == null) return -1; UserCache cache = player.getServer().getUserCache(); + String owner = Formatting.WHITE + users.stream() .filter(u -> u.rank == User.Rank.OWNER) @@ -78,12 +81,10 @@ public static int info(ServerPlayerEntity player, Faction faction) { // generate the --- int totalChars = 32; - String dashes = ""; - for (int i = 0; i < (totalChars - faction.getName().length()) / 2; i++) { - dashes += "-"; - } + StringBuilder dashes = new StringBuilder(); + dashes.append("-".repeat(Math.max(0, (totalChars - faction.getName().length()) / 2))); - new Message(Formatting.BLACK + dashes + "[ " + faction.getColor() + faction.getName() + Formatting.BLACK + " ]" + dashes) + new Message(Formatting.BLACK + dashes.toString() + "[ " + faction.getColor() + faction.getName() + Formatting.BLACK + " ]" + dashes) .send(player, false); new Message(Formatting.GOLD + "Description: ") .add(Formatting.WHITE + faction.getDescription()) @@ -91,7 +92,7 @@ public static int info(ServerPlayerEntity player, Faction faction) { new Message(Formatting.GOLD + "Owner: ") .add(Formatting.WHITE + owner) .send(player, false); - new Message(Formatting.GOLD + "Members (" + Formatting.WHITE.toString() + users.size() + Formatting.GOLD.toString() + "): ") + new Message(Formatting.GOLD + "Members (" + Formatting.WHITE + users.size() + Formatting.GOLD + "): ") .add(usersList) .send(player, false); new Message(Formatting.GOLD + "Power: ") diff --git a/src/main/java/io/icker/factions/command/JoinCommand.java b/src/main/java/io/icker/factions/command/JoinCommand.java index 2b93237a..bf0f1b14 100644 --- a/src/main/java/io/icker/factions/command/JoinCommand.java +++ b/src/main/java/io/icker/factions/command/JoinCommand.java @@ -2,22 +2,23 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; -import io.icker.factions.FactionsMod; import io.icker.factions.api.persistents.Faction; -import io.icker.factions.api.persistents.User; import io.icker.factions.util.Command; import io.icker.factions.util.Message; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; +import static io.icker.factions.FactionsMod.CONFIG; +import static io.icker.factions.api.persistents.User.Rank.MEMBER; + public class JoinCommand implements Command { - private int run(CommandContext context) throws CommandSyntaxException { + private int run(CommandContext context) { String name = StringArgumentType.getString(context, "name"); ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute Faction faction = Faction.getByName(name); @@ -33,17 +34,16 @@ private int run(CommandContext context) throws CommandSynta return 0; } - if (FactionsMod.CONFIG.MAX_FACTION_SIZE != -1 && faction.getUsers().size() >= FactionsMod.CONFIG.MAX_FACTION_SIZE) { + if (CONFIG.MAX_FACTION_SIZE != -1 && faction.getUsers().size() >= CONFIG.MAX_FACTION_SIZE) { new Message("Cannot join faction as it is currently full").fail().send(player, false); return 0; } if (invited) faction.invites.remove(player.getUuid()); - Command.getUser(player).joinFaction(faction.getID(), User.Rank.MEMBER); + Command.getUser(player).joinFaction(faction.getID(), MEMBER); source.getServer().getPlayerManager().sendCommandTree(player); new Message(player.getName().getString() + " joined").send(faction); - faction.adjustPower(FactionsMod.CONFIG.POWER.MEMBER); return 1; } diff --git a/src/main/java/io/icker/factions/command/LeaveCommand.java b/src/main/java/io/icker/factions/command/LeaveCommand.java index 3863e36c..cd200c4a 100644 --- a/src/main/java/io/icker/factions/command/LeaveCommand.java +++ b/src/main/java/io/icker/factions/command/LeaveCommand.java @@ -1,9 +1,7 @@ package io.icker.factions.command; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; -import io.icker.factions.FactionsMod; import io.icker.factions.api.persistents.Faction; import io.icker.factions.api.persistents.User; import io.icker.factions.util.Command; @@ -13,9 +11,10 @@ import net.minecraft.server.network.ServerPlayerEntity; public class LeaveCommand implements Command { - private int run(CommandContext context) throws CommandSyntaxException { + private int run(CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute User user = Command.getUser(player); Faction faction = user.getFaction(); @@ -30,8 +29,6 @@ private int run(CommandContext context) throws CommandSynta if (faction.getUsers().size() == 0) { faction.remove(); - } else { - faction.adjustPower(-FactionsMod.CONFIG.POWER.MEMBER); } return 1; diff --git a/src/main/java/io/icker/factions/command/MemberCommand.java b/src/main/java/io/icker/factions/command/MemberCommand.java index 9deb31e7..1b169a5a 100644 --- a/src/main/java/io/icker/factions/command/MemberCommand.java +++ b/src/main/java/io/icker/factions/command/MemberCommand.java @@ -3,7 +3,6 @@ import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; import io.icker.factions.api.persistents.Faction; import io.icker.factions.api.persistents.User; @@ -20,9 +19,10 @@ import java.util.stream.Collectors; public class MemberCommand implements Command { - private int self(CommandContext context) throws CommandSyntaxException { + private int self(CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute User user = Command.getUser(player); if (!user.isInFaction()) { @@ -33,11 +33,12 @@ private int self(CommandContext context) throws CommandSynt return members(player, user.getFaction()); } - private int any(CommandContext context) throws CommandSyntaxException { + private int any(CommandContext context) { String factionName = StringArgumentType.getString(context, "faction"); ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute Faction faction = Faction.getByName(factionName); if (faction == null) { @@ -50,6 +51,7 @@ private int any(CommandContext context) throws CommandSynta public static int members(ServerPlayerEntity player, Faction faction) { List users = faction.getUsers(); + if (player.getServer() == null) return -1; UserCache cache = player.getServer().getUserCache(); long memberCount = users.stream().filter(u -> u.rank == User.Rank.MEMBER).count(); @@ -81,12 +83,10 @@ public static int members(ServerPlayerEntity player, Faction faction) { // generate the --- int totalChars = 32; - String dashes = ""; - for (int i = 0; i < (totalChars - faction.getName().length()) / 2; i++) { - dashes += "-"; - } + StringBuilder dashes = new StringBuilder(); + dashes.append("-".repeat(Math.max(0, (totalChars - faction.getName().length()) / 2))); - new Message(Formatting.BLACK + dashes + "[ " + faction.getColor() + faction.getName() + Formatting.BLACK + " ]" + dashes) + new Message(Formatting.BLACK + dashes.toString() + "[ " + faction.getColor() + faction.getName() + Formatting.BLACK + " ]" + dashes) .send(player, false); new Message(Formatting.GOLD + "Total Members: ") .add(Formatting.WHITE.toString() + users.size()) @@ -94,13 +94,13 @@ public static int members(ServerPlayerEntity player, Faction faction) { new Message(Formatting.GOLD + "Owner: ") .add(owner) .send(player, false); - new Message(Formatting.GOLD + "Leaders (" + Formatting.WHITE.toString() + leaderCount + Formatting.GOLD.toString() + "): ") + new Message(Formatting.GOLD + "Leaders (" + Formatting.WHITE + leaderCount + Formatting.GOLD + "): ") .add(leaders) .send(player, false); - new Message(Formatting.GOLD + "Commanders (" + Formatting.WHITE.toString() + commanderCount + Formatting.GOLD.toString() + "): ") + new Message(Formatting.GOLD + "Commanders (" + Formatting.WHITE + commanderCount + Formatting.GOLD + "): ") .add(commanders) .send(player, false); - new Message(Formatting.GOLD + "Members (" + Formatting.WHITE.toString() + memberCount + Formatting.GOLD.toString() + "): ") + new Message(Formatting.GOLD + "Members (" + Formatting.WHITE + memberCount + Formatting.GOLD + "): ") .add(members) .send(player, false); diff --git a/src/main/java/io/icker/factions/core/FactionsManager.java b/src/main/java/io/icker/factions/core/FactionsManager.java index 5eac8ef4..9d758ae8 100644 --- a/src/main/java/io/icker/factions/core/FactionsManager.java +++ b/src/main/java/io/icker/factions/core/FactionsManager.java @@ -1,6 +1,5 @@ package io.icker.factions.core; -import io.icker.factions.FactionsMod; import io.icker.factions.api.events.FactionEvents; import io.icker.factions.api.events.PlayerEvents; import io.icker.factions.api.persistents.Faction; @@ -15,11 +14,23 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +import static io.icker.factions.FactionsMod.CONFIG; +import static java.lang.String.format; public class FactionsManager { + //region Constants + public static final String + POWER_LOST_MESSAGE = "%s lost %d power from dying", + POWER_GAINED_MESSAGE = "%s gained %d power from surviving"; public static PlayerManager playerManager; + //endregion public static void register() { ServerLifecycleEvents.SERVER_STARTED.register(FactionsManager::serverStarted); @@ -38,10 +49,10 @@ private static void serverStarted(MinecraftServer server) { private static void factionModified(Faction faction) { ServerPlayerEntity[] players = faction.getUsers() - .stream() - .map(user -> playerManager.getPlayer(user.getID())) - .filter(player -> player != null) - .toArray(ServerPlayerEntity[]::new); + .stream() + .map(user -> playerManager.getPlayer(user.getID())) + .filter(Objects::nonNull) + .toArray(ServerPlayerEntity[]::new); updatePlayerList(players); } @@ -52,44 +63,44 @@ private static void memberChange(Faction faction, User user) { } } - private static void playerDeath(ServerPlayerEntity player, DamageSource source) { + private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource source) { User member = User.get(player.getUuid()); - if (!member.isInFaction()) return; + int adjusted = member.addPower(-CONFIG.POWER.POWER_TICKS.DEATH_PENALTY); - Faction faction = member.getFaction(); + final MutableText message = Text.literal(format(POWER_LOST_MESSAGE, player.getName().getString(), adjusted)); - int adjusted = faction.adjustPower(-FactionsMod.CONFIG.POWER.POWER_TICKS.DEATH_PENALTY); - new Message( - "%s lost %d power from dying", - player.getName().getString(), - adjusted - ).send(faction); + if (member.isInFaction()) { + final Faction faction = member.getFaction(); + new Message(message).send(faction); + } else { + player.sendMessage(message); + } } - private static void powerTick(ServerPlayerEntity player) { + private static void powerTick(@NotNull ServerPlayerEntity player) { User member = User.get(player.getUuid()); - if (!member.isInFaction()) return; + if (member.getPower() == member.getMaxPower()) return; + int adjusted = member.addPower(CONFIG.POWER.POWER_TICKS.REWARD); - Faction faction = member.getFaction(); + final MutableText message = Text.literal(format(POWER_GAINED_MESSAGE, player.getName().getString(), adjusted)); - int adjusted = faction.adjustPower(FactionsMod.CONFIG.POWER.POWER_TICKS.REWARD); - if (adjusted != 0) - new Message( - "%s gained %d power from surviving", - player.getName().getString(), - adjusted - ).send(faction); + if (member.isInFaction()) { + final Faction faction = member.getFaction(); + new Message(message).send(faction); + } else { + player.sendMessage(message); + } } - private static void updatePlayerList(ServerPlayerEntity ...players) { + private static void updatePlayerList(ServerPlayerEntity... players) { playerManager.sendToAll(new PlayerListS2CPacket(PlayerListS2CPacket.Action.UPDATE_DISPLAY_NAME, players)); } private static ActionResult openSafe(PlayerEntity player, Faction faction) { - User user = User.get(player.getUuid()); + User user = User.get(player.getUuid()); if (!user.isInFaction()) { - if (FactionsMod.CONFIG.SAFE != null && FactionsMod.CONFIG.SAFE.ENDER_CHEST) { + if (CONFIG.SAFE != null && CONFIG.SAFE.ENDER_CHEST) { new Message("Cannot use enderchests when not in a faction").fail().send(player, false); return ActionResult.FAIL; } @@ -97,16 +108,16 @@ private static ActionResult openSafe(PlayerEntity player, Faction faction) { } player.openHandledScreen( - new SimpleNamedScreenHandlerFactory( - (syncId, inventory, p) -> { - if (FactionsMod.CONFIG.SAFE.DOUBLE) { - return GenericContainerScreenHandler.createGeneric9x6(syncId, inventory, faction.getSafe()); - } else { - return GenericContainerScreenHandler.createGeneric9x3(syncId, inventory, faction.getSafe()); - } - }, - Text.of(String.format("%s's Safe", faction.getName())) - ) + new SimpleNamedScreenHandlerFactory( + (syncId, inventory, p) -> { + if (CONFIG.SAFE.DOUBLE) { + return GenericContainerScreenHandler.createGeneric9x6(syncId, inventory, faction.getSafe()); + } else { + return GenericContainerScreenHandler.createGeneric9x3(syncId, inventory, faction.getSafe()); + } + }, + Text.of(format("%s's Safe", faction.getName())) + ) ); return ActionResult.SUCCESS; diff --git a/src/main/java/io/icker/factions/util/Message.java b/src/main/java/io/icker/factions/util/Message.java index cffc35cd..8502c0f9 100644 --- a/src/main/java/io/icker/factions/util/Message.java +++ b/src/main/java/io/icker/factions/util/Message.java @@ -10,6 +10,7 @@ import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import org.jetbrains.annotations.NotNull; public class Message { public static PlayerManager manager; @@ -19,6 +20,10 @@ public Message(String message) { text = (MutableText) Text.of(message); } + public Message(MutableText message) { + text = message; + } + public Message(String message, Object... args) { text = (MutableText) Text.of(String.format(message, args)); } @@ -72,6 +77,7 @@ public Message send(Faction faction) { return this; } + @SuppressWarnings("unused") //util public void sendToGlobalChat() { for (ServerPlayerEntity player : manager.getPlayerList()) { User.ChatMode option = User.get(player.getUuid()).chat; @@ -79,9 +85,11 @@ public void sendToGlobalChat() { } } - public void sendToFactionChat(Faction faction) { + @SuppressWarnings("unused") //util + public void sendToFactionChat(@NotNull Faction faction) { for (User member : faction.getUsers()) { ServerPlayerEntity player = manager.getPlayer(member.getID()); + if (player == null) return; // Confirm that it's a player executing the command and not an entity with /execute player.sendMessage(text, false); } } diff --git a/src/main/java/io/icker/factions/util/Migrator.java b/src/main/java/io/icker/factions/util/Migrator.java index fc9a9bdc..58763069 100644 --- a/src/main/java/io/icker/factions/util/Migrator.java +++ b/src/main/java/io/icker/factions/util/Migrator.java @@ -1,23 +1,19 @@ package io.icker.factions.util; +import io.icker.factions.FactionsMod; +import io.icker.factions.api.persistents.*; +import net.minecraft.util.Formatting; + import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; +import java.sql.*; import java.util.UUID; -import io.icker.factions.FactionsMod; -import io.icker.factions.api.persistents.Claim; -import io.icker.factions.api.persistents.Faction; -import io.icker.factions.api.persistents.Home; -import io.icker.factions.api.persistents.Relationship; -import io.icker.factions.api.persistents.User; -import net.minecraft.util.Formatting; +import static java.util.Objects.requireNonNull; public class Migrator { public static Connection con; + + @SuppressWarnings("ResultOfMethodCallIgnored") public static void migrate() { File file = new File("./factions/factions.mv.db"); if (file.isFile()) { @@ -33,7 +29,7 @@ private static void moveData() { Query query = new Query("SELECT * FROM Faction;").executeQuery(); while (query.next()) { - Faction faction = new Faction(query.getString("name"), query.getString("description"), "No faction MOTD set", Formatting.byName(query.getString("color")), query.getBool("open"), query.getInt("power")); + Faction faction = new Faction(query.getString("name"), query.getString("description"), "No faction MOTD set", requireNonNull(Formatting.byName(query.getString("color"))), query.getBool("open")); Faction.add(faction); Query homeQuery = new Query("SELECT * FROM Home WHERE faction = ?;").set(faction.getName()).executeQuery(); @@ -58,7 +54,7 @@ private static void moveData() { while (query.next()) { OldRank rank; try { - rank = Enum.valueOf(OldRank.class, query.getString("rank")); + rank = Enum.valueOf(OldRank.class, requireNonNull(query.getString("rank"))); } catch (IllegalArgumentException e) { rank = OldRank.CIVILIAN; } @@ -72,7 +68,7 @@ private static void moveData() { while (query.next()) { User.ChatMode opt; try { - opt = Enum.valueOf(User.ChatMode.class, query.getString("chat")); + opt = Enum.valueOf(User.ChatMode.class, requireNonNull(query.getString("chat"))); } catch (IllegalArgumentException e) { opt = User.ChatMode.GLOBAL; } diff --git a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java index b37c7833..4329d8a5 100644 --- a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java +++ b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java @@ -22,7 +22,7 @@ public class PlaceholdersWrapper { public static final Identifier FACTION_POWER_ID = new Identifier(MODID, "power"); public static final Identifier FACTION_POWER_FORMATTED_ID = new Identifier(MODID, "power_formatted"); public static final Identifier FACTION_MAX_POWER_ID = new Identifier(MODID, "max_power"); -// public static final Identifier FACTION_PLAYER_POWER_ID = new Identifier(MODID, "player_power"); + public static final Identifier FACTION_PLAYER_POWER_ID = new Identifier(MODID, "player_power"); public static final Identifier FACTION_PLAYER_MAX_POWER_ID = new Identifier(MODID, "player_max_power"); public static final Identifier FACTION_REQUIRED_POWER_ID = new Identifier(MODID, "required_power"); public static final Identifier FACTION_REQUIRED_POWER_FORMATTED_ID = new Identifier(MODID, "required_power_formatted"); @@ -149,19 +149,17 @@ public static void init() { return value(r); }); -// register(FACTION_PLAYER_POWER_ID, (ctx, argument) -> { -// if (!ctx.hasPlayer()) return invalid("No Player!"); -// assert ctx.player() != null; -// -// final var member = User.get(ctx.player().getUuid()); -//// if (member == null) return value("" + User.getPower(ctx.player().getUuid())); -// if (member == null) return value("" + User.getMaxPower(ctx.player().getUuid())); -// -//// String r = "" + member.getPower(); -// String r = "" + member.getMaxPower(); -// -// return value(r); -// }); + register(FACTION_PLAYER_POWER_ID, (ctx, argument) -> { + if (!ctx.hasPlayer()) return invalid("No Player!"); + assert ctx.player() != null; + + final var member = User.get(ctx.player().getUuid()); + if (member == null) return value("" + User.getPower(ctx.player().getUuid())); + + String r = "" + member.getPower(); + + return value(r); + }); register(FACTION_PLAYER_MAX_POWER_ID, (ctx, argument) -> { if (!ctx.hasPlayer()) return invalid("No Player!"); From 97cfd5d050e73396d6678d730fce3fed994350d0 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Wed, 6 Jul 2022 20:40:36 +0200 Subject: [PATCH 04/20] Remove base power pt.1 Signed-off-by: Camper_Samu --- src/main/java/io/icker/factions/api/persistents/Faction.java | 5 ++--- src/main/java/io/icker/factions/util/PermissionUtil.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/icker/factions/api/persistents/Faction.java b/src/main/java/io/icker/factions/api/persistents/Faction.java index 793e61fc..58aa9986 100644 --- a/src/main/java/io/icker/factions/api/persistents/Faction.java +++ b/src/main/java/io/icker/factions/api/persistents/Faction.java @@ -10,8 +10,6 @@ import java.util.*; -import static io.icker.factions.FactionsMod.CONFIG; - @Name("Faction") public class Faction { private static final HashMap STORE = Database.load(Faction.class, Faction::getID); @@ -238,7 +236,8 @@ public void remove() { } public int calculateMaxPower() { - int maxPower = CONFIG.POWER.BASE; // + (faction.getMembers().size() * Config.MEMBER_POWER); + //we need to remove base power otherwise is problematic + int maxPower = 0; //CONFIG.POWER.BASE; // + (faction.getMembers().size() * Config.MEMBER_POWER); for (final User user : getUsers()) { maxPower += user.getMaxPower(); } diff --git a/src/main/java/io/icker/factions/util/PermissionUtil.java b/src/main/java/io/icker/factions/util/PermissionUtil.java index 1ab4b753..edd4bf6b 100644 --- a/src/main/java/io/icker/factions/util/PermissionUtil.java +++ b/src/main/java/io/icker/factions/util/PermissionUtil.java @@ -23,7 +23,7 @@ public static int getPermissionPower(UUID uuid){ } } } - } catch (Exception ignored) {} + } catch (NoClassDefFoundError | Exception ignored) {} return power; } From 09790d6fc64296251962d1e2edd9bfefdf79daab Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 18:16:42 +0200 Subject: [PATCH 05/20] fix power Signed-off-by: Camper_Samu --- src/main/java/io/icker/factions/core/FactionsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/icker/factions/core/FactionsManager.java b/src/main/java/io/icker/factions/core/FactionsManager.java index 648c37aa..fe32affb 100644 --- a/src/main/java/io/icker/factions/core/FactionsManager.java +++ b/src/main/java/io/icker/factions/core/FactionsManager.java @@ -65,7 +65,7 @@ private static void memberChange(Faction faction, User user) { private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource source) { User member = User.get(player.getUuid()); - int adjusted = member.addPower(-CONFIG.POWER.POWER.DEATH_PENALTY); + int adjusted = member.addPower(-CONFIG.POWER.DEATH_PENALTY); final MutableText message = Text.literal(format(POWER_LOST_MESSAGE, player.getName().getString(), adjusted)); From 7bb9da6b98458b17763cacb04ccfc24a455856d6 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 18:18:29 +0200 Subject: [PATCH 06/20] forgor a null check Signed-off-by: Camper_Samu --- src/main/java/io/icker/factions/core/FactionsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/icker/factions/core/FactionsManager.java b/src/main/java/io/icker/factions/core/FactionsManager.java index fe32affb..572e1ad1 100644 --- a/src/main/java/io/icker/factions/core/FactionsManager.java +++ b/src/main/java/io/icker/factions/core/FactionsManager.java @@ -110,7 +110,7 @@ private static ActionResult openSafe(PlayerEntity player, Faction faction) { player.openHandledScreen( new SimpleNamedScreenHandlerFactory( (syncId, inventory, p) -> { - if (CONFIG.SAFE.DOUBLE) { + if (CONFIG.SAFE != null && CONFIG.SAFE.DOUBLE) { return GenericContainerScreenHandler.createGeneric9x6(syncId, inventory, faction.getSafe()); } else { return GenericContainerScreenHandler.createGeneric9x3(syncId, inventory, faction.getSafe()); From 1f116a80f9c76d9414b30f0b727792a1f5ae13e3 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 18:34:26 +0200 Subject: [PATCH 07/20] Removed Base Power (commented out), added Faction#calculateRequiredPower to prevent code duplication and missed formula changes (also this will allow for custom formulas in the future), NPE proofing in various commands and a bit of code annotation. Signed-off-by: Camper_Samu --- .../factions/api/persistents/Faction.java | 7 ++- .../icker/factions/command/ClaimCommand.java | 44 +++++++++++-------- .../icker/factions/command/InfoCommand.java | 5 +-- .../io/icker/factions/config/PowerConfig.java | 8 ++-- .../io/icker/factions/core/WorldManager.java | 3 +- 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/main/java/io/icker/factions/api/persistents/Faction.java b/src/main/java/io/icker/factions/api/persistents/Faction.java index 434ee457..acc603ca 100644 --- a/src/main/java/io/icker/factions/api/persistents/Faction.java +++ b/src/main/java/io/icker/factions/api/persistents/Faction.java @@ -1,5 +1,6 @@ package io.icker.factions.api.persistents; +import io.icker.factions.FactionsMod; import io.icker.factions.api.events.FactionEvents; import io.icker.factions.database.Database; import io.icker.factions.database.Field; @@ -240,10 +241,14 @@ public void remove() { public int calculateMaxPower() { //we need to remove base power otherwise is problematic - int maxPower = 0; //CONFIG.POWER.BASE; // + (faction.getMembers().size() * Config.MEMBER_POWER); + int maxPower = 0; for (final User user : getUsers()) { maxPower += user.getMaxPower(); } return maxPower; } + + public int calculateRequiredPower(){ + return (getClaims().size() + 1) * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; + } } \ No newline at end of file diff --git a/src/main/java/io/icker/factions/command/ClaimCommand.java b/src/main/java/io/icker/factions/command/ClaimCommand.java index bb2a49e2..51dde781 100644 --- a/src/main/java/io/icker/factions/command/ClaimCommand.java +++ b/src/main/java/io/icker/factions/command/ClaimCommand.java @@ -2,7 +2,6 @@ import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; import io.icker.factions.FactionsMod; import io.icker.factions.api.persistents.Claim; @@ -16,6 +15,7 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Formatting; import net.minecraft.util.math.ChunkPos; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -24,9 +24,10 @@ import java.util.stream.Collectors; public class ClaimCommand implements Command { - private int list(CommandContext context) throws CommandSyntaxException { + private int list(@NotNull CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute List claims = Command.getUser(player).getFaction().getClaims(); int count = claims.size(); @@ -38,10 +39,10 @@ private int list(CommandContext context) throws CommandSynt if (count == 0) return 1; - HashMap> claimsMap = new HashMap>(); + HashMap> claimsMap = new HashMap<>(); claims.forEach(claim -> { - claimsMap.putIfAbsent(claim.level, new ArrayList()); + claimsMap.putIfAbsent(claim.level, new ArrayList<>()); claimsMap.get(claim.level).add(claim); }); @@ -64,15 +65,16 @@ private int list(CommandContext context) throws CommandSynt return 1; } - private int addForced(CommandContext context, int size) throws CommandSyntaxException { + private int addForced(@NotNull CommandContext context, int size) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute ServerWorld world = player.getWorld(); Faction faction = Command.getUser(player).getFaction(); String dimension = world.getRegistryKey().getValue().toString(); - ArrayList chunks = new ArrayList(); + ArrayList chunks = new ArrayList<>(); for (int x = -size + 1; x < size; x++) { for (int y = -size + 1; y < size; y++) { @@ -116,12 +118,13 @@ private int addForced(CommandContext context, int size) thr return 1; } - private int add(CommandContext context) throws CommandSyntaxException { + private int add(@NotNull CommandContext context) { ServerPlayerEntity player = context.getSource().getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute Faction faction = Command.getUser(player).getFaction(); int requiredPower = (faction.getClaims().size() + 1) * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; - int maxPower = faction.getUsers().size() * FactionsMod.CONFIG.POWER.MEMBER + FactionsMod.CONFIG.POWER.BASE; + int maxPower = faction.calculateMaxPower(); if (maxPower < requiredPower) { new Message("Not enough faction power to claim chunk").fail().send(player, false); @@ -131,15 +134,15 @@ private int add(CommandContext context) throws CommandSynta return addForced(context, 1); } - private int addSize(CommandContext context) throws CommandSyntaxException { - int size = IntegerArgumentType.getInteger(context, "size"); + private int addSize(CommandContext context) { + final int size = IntegerArgumentType.getInteger(context, "size"); ServerPlayerEntity player = context.getSource().getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute Faction faction = Command.getUser(player).getFaction(); - int requiredPower = (faction.getClaims().size() + 1) * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; - int maxPower = faction.getUsers().size() * FactionsMod.CONFIG.POWER.MEMBER + FactionsMod.CONFIG.POWER.BASE; + final int requiredPower = (faction.getClaims().size() + 1) * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; - if (maxPower < requiredPower) { + if (faction.calculateMaxPower() < requiredPower) { new Message("Not enough faction power to claim chunks").fail().send(player, false); return 0; } @@ -147,10 +150,11 @@ private int addSize(CommandContext context) throws CommandS return addForced(context, size); } - private int remove(CommandContext context) throws CommandSyntaxException { + private int remove(@NotNull CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute ServerWorld world = player.getWorld(); ChunkPos chunkPos = world.getChunk(player.getBlockPos()).getPos(); @@ -185,11 +189,12 @@ private int remove(CommandContext context) throws CommandSy return 1; } - private int removeSize(CommandContext context) throws CommandSyntaxException { + private int removeSize(CommandContext context) { int size = IntegerArgumentType.getInteger(context, "size"); ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute ServerWorld world = player.getWorld(); String dimension = world.getRegistryKey().getValue().toString(); @@ -218,9 +223,10 @@ private int removeSize(CommandContext context) throws Comma return 1; } - private int removeAll(CommandContext context) throws CommandSyntaxException { + private int removeAll(@NotNull CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute Faction faction = Command.getUser(player).getFaction(); @@ -232,9 +238,10 @@ private int removeAll(CommandContext context) throws Comman return 1; } - private int auto(CommandContext context) throws CommandSyntaxException { + private int auto(@NotNull CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute User user = Command.getUser(player); user.autoclaim = !user.autoclaim; @@ -251,10 +258,11 @@ private int auto(CommandContext context) throws CommandSynt } @SuppressWarnings("") - private int setAccessLevel(CommandContext context, boolean increase) throws CommandSyntaxException { + private int setAccessLevel(@NotNull CommandContext context, boolean increase) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); + if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute ServerWorld world = player.getWorld(); ChunkPos chunkPos = world.getChunk(player.getBlockPos()).getPos(); diff --git a/src/main/java/io/icker/factions/command/InfoCommand.java b/src/main/java/io/icker/factions/command/InfoCommand.java index 94b3f7dc..5e9ce37c 100644 --- a/src/main/java/io/icker/factions/command/InfoCommand.java +++ b/src/main/java/io/icker/factions/command/InfoCommand.java @@ -77,13 +77,12 @@ public static int info(ServerPlayerEntity player, Faction faction) { .collect(Collectors.joining(Formatting.GRAY + ", ")); int requiredPower = faction.getClaims().size() * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; - int maxPower = users.size() * FactionsMod.CONFIG.POWER.MEMBER + FactionsMod.CONFIG.POWER.BASE; // generate the --- int numDashes = 32 - faction.getName().length(); String dashes = new StringBuilder("--------------------------------").substring(0, numDashes/2); - new Message(Formatting.BLACK + dashes.toString() + "[ " + faction.getColor() + faction.getName() + Formatting.BLACK + " ]" + dashes) + new Message(Formatting.BLACK + dashes + "[ " + faction.getColor() + faction.getName() + Formatting.BLACK + " ]" + dashes) .send(player, false); new Message(Formatting.GOLD + "Description: ") .add(Formatting.WHITE + faction.getDescription()) @@ -95,7 +94,7 @@ public static int info(ServerPlayerEntity player, Faction faction) { .add(usersList) .send(player, false); new Message(Formatting.GOLD + "Power: ") - .add(Formatting.GREEN.toString() + faction.getPower() + slash() + requiredPower + slash() + maxPower) + .add(Formatting.GREEN.toString() + faction.getPower() + slash() + requiredPower + slash() + faction.calculateMaxPower()) .hover("Current / Required / Max") .send(player, false); new Message(Formatting.GREEN + "Allies (" + Formatting.WHITE + faction.getMutualAllies().size() + Formatting.GREEN + "): ") diff --git a/src/main/java/io/icker/factions/config/PowerConfig.java b/src/main/java/io/icker/factions/config/PowerConfig.java index f89d0210..3d86298c 100644 --- a/src/main/java/io/icker/factions/config/PowerConfig.java +++ b/src/main/java/io/icker/factions/config/PowerConfig.java @@ -2,12 +2,14 @@ import com.google.gson.*; import com.google.gson.annotations.SerializedName; +import org.jetbrains.annotations.NotNull; import java.lang.reflect.Type; public class PowerConfig { - @SerializedName("base") - public int BASE = 20; +// TODO(CamperSamu): Delete this after https://github.com/ickerio/factions/pull/71#issuecomment-1179757876 gets greenlighted +// @SerializedName("base") +// public int BASE = 20; @SerializedName("member") public int MEMBER = 20; @@ -31,7 +33,7 @@ public static class PowerTicks { public static class Deserializer implements JsonDeserializer { @Override - public PowerConfig deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + public PowerConfig deserialize(@NotNull JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (!json.isJsonObject() && !json.getAsBoolean()) { return null; } diff --git a/src/main/java/io/icker/factions/core/WorldManager.java b/src/main/java/io/icker/factions/core/WorldManager.java index 0f829afe..332d5790 100644 --- a/src/main/java/io/icker/factions/core/WorldManager.java +++ b/src/main/java/io/icker/factions/core/WorldManager.java @@ -34,9 +34,8 @@ private static void onMove(ServerPlayerEntity player) { if (user.autoclaim && claim == null) { Faction faction = user.getFaction(); int requiredPower = (faction.getClaims().size() + 1) * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; - int maxPower = faction.getUsers().size() * FactionsMod.CONFIG.POWER.MEMBER + FactionsMod.CONFIG.POWER.BASE; - if (maxPower < requiredPower) { + if (faction.calculateMaxPower() < requiredPower) { new Message("Not enough faction power to claim chunk, autoclaim toggled off").fail().send(player, false); user.autoclaim = false; } else { From 29b21ea4f29ab0967e86cce6d012514e42b9e4e5 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 18:59:34 +0200 Subject: [PATCH 08/20] Null-proofing Command.java Signed-off-by: Camper_Samu --- .../java/io/icker/factions/util/Command.java | 127 ++++++++++-------- 1 file changed, 74 insertions(+), 53 deletions(-) diff --git a/src/main/java/io/icker/factions/util/Command.java b/src/main/java/io/icker/factions/util/Command.java index 53b2bb88..1f118af1 100644 --- a/src/main/java/io/icker/factions/util/Command.java +++ b/src/main/java/io/icker/factions/util/Command.java @@ -1,10 +1,7 @@ package io.icker.factions.util; -import java.util.function.Predicate; - import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.tree.LiteralCommandNode; - import io.icker.factions.FactionsMod; import io.icker.factions.api.persistents.Faction; import io.icker.factions.api.persistents.User; @@ -12,17 +9,28 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import java.util.function.Predicate; public interface Command { - public LiteralCommandNode getNode(); - public static final boolean permissions = FabricLoader.getInstance().isModLoaded("fabric-permissions-api-v0"); + boolean permissions = FabricLoader.getInstance().isModLoaded("fabric-permissions-api-v0"); - public interface Requires { - boolean run(User user); + static User getUser(@NotNull ServerPlayerEntity player) { + User user = User.get(player.getUuid()); + if (user.getSpoof() == null) { + return user; + } + return user.getSpoof(); + } + + LiteralCommandNode getNode(); + interface Requires { + @Contract(pure = true) @SafeVarargs - public static Predicate multiple(Predicate... args) { + static @NotNull Predicate multiple(Predicate... args) { return source -> { for (Predicate predicate : args) { if (!predicate.test(source)) return false; @@ -32,97 +40,110 @@ public static Predicate multiple(Predicate isFactionless() { + @Contract(pure = true) + static @NotNull Predicate isFactionless() { return require(user -> !user.isInFaction()); } - public static Predicate isMember() { - return require(user -> user.isInFaction()); + @Contract(pure = true) + static @NotNull Predicate isMember() { + return require(User::isInFaction); } - public static Predicate isCommander() { + @Contract(pure = true) + static @NotNull Predicate isCommander() { return require(user -> user.rank == User.Rank.COMMANDER || user.rank == User.Rank.LEADER || user.rank == User.Rank.OWNER); } - public static Predicate isLeader() { + @Contract(pure = true) + static @NotNull Predicate isLeader() { return require(user -> user.rank == User.Rank.LEADER || user.rank == User.Rank.OWNER); } - public static Predicate isOwner() { + @Contract(pure = true) + static @NotNull Predicate isOwner() { return require(user -> user.rank == User.Rank.OWNER); } - - public static Predicate isAdmin() { + + @Contract(pure = true) + @SuppressWarnings("unused") //util + static @NotNull Predicate isAdmin() { return source -> source.hasPermissionLevel(FactionsMod.CONFIG.REQUIRED_BYPASS_LEVEL); } - public static Predicate hasPerms(String permission, int defaultValue) { + @Contract(pure = true) + static @NotNull Predicate hasPerms(String permission, int defaultValue) { return source -> !permissions || Permissions.check(source, permission, defaultValue); } - public static Predicate require(Requires req) { + @Contract(pure = true) + static @NotNull Predicate require(Requires req) { return source -> { - ServerPlayerEntity entity = source.getPlayer(); - User user = Command.getUser(entity); + ServerPlayerEntity player = source.getPlayer(); + if (player == null) + return false; // Confirm that it's a player executing the command and not an entity with /execute (or console) + User user = Command.getUser(player); return req.run(user); }; } - } - public interface Suggests { - String[] run(User user); + boolean run(User user); + } - public static SuggestionProvider allFactions() { + interface Suggests { + @Contract(pure = true) + static @NotNull SuggestionProvider allFactions() { return allFactions(true); } - public static SuggestionProvider allFactions(boolean includeYou) { - return suggest(user -> - Faction.all() - .stream() - .filter(f -> includeYou || !user.isInFaction() || !user.getFaction().getID().equals(f.getID())) - .map(f -> f.getName()) - .toArray(String[]::new) + @Contract(pure = true) + static @NotNull SuggestionProvider allFactions(boolean includeYou) { + return suggest(user -> + Faction.all() + .stream() + .filter(f -> includeYou || !user.isInFaction() || !user.getFaction().getID().equals(f.getID())) + .map(Faction::getName) + .toArray(String[]::new) ); } - public static SuggestionProvider openFactions() { + @Contract(pure = true) + @SuppressWarnings("unused") //util + static @NotNull SuggestionProvider openFactions() { return suggest(user -> - Faction.all() - .stream() - .filter(f -> f.isOpen()) - .map(f -> f.getName()) - .toArray(String[]::new) + Faction.all() + .stream() + .filter(Faction::isOpen) + .map(Faction::getName) + .toArray(String[]::new) ); } - public static SuggestionProvider openInvitedFactions() { + @Contract(pure = true) + static @NotNull SuggestionProvider openInvitedFactions() { return suggest(user -> - Faction.all() - .stream() - .filter(f -> f.isOpen() || f.isInvited(user.getID())) - .map(f -> f.getName()) - .toArray(String[]::new) + Faction.all() + .stream() + .filter(f -> f.isOpen() || f.isInvited(user.getID())) + .map(Faction::getName) + .toArray(String[]::new) ); } - public static SuggestionProvider suggest(Suggests sug) { + @Contract(pure = true) + static @NotNull SuggestionProvider suggest(Suggests sug) { return (context, builder) -> { - ServerPlayerEntity entity = context.getSource().getPlayer(); - User user = User.get(entity.getUuid()); + ServerPlayerEntity player = context.getSource().getPlayer(); + if (player == null) + return null; // Confirm that it's a player executing the command and not an entity with /execute + User user = User.get(player.getUuid()); for (String suggestion : sug.run(user)) { builder.suggest(suggestion); } return builder.buildFuture(); }; } - } - public static User getUser(ServerPlayerEntity player) { - User user = User.get(player.getUuid()); - if (user.getSpoof() == null) { - return user; - } - return user.getSpoof(); + String[] run(User user); } } \ No newline at end of file From e3f9d2c4249102e476c1767f409a83736124e082 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 20:28:26 +0200 Subject: [PATCH 09/20] Fix User I/O (oops) Signed-off-by: Camper_Samu --- src/main/java/io/icker/factions/api/persistents/User.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/icker/factions/api/persistents/User.java b/src/main/java/io/icker/factions/api/persistents/User.java index 808ccd71..60da4840 100644 --- a/src/main/java/io/icker/factions/api/persistents/User.java +++ b/src/main/java/io/icker/factions/api/persistents/User.java @@ -40,7 +40,7 @@ public enum SoundMode { } @Field("ID") - private final UUID id; + private UUID id; @Field("FactionID") private UUID factionID; @@ -72,8 +72,7 @@ public User(UUID id) { power = getMaxPower(); } -// NOTE(CamperSamu): why does this exist?? -// public User() {} + public User() {} @SuppressWarnings("unused") //util public String getKey() { From 104e6f176ee47dd76ed51f486320d5fc58cb34bf Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 20:29:24 +0200 Subject: [PATCH 10/20] Added a generic Player Death event Signed-off-by: Camper_Samu --- .../io/icker/factions/api/events/PlayerEvents.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/io/icker/factions/api/events/PlayerEvents.java b/src/main/java/io/icker/factions/api/events/PlayerEvents.java index e6b36e64..44c4de11 100644 --- a/src/main/java/io/icker/factions/api/events/PlayerEvents.java +++ b/src/main/java/io/icker/factions/api/events/PlayerEvents.java @@ -58,6 +58,15 @@ public class PlayerEvents { } }); + /** + * Called when a player dies + */ + public static final Event ON_PLAYER_DEATH = EventFactory.createArrayBacked(PlayerDeath.class, callbacks -> (player, source) -> { + for (PlayerDeath callback : callbacks) { + callback.onPlayerDeath(player, source); + } + }); + /** * Called on a power reward will be given */ @@ -101,6 +110,11 @@ public interface KilledByPlayer { void onKilledByPlayer(ServerPlayerEntity player, DamageSource source); } + @FunctionalInterface + public interface PlayerDeath { + void onPlayerDeath(ServerPlayerEntity player, DamageSource source); + } + @FunctionalInterface public interface PowerTick { void onPowerTick(ServerPlayerEntity player); From ff46fb4300ab8bbc357e1123d60264fbe2635c66 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 20:32:13 +0200 Subject: [PATCH 11/20] Added a generic Player Death event pt.2 + config option to apply death penalty for every death (pveDeathPenalty, false by default) Signed-off-by: Camper_Samu --- .../icker/factions/command/InfoCommand.java | 57 ++++++++----- .../io/icker/factions/config/PowerConfig.java | 3 + .../icker/factions/core/FactionsManager.java | 21 ++--- .../mixin/ServerPlayerEntityMixin.java | 10 +-- .../factions/util/PlaceholdersWrapper.java | 82 +++++++++++++++++-- 5 files changed, 129 insertions(+), 44 deletions(-) diff --git a/src/main/java/io/icker/factions/command/InfoCommand.java b/src/main/java/io/icker/factions/command/InfoCommand.java index 5e9ce37c..33280dfc 100644 --- a/src/main/java/io/icker/factions/command/InfoCommand.java +++ b/src/main/java/io/icker/factions/command/InfoCommand.java @@ -19,16 +19,31 @@ import java.util.List; import java.util.stream.Collectors; +import static net.minecraft.util.Formatting.*; + public class InfoCommand implements Command { + //region Constants + private static final String + UNCACHED_PLAYER_TEXT = "{Uncached Player}", + DELIMITER = ", "; + //endregion + private int self(CommandContext context) { ServerCommandSource source = context.getSource(); ServerPlayerEntity player = source.getPlayer(); if (player == null) return -1; // Confirm that it's a player executing the command and not an entity with /execute User user = Command.getUser(player); - if (!user.isInFaction()) { - new Message("Command can only be used whilst in a faction").fail().send(player, false); - return 0; + if (!user.isInFaction()) { //return player power + final String dashes = new StringBuilder("--------------------------------").substring(0, (32 - player.getName().getString().length())/2); +// final MutableText pinfo = Text.literal(dashes).append("[ ").formatted(BLACK).append(player.getName()).append(" ]").formatted(BLACK).append(dashes); + final var color = player.getName().getStyle().getColor() == null ? + WHITE : Formatting.byName(player.getName().getStyle().getColor().getName()); + new Message(BLACK + dashes + "[ " + color + player.getName().getString() + BLACK + " ]" + dashes).send(player, false); + new Message(GOLD + "Power: " + GREEN + user.getPower() + "/" + user.getMaxPower()) + .hover("Current / Max") + .send(player, false); + return 1; } return info(player, user.getFaction()); @@ -56,25 +71,25 @@ public static int info(ServerPlayerEntity player, Faction faction) { if (player.getServer() == null) return -1; UserCache cache = player.getServer().getUserCache(); - String owner = Formatting.WHITE + + String owner = WHITE + users.stream() .filter(u -> u.rank == User.Rank.OWNER) - .map(user -> cache.getByUuid(user.getID()).orElse(new GameProfile(Util.NIL_UUID, "{Uncached Player}")).getName()) - .collect(Collectors.joining(", ")); + .map(user -> cache.getByUuid(user.getID()).orElse(new GameProfile(Util.NIL_UUID, UNCACHED_PLAYER_TEXT)).getName()) + .collect(Collectors.joining(DELIMITER)); String usersList = users.stream() - .map(user -> cache.getByUuid(user.getID()).orElse(new GameProfile(Util.NIL_UUID, "{Uncached Player}")).getName()) - .collect(Collectors.joining(", ")); + .map(user -> cache.getByUuid(user.getID()).orElse(new GameProfile(Util.NIL_UUID, UNCACHED_PLAYER_TEXT)).getName()) + .collect(Collectors.joining(DELIMITER)); String mutualAllies = faction.getMutualAllies().stream() .map(rel -> Faction.get(rel.target)) .map(fac -> fac.getColor() + fac.getName()) - .collect(Collectors.joining(Formatting.GRAY + ", ")); + .collect(Collectors.joining(Formatting.GRAY + DELIMITER)); String enemiesWith = Formatting.GRAY + faction.getEnemiesWith().stream() .map(rel -> Faction.get(rel.target)) .map(fac -> fac.getColor() + fac.getName()) - .collect(Collectors.joining(Formatting.GRAY + ", ")); + .collect(Collectors.joining(Formatting.GRAY + DELIMITER)); int requiredPower = faction.getClaims().size() * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; @@ -82,25 +97,25 @@ public static int info(ServerPlayerEntity player, Faction faction) { int numDashes = 32 - faction.getName().length(); String dashes = new StringBuilder("--------------------------------").substring(0, numDashes/2); - new Message(Formatting.BLACK + dashes + "[ " + faction.getColor() + faction.getName() + Formatting.BLACK + " ]" + dashes) + new Message(BLACK + dashes + "[ " + faction.getColor() + faction.getName() + BLACK + " ]" + dashes) .send(player, false); - new Message(Formatting.GOLD + "Description: ") - .add(Formatting.WHITE + faction.getDescription()) + new Message(GOLD + "Description: ") + .add(WHITE + faction.getDescription()) .send(player, false); - new Message(Formatting.GOLD + "Owner: ") - .add(Formatting.WHITE + owner) + new Message(GOLD + "Owner: ") + .add(WHITE + owner) .send(player, false); - new Message(Formatting.GOLD + "Members (" + Formatting.WHITE + users.size() + Formatting.GOLD + "): ") + new Message(GOLD + "Members (" + WHITE + users.size() + GOLD + "): ") .add(usersList) .send(player, false); - new Message(Formatting.GOLD + "Power: ") - .add(Formatting.GREEN.toString() + faction.getPower() + slash() + requiredPower + slash() + faction.calculateMaxPower()) + new Message(GOLD + "Power: ") + .add(GREEN.toString() + faction.getPower() + slash() + requiredPower + slash() + faction.calculateMaxPower()) .hover("Current / Required / Max") .send(player, false); - new Message(Formatting.GREEN + "Allies (" + Formatting.WHITE + faction.getMutualAllies().size() + Formatting.GREEN + "): ") + new Message(GREEN + "Allies (" + WHITE + faction.getMutualAllies().size() + GREEN + "): ") .add(mutualAllies) .send(player, false); - new Message(Formatting.RED + "Enemies (" + Formatting.WHITE + faction.getEnemiesWith().size() + Formatting.RED + "): ") + new Message(RED + "Enemies (" + WHITE + faction.getEnemiesWith().size() + RED + "): ") .add(enemiesWith) .send(player, false); @@ -108,7 +123,7 @@ public static int info(ServerPlayerEntity player, Faction faction) { } private static String slash() { - return Formatting.GRAY + " / " + Formatting.GREEN; + return Formatting.GRAY + " / " + GREEN; } public LiteralCommandNode getNode() { diff --git a/src/main/java/io/icker/factions/config/PowerConfig.java b/src/main/java/io/icker/factions/config/PowerConfig.java index 3d86298c..4cb38946 100644 --- a/src/main/java/io/icker/factions/config/PowerConfig.java +++ b/src/main/java/io/icker/factions/config/PowerConfig.java @@ -23,6 +23,9 @@ public class PowerConfig { @SerializedName("powerTicks") public PowerTicks POWER_TICKS = new PowerTicks(); + @SerializedName("pveDeathPenalty") + public boolean PVE_DEATH_PENALTY = false; + public static class PowerTicks { @SerializedName("ticks") public int TICKS = 12000; diff --git a/src/main/java/io/icker/factions/core/FactionsManager.java b/src/main/java/io/icker/factions/core/FactionsManager.java index 572e1ad1..aeaf653d 100644 --- a/src/main/java/io/icker/factions/core/FactionsManager.java +++ b/src/main/java/io/icker/factions/core/FactionsManager.java @@ -1,11 +1,8 @@ package io.icker.factions.core; -import io.icker.factions.api.events.FactionEvents; -import io.icker.factions.api.events.PlayerEvents; import io.icker.factions.api.persistents.Faction; import io.icker.factions.api.persistents.User; import io.icker.factions.util.Message; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; @@ -22,7 +19,10 @@ import java.util.Objects; import static io.icker.factions.FactionsMod.CONFIG; +import static io.icker.factions.api.events.FactionEvents.*; +import static io.icker.factions.api.events.PlayerEvents.*; import static java.lang.String.format; +import static net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents.SERVER_STARTED; public class FactionsManager { //region Constants @@ -33,13 +33,14 @@ public class FactionsManager { //endregion public static void register() { - ServerLifecycleEvents.SERVER_STARTED.register(FactionsManager::serverStarted); - FactionEvents.MODIFY.register(FactionsManager::factionModified); - FactionEvents.MEMBER_JOIN.register(FactionsManager::memberChange); - FactionEvents.MEMBER_LEAVE.register(FactionsManager::memberChange); - PlayerEvents.ON_KILLED_BY_PLAYER.register(FactionsManager::playerDeath); - PlayerEvents.ON_POWER_TICK.register(FactionsManager::powerTick); - PlayerEvents.OPEN_SAFE.register(FactionsManager::openSafe); + SERVER_STARTED.register(FactionsManager::serverStarted); + MODIFY.register(FactionsManager::factionModified); + MEMBER_JOIN.register(FactionsManager::memberChange); + MEMBER_LEAVE.register(FactionsManager::memberChange); + if (CONFIG.POWER.PVE_DEATH_PENALTY) ON_PLAYER_DEATH.register(FactionsManager::playerDeath); + else ON_KILLED_BY_PLAYER.register(FactionsManager::playerDeath); + ON_POWER_TICK.register(FactionsManager::powerTick); + OPEN_SAFE.register(FactionsManager::openSafe); } private static void serverStarted(MinecraftServer server) { diff --git a/src/main/java/io/icker/factions/mixin/ServerPlayerEntityMixin.java b/src/main/java/io/icker/factions/mixin/ServerPlayerEntityMixin.java index 6c924c8d..a9e4e196 100644 --- a/src/main/java/io/icker/factions/mixin/ServerPlayerEntityMixin.java +++ b/src/main/java/io/icker/factions/mixin/ServerPlayerEntityMixin.java @@ -30,14 +30,14 @@ protected ServerPlayerEntityMixin(EntityType entityType, @Inject(at = @At("HEAD"), method = "setClientSettings") public void setClientSettings(ClientSettingsC2SPacket packet, CallbackInfo info) { - User member = User.get(((ServerPlayerEntity)(Object) this).getUuid()); + User member = User.get(getUuid()); member.language = packet.language(); } @Inject(at = @At("HEAD"), method = "onDeath") public void onDeath(DamageSource source, CallbackInfo info) { Entity entity = source.getSource(); - if (entity == null || !entity.isPlayer()) return; + if (entity == null || !entity.isPlayer()) PlayerEvents.ON_PLAYER_DEATH.invoker().onPlayerDeath((ServerPlayerEntity) (Object) this, source); PlayerEvents.ON_KILLED_BY_PLAYER.invoker().onKilledByPlayer((ServerPlayerEntity) (Object) this, source); } @@ -58,15 +58,15 @@ private void isInvulnerableTo(DamageSource damageSource, CallbackInfoReturnable< @Inject(method = "getPlayerListName", at = @At("HEAD"), cancellable = true) public void getPlayerListName(CallbackInfoReturnable cir) { if (FactionsMod.CONFIG.DISPLAY.TAB_MENU) { - User member = User.get(((ServerPlayerEntity) (Object) this).getUuid()); + User member = User.get(getUuid()); if (member.isInFaction()) { Faction faction = member.getFaction(); cir.setReturnValue(new Message(String.format("[%s] ", faction.getName())).format(faction.getColor()).add( - new Message(((ServerPlayerEntity) (Object) this).getName().getString()).format(Formatting.WHITE) + new Message(getName().getString()).format(Formatting.WHITE) ).raw()); } else { cir.setReturnValue(new Message("[FACTIONLESS] ").format(Formatting.GRAY).add( - new Message(((ServerPlayerEntity) (Object) this).getName().getString()).format(Formatting.WHITE) + new Message(getName().getString()).format(Formatting.WHITE) ).raw()); } } diff --git a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java index 6b53586b..31e5cf26 100644 --- a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java +++ b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java @@ -1,6 +1,5 @@ package io.icker.factions.util; -import io.icker.factions.FactionsMod; import io.icker.factions.api.persistents.User; import net.minecraft.text.Style; import net.minecraft.text.Text; @@ -9,10 +8,14 @@ import static eu.pb4.placeholders.api.PlaceholderResult.invalid; import static eu.pb4.placeholders.api.PlaceholderResult.value; +import static eu.pb4.placeholders.api.Placeholders.parsePlaceholder; import static eu.pb4.placeholders.api.Placeholders.register; import static io.icker.factions.FactionsMod.MODID; import static java.lang.Integer.*; +import static net.minecraft.text.Text.empty; +import static net.minecraft.text.Text.literal; import static net.minecraft.util.Formatting.DARK_GRAY; +import static net.minecraft.util.Formatting.GRAY; public class PlaceholdersWrapper { public static final Identifier FACTION_NAME_ID = new Identifier(MODID, "name"); @@ -25,11 +28,14 @@ public class PlaceholdersWrapper { public static final Identifier FACTION_POWER_FORMATTED_ID = new Identifier(MODID, "power_formatted"); public static final Identifier FACTION_MAX_POWER_ID = new Identifier(MODID, "max_power"); public static final Identifier FACTION_PLAYER_POWER_ID = new Identifier(MODID, "player_power"); + public static final Identifier FACTION_PLAYER_POWER_FORMATTED_ID = new Identifier(MODID, "player_power_formatted"); public static final Identifier FACTION_PLAYER_MAX_POWER_ID = new Identifier(MODID, "player_max_power"); public static final Identifier FACTION_REQUIRED_POWER_ID = new Identifier(MODID, "required_power"); public static final Identifier FACTION_REQUIRED_POWER_FORMATTED_ID = new Identifier(MODID, "required_power_formatted"); + public static final Identifier FACTION_POWER_STATS_ID = new Identifier(MODID, "power_stats"); + public static final Identifier FACTION_POWER_STATS_FORMATTED_ID = new Identifier(MODID, "power_stats_formatted"); public static final String NULL_STRING = "N/A"; - public static final Text NULL_TEXT = Text.literal(NULL_STRING).formatted(DARK_GRAY); + public static final Text NULL_TEXT = literal(NULL_STRING).formatted(DARK_GRAY); public static void init() { register(FACTION_NAME_ID, (ctx, argument) -> { @@ -45,7 +51,7 @@ public static void init() { final var faction = member.getFaction(); if (faction != null) - r = Text.literal(faction.getName()).formatted(member.getFaction().getColor()); + r = literal(faction.getName()).formatted(member.getFaction().getColor()); return value(r); }); @@ -155,7 +161,7 @@ public static void init() { if (faction != null) { final int red = mapBoundRange(faction.calculateMaxPower(), 0, 170, 255, faction.getPower()); final int green = mapBoundRange(0, faction.calculateMaxPower(), 170, 255, faction.getPower()); - r = Text.literal("" + faction.getPower()).setStyle(Style.EMPTY.withColor(TextColor.parse("#" + toHexString(red) + toHexString(green) + "AA"))); + r = literal("" + faction.getPower()).setStyle(Style.EMPTY.withColor(TextColor.parse("#" + toHexString(red) + toHexString(green) + "AA"))); } return value(r); @@ -189,6 +195,18 @@ public static void init() { return value(r); }); + register(FACTION_PLAYER_POWER_FORMATTED_ID, (ctx, argument) -> { + if (!ctx.hasPlayer()) return invalid("No Player!"); + assert ctx.player() != null; + + final var member = User.get(ctx.player().getUuid()); + + final int red = mapBoundRange(member.getMaxPower(), 0, 170, 255, member.getPower()); + final int green = mapBoundRange(0, member.getMaxPower(), 170, 255, member.getPower()); + + return value(literal("" + member.getPower()).setStyle(Style.EMPTY.withColor(TextColor.parse("#" + toHexString(red) + toHexString(green) + "AA")))); + }); + register(FACTION_PLAYER_MAX_POWER_ID, (ctx, argument) -> { if (!ctx.hasPlayer()) return invalid("No Player!"); assert ctx.player() != null; @@ -213,7 +231,7 @@ public static void init() { final var faction = member.getFaction(); if (faction != null) - r = "" + faction.getClaims().size() * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; + r = "" + faction.calculateRequiredPower(); return value(r); }); @@ -231,16 +249,64 @@ public static void init() { if (faction != null) { - final int reqPower = faction.getClaims().size() * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; + final int reqPower = faction.calculateRequiredPower(); final int red = mapBoundRange(0, faction.getPower(), 85, 255, reqPower); - r = Text.literal("" + reqPower).setStyle(Style.EMPTY.withColor(TextColor.parse("#" + toHexString(red) + "5555"))); + r = literal("" + reqPower).setStyle(Style.EMPTY.withColor(TextColor.parse("#" + toHexString(red) + "5555"))); } return value(r); }); + + register(FACTION_POWER_STATS_ID, (ctx, argument) -> { + if (!ctx.hasPlayer()) return invalid("No Player!"); + assert ctx.player() != null; + + final var member = User.get(ctx.player().getUuid()); + if (member.isInFaction()) { + return value( + empty() + .append(parsePlaceholder(FACTION_POWER_ID, argument, ctx).text()) + .append(literal("/").formatted(DARK_GRAY)) + .append(parsePlaceholder(FACTION_REQUIRED_POWER_ID, argument, ctx).text()) + .append(literal("/").formatted(DARK_GRAY)) + .append(parsePlaceholder(FACTION_MAX_POWER_ID, argument, ctx).text()) + ); + } else { + return value( + empty() + .append(parsePlaceholder(FACTION_PLAYER_POWER_ID, argument, ctx).text()) + .append(literal("/").formatted(DARK_GRAY)) + .append(parsePlaceholder(FACTION_PLAYER_MAX_POWER_ID, argument, ctx).text()) + ); + } + }); + + register(FACTION_POWER_STATS_FORMATTED_ID, (ctx, argument) -> { + if (!ctx.hasPlayer()) return invalid("No Player!"); + assert ctx.player() != null; + + final var member = User.get(ctx.player().getUuid()); + if (member.isInFaction()) { + return value( + empty() + .append(parsePlaceholder(FACTION_POWER_FORMATTED_ID, argument, ctx).text()) + .append(literal("/").formatted(DARK_GRAY)) + .append(parsePlaceholder(FACTION_REQUIRED_POWER_FORMATTED_ID, argument, ctx).text()) + .append(literal("/").formatted(DARK_GRAY)) + .append(parsePlaceholder(FACTION_MAX_POWER_ID, argument, ctx).text().copy().formatted(GRAY)) + ); + } else { + return value( + empty() + .append(parsePlaceholder(FACTION_PLAYER_POWER_FORMATTED_ID, argument, ctx).text()) + .append(literal("/").formatted(DARK_GRAY)) + .append(parsePlaceholder(FACTION_PLAYER_MAX_POWER_ID, argument, ctx).text().copy().formatted(GRAY)) + ); + } + }); } - @SuppressWarnings("all") + @SuppressWarnings("all") //math utils private static int mapBoundRange(int a1, int a2, int b1, int b2, int s) { return min(b2, max(b1, b1 + ((s - a1) * (b2 - b1)) / (a2 - a1))); } From 66a96fcea92f819dad2603db9530c51021e46829 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 20:43:54 +0200 Subject: [PATCH 12/20] Fixed the required power calculation (whoops) Signed-off-by: Camper_Samu --- .../java/io/icker/factions/api/persistents/Faction.java | 2 +- .../java/io/icker/factions/core/FactionsManager.java | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/icker/factions/api/persistents/Faction.java b/src/main/java/io/icker/factions/api/persistents/Faction.java index acc603ca..20c07cd8 100644 --- a/src/main/java/io/icker/factions/api/persistents/Faction.java +++ b/src/main/java/io/icker/factions/api/persistents/Faction.java @@ -249,6 +249,6 @@ public int calculateMaxPower() { } public int calculateRequiredPower(){ - return (getClaims().size() + 1) * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; + return (getClaims().size()) * FactionsMod.CONFIG.POWER.CLAIM_WEIGHT; } } \ No newline at end of file diff --git a/src/main/java/io/icker/factions/core/FactionsManager.java b/src/main/java/io/icker/factions/core/FactionsManager.java index aeaf653d..93a2a023 100644 --- a/src/main/java/io/icker/factions/core/FactionsManager.java +++ b/src/main/java/io/icker/factions/core/FactionsManager.java @@ -12,7 +12,6 @@ import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.MutableText; -import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import org.jetbrains.annotations.NotNull; @@ -23,6 +22,8 @@ import static io.icker.factions.api.events.PlayerEvents.*; import static java.lang.String.format; import static net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents.SERVER_STARTED; +import static net.minecraft.text.Text.literal; +import static net.minecraft.text.Text.of; public class FactionsManager { //region Constants @@ -68,7 +69,7 @@ private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource User member = User.get(player.getUuid()); int adjusted = member.addPower(-CONFIG.POWER.DEATH_PENALTY); - final MutableText message = Text.literal(format(POWER_LOST_MESSAGE, player.getName().getString(), adjusted)); + final MutableText message = literal(format(POWER_LOST_MESSAGE, player.getName().getString(), adjusted)); if (member.isInFaction()) { final Faction faction = member.getFaction(); @@ -83,7 +84,7 @@ private static void powerTick(@NotNull ServerPlayerEntity player) { if (member.getPower() == member.getMaxPower()) return; int adjusted = member.addPower(CONFIG.POWER.POWER_TICKS.REWARD); - final MutableText message = Text.literal(format(POWER_GAINED_MESSAGE, player.getName().getString(), adjusted)); + final MutableText message = literal(format(POWER_GAINED_MESSAGE, player.getName().getString(), adjusted)); if (member.isInFaction()) { final Faction faction = member.getFaction(); @@ -117,7 +118,7 @@ private static ActionResult openSafe(PlayerEntity player, Faction faction) { return GenericContainerScreenHandler.createGeneric9x3(syncId, inventory, faction.getSafe()); } }, - Text.of(format("%s's Safe", faction.getName())) + of(format("%s's Safe", faction.getName())) ) ); From c38700ee1654c3134e16a9c48d5b248553c97e60 Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 10 Jul 2022 20:52:39 +0200 Subject: [PATCH 13/20] Default power config re-balance Signed-off-by: Camper_Samu --- src/main/java/io/icker/factions/config/PowerConfig.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/icker/factions/config/PowerConfig.java b/src/main/java/io/icker/factions/config/PowerConfig.java index 4cb38946..ceba23fe 100644 --- a/src/main/java/io/icker/factions/config/PowerConfig.java +++ b/src/main/java/io/icker/factions/config/PowerConfig.java @@ -7,18 +7,15 @@ import java.lang.reflect.Type; public class PowerConfig { -// TODO(CamperSamu): Delete this after https://github.com/ickerio/factions/pull/71#issuecomment-1179757876 gets greenlighted -// @SerializedName("base") -// public int BASE = 20; @SerializedName("member") public int MEMBER = 20; @SerializedName("claimWeight") - public int CLAIM_WEIGHT = 5; + public int CLAIM_WEIGHT = 2; @SerializedName("deathPenalty") - public int DEATH_PENALTY = 10; + public int DEATH_PENALTY = 5; @SerializedName("powerTicks") public PowerTicks POWER_TICKS = new PowerTicks(); @@ -31,7 +28,7 @@ public static class PowerTicks { public int TICKS = 12000; @SerializedName("reward") - public int REWARD = 1; + public int REWARD = 3; } public static class Deserializer implements JsonDeserializer { From c35111a051f5e44aeb9b0db766e1e50226f3559d Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Sun, 17 Jul 2022 22:29:02 +0200 Subject: [PATCH 14/20] Fix ArithmeticException when connecting via FabricProxy-Lite with hackEarlySend turned on Signed-off-by: Camper_Samu --- .../java/io/icker/factions/util/PlaceholdersWrapper.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java index 31e5cf26..60c8cdf7 100644 --- a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java +++ b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java @@ -308,6 +308,10 @@ public static void init() { @SuppressWarnings("all") //math utils private static int mapBoundRange(int a1, int a2, int b1, int b2, int s) { - return min(b2, max(b1, b1 + ((s - a1) * (b2 - b1)) / (a2 - a1))); + try { + return min(b2, max(b1, b1 + ((s - a1) * (b2 - b1)) / (a2 - a1))); + } catch (ArithmeticException ignored){ + return 0; + } } } From 4d83169ae1c2e6d9269cf082136d9a81238866cb Mon Sep 17 00:00:00 2001 From: Camper_Samu Date: Thu, 28 Jul 2022 17:03:55 +0200 Subject: [PATCH 15/20] One day I'll stop messing up conflicts lol Signed-off-by: Camper_Samu --- src/main/java/io/icker/factions/api/persistents/Faction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/icker/factions/api/persistents/Faction.java b/src/main/java/io/icker/factions/api/persistents/Faction.java index 59fd1eb3..a2326482 100644 --- a/src/main/java/io/icker/factions/api/persistents/Faction.java +++ b/src/main/java/io/icker/factions/api/persistents/Faction.java @@ -242,6 +242,7 @@ public int calculateMaxPower() { maxPower += user.getMaxPower(); } return maxPower; + } @Override public boolean equals(Object o) { From d33c59eaa8b3f11bb312414cf093e8209b7fbb4e Mon Sep 17 00:00:00 2001 From: BlueZeeKing Date: Sat, 30 Jul 2022 15:59:16 -0400 Subject: [PATCH 16/20] Fix comment in Message and remove migrator --- src/main/java/io/icker/factions/util/Message.java | 2 +- src/main/java/io/icker/factions/util/Migrator.java | 0 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 src/main/java/io/icker/factions/util/Migrator.java diff --git a/src/main/java/io/icker/factions/util/Message.java b/src/main/java/io/icker/factions/util/Message.java index 8502c0f9..81d530b7 100644 --- a/src/main/java/io/icker/factions/util/Message.java +++ b/src/main/java/io/icker/factions/util/Message.java @@ -89,7 +89,7 @@ public void sendToGlobalChat() { public void sendToFactionChat(@NotNull Faction faction) { for (User member : faction.getUsers()) { ServerPlayerEntity player = manager.getPlayer(member.getID()); - if (player == null) return; // Confirm that it's a player executing the command and not an entity with /execute + if (player == null) return; // Make sure that player is online player.sendMessage(text, false); } } diff --git a/src/main/java/io/icker/factions/util/Migrator.java b/src/main/java/io/icker/factions/util/Migrator.java deleted file mode 100644 index e69de29b..00000000 From 6795b0823985883d9ce5b2d25c7bf66d8fc268e3 Mon Sep 17 00:00:00 2001 From: BlueZeeKing Date: Sat, 30 Jul 2022 16:17:43 -0400 Subject: [PATCH 17/20] Combine player death events --- .../factions/api/events/PlayerEvents.java | 20 +++---------------- .../icker/factions/core/FactionsManager.java | 7 ++++--- .../mixin/ServerPlayerEntityMixin.java | 3 +-- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/main/java/io/icker/factions/api/events/PlayerEvents.java b/src/main/java/io/icker/factions/api/events/PlayerEvents.java index 44c4de11..d882cca5 100644 --- a/src/main/java/io/icker/factions/api/events/PlayerEvents.java +++ b/src/main/java/io/icker/factions/api/events/PlayerEvents.java @@ -49,21 +49,12 @@ public class PlayerEvents { } }); - /** - * Called when a player is killed by another player - */ - public static final Event ON_KILLED_BY_PLAYER = EventFactory.createArrayBacked(KilledByPlayer.class, callbacks -> (player, source) -> { - for (KilledByPlayer callback : callbacks) { - callback.onKilledByPlayer(player, source); - } - }); - /** * Called when a player dies */ - public static final Event ON_PLAYER_DEATH = EventFactory.createArrayBacked(PlayerDeath.class, callbacks -> (player, source) -> { + public static final Event ON_PLAYER_DEATH = EventFactory.createArrayBacked(PlayerDeath.class, callbacks -> (player, source, killedByPlayer) -> { for (PlayerDeath callback : callbacks) { - callback.onPlayerDeath(player, source); + callback.onPlayerDeath(player, source, killedByPlayer); } }); @@ -105,14 +96,9 @@ public interface Move { void onMove(ServerPlayerEntity player); } - @FunctionalInterface - public interface KilledByPlayer { - void onKilledByPlayer(ServerPlayerEntity player, DamageSource source); - } - @FunctionalInterface public interface PlayerDeath { - void onPlayerDeath(ServerPlayerEntity player, DamageSource source); + void onPlayerDeath(ServerPlayerEntity player, DamageSource source, boolean killedByPlayer); } @FunctionalInterface diff --git a/src/main/java/io/icker/factions/core/FactionsManager.java b/src/main/java/io/icker/factions/core/FactionsManager.java index 93a2a023..60a22b10 100644 --- a/src/main/java/io/icker/factions/core/FactionsManager.java +++ b/src/main/java/io/icker/factions/core/FactionsManager.java @@ -38,8 +38,7 @@ public static void register() { MODIFY.register(FactionsManager::factionModified); MEMBER_JOIN.register(FactionsManager::memberChange); MEMBER_LEAVE.register(FactionsManager::memberChange); - if (CONFIG.POWER.PVE_DEATH_PENALTY) ON_PLAYER_DEATH.register(FactionsManager::playerDeath); - else ON_KILLED_BY_PLAYER.register(FactionsManager::playerDeath); + ON_PLAYER_DEATH.register(FactionsManager::playerDeath); ON_POWER_TICK.register(FactionsManager::powerTick); OPEN_SAFE.register(FactionsManager::openSafe); } @@ -65,7 +64,9 @@ private static void memberChange(Faction faction, User user) { } } - private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource source) { + private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource source, boolean killedByPlayer) { + if (!killedByPlayer && !CONFIG.POWER.PVE_DEATH_PENALTY) return; + User member = User.get(player.getUuid()); int adjusted = member.addPower(-CONFIG.POWER.DEATH_PENALTY); diff --git a/src/main/java/io/icker/factions/mixin/ServerPlayerEntityMixin.java b/src/main/java/io/icker/factions/mixin/ServerPlayerEntityMixin.java index a9e4e196..85dbfe56 100644 --- a/src/main/java/io/icker/factions/mixin/ServerPlayerEntityMixin.java +++ b/src/main/java/io/icker/factions/mixin/ServerPlayerEntityMixin.java @@ -37,8 +37,7 @@ public void setClientSettings(ClientSettingsC2SPacket packet, CallbackInfo info) @Inject(at = @At("HEAD"), method = "onDeath") public void onDeath(DamageSource source, CallbackInfo info) { Entity entity = source.getSource(); - if (entity == null || !entity.isPlayer()) PlayerEvents.ON_PLAYER_DEATH.invoker().onPlayerDeath((ServerPlayerEntity) (Object) this, source); - PlayerEvents.ON_KILLED_BY_PLAYER.invoker().onKilledByPlayer((ServerPlayerEntity) (Object) this, source); + PlayerEvents.ON_PLAYER_DEATH.invoker().onPlayerDeath((ServerPlayerEntity) (Object) this, source, entity == null || !entity.isPlayer()); } @Inject(at = @At("HEAD"), method = "tick") From f0a87d52ea83ccdeb850e8a871c445376fd88872 Mon Sep 17 00:00:00 2001 From: Camper_Samu <32773961+CamperSamu@users.noreply.github.com> Date: Wed, 3 Aug 2022 21:07:46 +0200 Subject: [PATCH 18/20] fix: Power penalty/bonus not working correctly (check power range before subtracting) Because of me changing how power is added the old code behaved in the wrong way. Now I moved the range check outside of the method and relocated it into the reward/penalty code. New Logic: - Penalty - Check if the power is less or zero - If the power is less or zero quit out the fuction - Before adding power, check if the penalty makes the power value negative - If so, instead of subtracting the power power penalty, subtract the remaining power - Otherwise subtract the power penalty like normal - Reward - Check if the power exceeds the max power - If the power exceeds the max power quit out the function - Before adding the reward, check if the current power + the reward overflows the max power - If so, add the remaining power (max power - power) - Otherwise, add power like normal. --- src/main/java/io/icker/factions/core/FactionsManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/icker/factions/core/FactionsManager.java b/src/main/java/io/icker/factions/core/FactionsManager.java index 60a22b10..0a4982cb 100644 --- a/src/main/java/io/icker/factions/core/FactionsManager.java +++ b/src/main/java/io/icker/factions/core/FactionsManager.java @@ -68,7 +68,8 @@ private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource if (!killedByPlayer && !CONFIG.POWER.PVE_DEATH_PENALTY) return; User member = User.get(player.getUuid()); - int adjusted = member.addPower(-CONFIG.POWER.DEATH_PENALTY); + if (member.getPower() <= 0) return; + int adjusted = member.addPower(member.getPower()-CONFIG.POWER.DEATH_PENALTY >= 0 ? -CONFIG.POWER.DEATH_PENALTY : -member.getPower()); final MutableText message = literal(format(POWER_LOST_MESSAGE, player.getName().getString(), adjusted)); @@ -82,8 +83,8 @@ private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource private static void powerTick(@NotNull ServerPlayerEntity player) { User member = User.get(player.getUuid()); - if (member.getPower() == member.getMaxPower()) return; - int adjusted = member.addPower(CONFIG.POWER.POWER_TICKS.REWARD); + if (member.getPower() >= member.getMaxPower()) return; + int adjusted = member.addPower(member.getPower() + CONFIG.POWER.POWER_TICKS.REWARD <= member.getMaxPower() ? CONFIG.POWER.POWER_TICKS.REWARD : member.getMaxPower() - member.getPower()); final MutableText message = literal(format(POWER_GAINED_MESSAGE, player.getName().getString(), adjusted)); From fabc217692bacf99771230189f04048fba82b166 Mon Sep 17 00:00:00 2001 From: Camper_Samu <32773961+CamperSamu@users.noreply.github.com> Date: Wed, 3 Aug 2022 21:12:47 +0200 Subject: [PATCH 19/20] fix: Wrong power reward/penalty message --- .../java/io/icker/factions/core/FactionsManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/icker/factions/core/FactionsManager.java b/src/main/java/io/icker/factions/core/FactionsManager.java index 0a4982cb..16334d1c 100644 --- a/src/main/java/io/icker/factions/core/FactionsManager.java +++ b/src/main/java/io/icker/factions/core/FactionsManager.java @@ -69,9 +69,10 @@ private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource User member = User.get(player.getUuid()); if (member.getPower() <= 0) return; - int adjusted = member.addPower(member.getPower()-CONFIG.POWER.DEATH_PENALTY >= 0 ? -CONFIG.POWER.DEATH_PENALTY : -member.getPower()); + final int old = member.getPower(); + final int adjusted = member.addPower(member.getPower()-CONFIG.POWER.DEATH_PENALTY >= 0 ? -CONFIG.POWER.DEATH_PENALTY : -member.getPower()); - final MutableText message = literal(format(POWER_LOST_MESSAGE, player.getName().getString(), adjusted)); + final MutableText message = literal(format(POWER_LOST_MESSAGE, player.getName().getString(), old-adjusted)); if (member.isInFaction()) { final Faction faction = member.getFaction(); @@ -84,9 +85,10 @@ private static void playerDeath(@NotNull ServerPlayerEntity player, DamageSource private static void powerTick(@NotNull ServerPlayerEntity player) { User member = User.get(player.getUuid()); if (member.getPower() >= member.getMaxPower()) return; - int adjusted = member.addPower(member.getPower() + CONFIG.POWER.POWER_TICKS.REWARD <= member.getMaxPower() ? CONFIG.POWER.POWER_TICKS.REWARD : member.getMaxPower() - member.getPower()); + final int old = member.getPower(); + final int adjusted = member.addPower(member.getPower() + CONFIG.POWER.POWER_TICKS.REWARD <= member.getMaxPower() ? CONFIG.POWER.POWER_TICKS.REWARD : member.getMaxPower() - member.getPower()); - final MutableText message = literal(format(POWER_GAINED_MESSAGE, player.getName().getString(), adjusted)); + final MutableText message = literal(format(POWER_GAINED_MESSAGE, player.getName().getString(), adjusted-old)); if (member.isInFaction()) { final Faction faction = member.getFaction(); From e115b1f6765dc2a4b2ea9e8c89b1d1f84fa0a3f2 Mon Sep 17 00:00:00 2001 From: BlueZeeKing Date: Wed, 3 Aug 2022 16:29:48 -0400 Subject: [PATCH 20/20] Remove redundant check if member is null --- src/main/java/io/icker/factions/util/PlaceholdersWrapper.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java index c0d02ffa..ed687d1d 100644 --- a/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java +++ b/src/main/java/io/icker/factions/util/PlaceholdersWrapper.java @@ -182,7 +182,6 @@ public static void init() { assert ctx.player() != null; final var member = User.get(ctx.player().getUuid()); - if (member == null) return value("" + User.getPower(ctx.player().getUuid())); String r = "" + member.getPower(); @@ -206,7 +205,6 @@ public static void init() { assert ctx.player() != null; final var member = User.get(ctx.player().getUuid()); - if (member == null) return value("" + User.getMaxPower(ctx.player().getUuid())); String r = "" + member.getMaxPower();