From df5f3cebc1034e88b9ed88e1f2a59db035f7fb6f Mon Sep 17 00:00:00 2001 From: Clem Fern Date: Sat, 9 Nov 2024 11:28:07 +0100 Subject: [PATCH 01/14] wip --- .vscode/settings.json | 4 + pom.xml | 17 +- .../gringottslands/GringottsLand.java | 17 -- .../gringottslands/GringottsLands.java | 85 +++++++++ .../gringottslands/LandsConfiguration.java | 28 +++ .../gringottslands/LandsDependency.java | 151 ++++++++++++++++ .../gringottslands/LandsLanguage.java | 33 ++++ .../gringottslands/LandsPermissions.java | 37 ++++ .../land/LandAccountHolder.java | 68 +++++++ .../land/LandHolderProvider.java | 165 +++++++++++++++++ .../nation/NationAccountHolder.java | 71 ++++++++ .../nation/NationHolderProvider.java | 168 ++++++++++++++++++ src/main/resources/config.yml | 10 ++ src/main/resources/i18n/messages_de.yml | 4 + src/main/resources/i18n/messages_fr.yml | 6 + src/main/resources/i18n/messages_pt-BR.yml | 4 + src/main/resources/messages.yml | 5 + target/classes/config.yml | 10 ++ target/classes/i18n/messages_de.yml | 4 + target/classes/i18n/messages_fr.yml | 6 + target/classes/i18n/messages_pt-BR.yml | 4 + target/classes/messages.yml | 5 + .../gringottslands/GringottsLand.class | Bin 520 -> 0 bytes .../gringottslands/GringottsLands.class | Bin 0 -> 4485 bytes .../gringottslands/LandsConfiguration.class | Bin 0 -> 2114 bytes .../gringottslands/LandsDependency.class | Bin 0 -> 5465 bytes .../gringottslands/LandsLanguage.class | Bin 0 -> 3290 bytes .../gringottslands/LandsPermissions.class | Bin 0 -> 1606 bytes .../land/LandAccountHolder.class | Bin 0 -> 2181 bytes .../land/LandHolderProvider.class | Bin 0 -> 6176 bytes .../nation/NationAccountHolder.class | Bin 0 -> 2211 bytes .../nation/NationHolderProvider.class | Bin 0 -> 6272 bytes target/gringotts-lands.jar | Bin 0 -> 19898 bytes target/maven-archiver/pom.properties | 5 + .../compile/default-compile/createdFiles.lst | 0 .../compile/default-compile/inputFiles.lst | 9 + 36 files changed, 894 insertions(+), 22 deletions(-) create mode 100644 .vscode/settings.json delete mode 100644 src/main/java/net/laboulangerie/gringottslands/GringottsLand.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/GringottsLands.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/LandsDependency.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/LandsPermissions.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/nation/NationAccountHolder.java create mode 100644 src/main/java/net/laboulangerie/gringottslands/nation/NationHolderProvider.java create mode 100644 src/main/resources/config.yml create mode 100644 src/main/resources/i18n/messages_de.yml create mode 100644 src/main/resources/i18n/messages_fr.yml create mode 100644 src/main/resources/i18n/messages_pt-BR.yml create mode 100644 src/main/resources/messages.yml create mode 100644 target/classes/config.yml create mode 100644 target/classes/i18n/messages_de.yml create mode 100644 target/classes/i18n/messages_fr.yml create mode 100644 target/classes/i18n/messages_pt-BR.yml create mode 100644 target/classes/messages.yml delete mode 100644 target/classes/net/laboulangerie/gringottslands/GringottsLand.class create mode 100644 target/classes/net/laboulangerie/gringottslands/GringottsLands.class create mode 100644 target/classes/net/laboulangerie/gringottslands/LandsConfiguration.class create mode 100644 target/classes/net/laboulangerie/gringottslands/LandsDependency.class create mode 100644 target/classes/net/laboulangerie/gringottslands/LandsLanguage.class create mode 100644 target/classes/net/laboulangerie/gringottslands/LandsPermissions.class create mode 100644 target/classes/net/laboulangerie/gringottslands/land/LandAccountHolder.class create mode 100644 target/classes/net/laboulangerie/gringottslands/land/LandHolderProvider.class create mode 100644 target/classes/net/laboulangerie/gringottslands/nation/NationAccountHolder.class create mode 100644 target/classes/net/laboulangerie/gringottslands/nation/NationHolderProvider.class create mode 100644 target/gringotts-lands.jar create mode 100644 target/maven-archiver/pom.properties create mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..07498ee --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "java.compile.nullAnalysis.mode": "disabled", + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1ef84ce..e326d6e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 net.laboulangerie - gringottslands + gringotts-lands 1.0-SNAPSHOT GringottsLands @@ -18,7 +18,7 @@ 17 - GringottsLands + gringotts-lands src/main/resources @@ -46,9 +46,16 @@ provided - com.github.LaBoulangerie - Gringotts - 2.12.2 + com.github.nikosgram + gringotts + 2.12.3 + provided + + + com.github.angeschossen + LandsAPI + 7.10.2 + provided \ No newline at end of file diff --git a/src/main/java/net/laboulangerie/gringottslands/GringottsLand.java b/src/main/java/net/laboulangerie/gringottslands/GringottsLand.java deleted file mode 100644 index d7da2bb..0000000 --- a/src/main/java/net/laboulangerie/gringottslands/GringottsLand.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.laboulangerie.gringottslands; - -import org.bukkit.plugin.java.JavaPlugin; - -public class GringottsLand extends JavaPlugin { - @Override - public void onEnable() { - // TODO Auto-generated method stub - super.onEnable(); - } - - @Override - public void onDisable() { - // TODO Auto-generated method stub - super.onDisable(); - } -} \ No newline at end of file diff --git a/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java b/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java new file mode 100644 index 0000000..5d106e3 --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java @@ -0,0 +1,85 @@ +package net.laboulangerie.gringottslands; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import org.gestern.gringotts.Gringotts; +import org.gestern.gringotts.api.dependency.Dependency; + +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; + +public class GringottsLands extends JavaPlugin { + private static final String MESSAGES_YML = "messages.yml"; + + @Override + public void onLoad() { + try { + Plugin plugin = Gringotts.instance.getDependencies() + .hookPlugin("Lands", "me.angeschossen.lands.Lands", "7.9.5"); + + if (plugin != null && Gringotts.instance.getDependencies() + .registerDependency(new LandsDependency(Gringotts.instance, plugin))) { + getLogger().warning("Lands plugin is already assigned into the dependencies."); + } + } catch (IllegalArgumentException e) { + getLogger().warning("Looks like Lands plugin is not compatible with Gringotts"); + } + + // load and init configuration + saveDefaultConfig(); // saves default configuration if no config.yml exists yet + reloadConfig(); + + Gringotts.instance.getDependencies().getDependency("lands").ifPresent(Dependency::onLoad); + } + + @Override + public void onEnable() { + + } + + @Override + public void onDisable() { + + } + + /** + * Reload config. + *

+ * override to handle custom config logic and language loading + */ + @Override + public void reloadConfig() { + super.reloadConfig(); + LandsConfiguration.CONF.readConfig(getConfig()); + LandsLanguage.LANG.readLanguage(getMessages()); + } + + /** + * Get the configured player interaction messages. + * + * @return the configured player interaction messages + */ + public FileConfiguration getMessages() { + String langPath = String.format("i18n/messages_%s.yml", LandsConfiguration.CONF.language); + + // try configured language first + InputStream langStream = getResource(langPath); + FileConfiguration conf; + + if (langStream != null) { + Reader langReader = new InputStreamReader(langStream, StandardCharsets.UTF_8); + conf = YamlConfiguration.loadConfiguration(langReader); + } else { + // use custom/default + File langFile = new File(getDataFolder(), MESSAGES_YML); + conf = YamlConfiguration.loadConfiguration(langFile); + } + + return conf; + } +} diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java new file mode 100644 index 0000000..69b06cf --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java @@ -0,0 +1,28 @@ +package net.laboulangerie.gringottslands; + +import org.bukkit.configuration.file.FileConfiguration; + +public enum LandsConfiguration { + CONF; + + /** + * Language to be used for messages. Should be an ISO 639-1 (alpha-2) code. + * If a language is not supported by Gringotts, use user-configured or default (English) messages. + */ + public String language = "custom"; + public String landSignTypeName = "land"; + public String nationSignTypeName = "nation"; + + public boolean vaultsOnlyInLands = false; + public long landStartBalance = 0; + public long nationStartBalance = 0; + + public void readConfig(FileConfiguration savedConfig) { + CONF.language = savedConfig.getString("language", "custom"); + CONF.landSignTypeName = savedConfig.getString("land_sign_type_name", "land"); + CONF.nationSignTypeName = savedConfig.getString("nation_sign_type_name", "nation"); + CONF.vaultsOnlyInLands = savedConfig.getBoolean("vaults_only_in_lands", false); + CONF.landStartBalance = savedConfig.getLong("land_start_balance", 0); + CONF.nationStartBalance = savedConfig.getLong("nation_start_balance", 0); + } +} diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java new file mode 100644 index 0000000..4bb4515 --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java @@ -0,0 +1,151 @@ +package net.laboulangerie.gringottslands; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; +import org.gestern.gringotts.Gringotts; +import org.gestern.gringotts.accountholder.AccountHolder; +import org.gestern.gringotts.api.dependency.Dependency; +import org.gestern.gringotts.event.PlayerVaultCreationEvent; + +import me.angeschossen.lands.api.LandsIntegration; +import me.angeschossen.lands.api.land.Land; +import me.angeschossen.lands.api.nation.Nation; +import net.laboulangerie.gringottslands.land.LandAccountHolder; +import net.laboulangerie.gringottslands.land.LandHolderProvider; +import net.laboulangerie.gringottslands.nation.NationAccountHolder; +import net.laboulangerie.gringottslands.nation.NationHolderProvider; + +public class LandsDependency implements Dependency, Listener { + private final NationHolderProvider nationHolderProvider; + private final LandHolderProvider landHolderProvider; + private final Gringotts gringotts; + private final Plugin plugin; + private final String id; + private final LandsIntegration api; + + /** + * Instantiates a new Lands dependency. + * + * @param gringotts the gringotts + * @param plugin the plugin + */ + public LandsDependency(Gringotts gringotts, Plugin plugin) { + if (plugin == null) { + throw new NullPointerException("'plugin' is null"); + } + + this.gringotts = gringotts; + this.plugin = plugin; + this.id = "lands"; + + this.api = LandsIntegration.of(plugin); + this.nationHolderProvider = new NationHolderProvider(this.api); + this.landHolderProvider = new LandHolderProvider(this.api); + + } + + /** + * Gets id. + * + * @return the id + */ + @Override + public String getId() { + return id; + } + + /** + * Gets plugin. + * + * @return the plugin + */ + @Override + public Plugin getPlugin() { + return this.plugin; + } + + /** + * On enable. + */ + @Override + public void onEnable() { + Bukkit.getPluginManager().registerEvents(this, this.gringotts); + Bukkit.getPluginManager().registerEvents(this.landHolderProvider, this.gringotts); + Bukkit.getPluginManager().registerEvents(this.nationHolderProvider, this.gringotts); + + Gringotts.instance.registerAccountHolderProvider(LandAccountHolder.ACCOUNT_TYPE, this.landHolderProvider); + Gringotts.instance.registerAccountHolderProvider(NationAccountHolder.ACCOUNT_TYPE, this.nationHolderProvider); + } + + /** + * Vault created. + * + * @param event the event + */ + @EventHandler + public void vaultCreated(PlayerVaultCreationEvent event) { + // some listener already claimed this event + if (event.isValid() || !this.isEnabled()) { + return; + } + + String line2String = event.getCause().getLine(2); + + if (line2String == null) { + return; + } + + Player player = event.getCause().getPlayer(); + + AccountHolder owner; + + if (event.getType().equals(LandsConfiguration.CONF.landSignTypeName)) { + if (!LandsPermissions.CREATE_VAULT_LAND.isAllowed(player)) { + player.sendMessage(LandsLanguage.LANG.noLandVaultPerm); + + return; + } + + Land land = this.api.getLandByName(line2String); + if (land == null) { + // TODO: no land found + // player.sendMessage(LandsLanguage.LANG.noLandResident); + return; + } + + owner = this.landHolderProvider.getAccountHolder(land); + } else if (event.getType().equals(LandsConfiguration.CONF.nationSignTypeName)) { + if (!LandsPermissions.CREATE_VAULT_NATION.isAllowed(player)) { + player.sendMessage(LandsLanguage.LANG.noNationVaultPerm); + + return; + } + + Nation nation = this.api.getNationByName(line2String); + if (nation == null) { + // TODO: no nation found + // player.sendMessage(LandsLanguage.LANG.notInNation); + return; + } + + owner = this.nationHolderProvider.getAccountHolder(nation); + } else { + return; + } + + if (owner == null) { + return; + } + + if (LandsConfiguration.CONF.vaultsOnlyInLands && this.api.getArea(event.getCause().getBlock().getLocation()) == null) { + event.getCause().getPlayer().sendMessage(LandsLanguage.LANG.vaultNotInLand); + return; + } + + event.setOwner(owner); + event.setValid(true); + } +} diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java b/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java new file mode 100644 index 0000000..a51a722 --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java @@ -0,0 +1,33 @@ +package net.laboulangerie.gringottslands; + +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.function.BiFunction; + +import static org.gestern.gringotts.Util.translateColors; + +public enum LandsLanguage { + LANG; + + public String noLandVaultPerm; + public String noLandResident; + public String noNationVaultPerm; + public String notInNation; + public String vaultNotInLand; + + public void readLanguage(FileConfiguration savedLanguage) { + BiFunction translator = (path, + def) -> translateColors(savedLanguage.getString(path, def)); + + LANG.noLandVaultPerm = translator.apply("noLandPerm", + "You do not have permission to create land vaults here."); + LANG.noLandResident = translator.apply("noLandResident", + "Cannot create land vault: You are not resident of a land."); + LANG.noNationVaultPerm = translator.apply("NoNationVaultPerm", + "You do not have permission to create nation vaults here."); + LANG.notInNation = translator.apply("notInNation", + "Cannot create nation vault: You do not belong to a nation."); + LANG.vaultNotInLand = translator.apply("vaultNotInLand", "You cannot create vaults outside of lands."); + + } +} diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsPermissions.java b/src/main/java/net/laboulangerie/gringottslands/LandsPermissions.java new file mode 100644 index 0000000..e1441f4 --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/LandsPermissions.java @@ -0,0 +1,37 @@ +package net.laboulangerie.gringottslands; + +import org.bukkit.entity.Player; + +/** + * The Permissions. + */ +public enum LandsPermissions { + /** + * Create vault land permissions. + */ + CREATE_VAULT_LAND("gringotts.createvault.land"), + /** + * Create vault nation permissions. + */ + CREATE_VAULT_NATION("gringotts.createvault.nation"); + + /** + * The Node. + */ + public final String node; + + LandsPermissions(String node) { + this.node = node; + } + + /** + * Check if a player has this permission. + * + * @param player player to check + * @return whether given player has this permission + */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public boolean isAllowed(Player player) { + return player.hasPermission(this.node); + } +} diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java b/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java new file mode 100644 index 0000000..acdd715 --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java @@ -0,0 +1,68 @@ +package net.laboulangerie.gringottslands.land; + +import me.angeschossen.lands.api.land.Land; + +import org.gestern.gringotts.accountholder.AccountHolder; + +public class LandAccountHolder implements AccountHolder { + public static final String ACCOUNT_TYPE = "land"; + private final Land land; + + /** + * Instantiates a new Land account holder. + * + * @param land the land + */ + LandAccountHolder(Land land) { + this.land = land; + } + + /** + * Return name of the account holder. + * + * @return name of the account holder + */ + @Override + public String getName() { + return this.land.getName(); + } + + /** + * Send message to the account holder. + * + * @param message to send + */ + @Override + public void sendMessage(String message) { + this.land.getOnlinePlayers().forEach(player -> player.sendMessage(message)); + } + + /** + * Type of the account holder. For instance "faction" or "player". + * + * @return account holder type + */ + @Override + public String getType() { + return ACCOUNT_TYPE; + } + + /** + * A unique identifier for the account holder. + * For players, this is simply the name. For factions, it is their id. + * + * @return unique account holder id + */ + @Override + public String getId() { + return this.land.getULID().toString(); + } + + /** + * The town onwing this account + * @return town object + */ + public Land getLand() { + return this.land; + } +} diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java new file mode 100644 index 0000000..06033b7 --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -0,0 +1,165 @@ +package net.laboulangerie.gringottslands.land; + +import me.angeschossen.lands.api.LandsIntegration; +import me.angeschossen.lands.api.applicationframework.util.ULID; +import me.angeschossen.lands.api.events.LandRenameEvent; +import me.angeschossen.lands.api.land.Land; +import me.angeschossen.lands.api.memberholder.MemberHolder; +import me.angeschossen.lands.api.player.LandPlayer; + +import org.bukkit.OfflinePlayer; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.gestern.gringotts.AccountChest; +import org.gestern.gringotts.Gringotts; +import org.gestern.gringotts.GringottsAccount; +import org.gestern.gringotts.accountholder.AccountHolder; +import org.gestern.gringotts.accountholder.AccountHolderProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +public class LandHolderProvider implements AccountHolderProvider, Listener { + + private LandsIntegration api; + + public LandHolderProvider(LandsIntegration api) { + this.api = api; + } + + /** + * Get the AccountHolder object mapped to the given id for this provider. + * + * @param ulid id of account holder + * @return account holder for id + */ + public @Nullable AccountHolder getAccountHolder(@NotNull ULID ulid) { + Land land = this.api.getLandByULID(ulid); + + return getAccountHolder(land); + } + + /** + * Get the AccountHolder object mapped to the given id for this provider. + * + * @param id id of account holder + * @return account holder for id + */ + @Override + public @Nullable AccountHolder getAccountHolder(@NotNull String id) { + try { + ULID targetUlid = ULID.fromString(id); + + return getAccountHolder(targetUlid); + } catch (IllegalArgumentException ignored) {} + + String vaultPrefix = LandAccountHolder.ACCOUNT_TYPE + "-"; + String validId = id.startsWith(vaultPrefix) ? id.substring(vaultPrefix.length()) : id; + + return getAccountHolder(ULID.fromString(validId)); + } + + /** + * Get the AccountHolder object mapped to the given id for this provider. + * + * @param uuid id of account holder + * @return account holder for id + */ + @Override + public @Nullable AccountHolder getAccountHolder(@NotNull UUID uuid) { + return null; + } + + /** + * Get a AccountHolder for the land of which player is a resident, if any. + * + * @param player player to get town for + * @return AccountHolder for the land of which player is a resident, if + * any. null otherwise. + */ + @Override + public @Nullable AccountHolder getAccountHolder(@NotNull OfflinePlayer player) { + LandPlayer resident = this.api.getLandPlayer(player.getUniqueId()); + if (resident == null) return null; + + + // resident.getLands().stream().f + + return null; + } + + /** + * Gets type. + * + * @return the type + */ + @Override + public String getType() { + return LandAccountHolder.ACCOUNT_TYPE; + } + + /** + * Gets account names. + * + * @return the account names + */ + @Override + public @NotNull Set getAccountNames() { + return this.api.getLands().stream().map(MemberHolder::getName).collect(Collectors.toSet()); + } + + /** + * Gets account holder. + * + * @param town the town + * @return the account holder + */ + public @Nullable AccountHolder getAccountHolder(@Nullable Land land) { + if (land == null) { + return null; + } + + return new LandAccountHolder(land); + } + + /** + * Rename town. + * + * @param event the event + */ + @EventHandler + public void renameLand(LandRenameEvent event) { + Land land = event.getLand(); + + AccountHolder holder = getAccountHolder(land); + + if (holder == null) { + return; + } + + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + + if (account == null) { + return; + } + + Gringotts.instance.getDao().retrieveChests(account).forEach(AccountChest::updateSign); + } + + /** + * Calculate start balance. + * + * @param event the event + */ + // @EventHandler + // public void calculateStartBalance(CalculateStartBalanceEvent event) { + // if (!event.holder.getType().equals(getType())) { + // return; + // } + + // event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.townStartBalance); + // } +} diff --git a/src/main/java/net/laboulangerie/gringottslands/nation/NationAccountHolder.java b/src/main/java/net/laboulangerie/gringottslands/nation/NationAccountHolder.java new file mode 100644 index 0000000..96231f9 --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/nation/NationAccountHolder.java @@ -0,0 +1,71 @@ +package net.laboulangerie.gringottslands.nation; + +import me.angeschossen.lands.api.nation.Nation; + +import org.gestern.gringotts.accountholder.AccountHolder; + +/** + * The type Nation account holder. + */ +public class NationAccountHolder implements AccountHolder { + public static final String ACCOUNT_TYPE = "nation"; + private final Nation nation; + + /** + * Instantiates a new Nation account holder. + * + * @param nation the nation + */ + NationAccountHolder(Nation nation) { + this.nation = nation; + } + + /** + * Return name of the account holder. + * + * @return name of the account holder + */ + @Override + public String getName() { + return this.nation.getName(); + } + + /** + * Send message to the account holder. + * + * @param message to send + */ + @Override + public void sendMessage(String message) { + this.nation.getOnlinePlayers().forEach(player -> player.sendMessage(message)); + } + + /** + * Type of the account holder. For instance "faction" or "player". + * + * @return account holder type + */ + @Override + public String getType() { + return ACCOUNT_TYPE; + } + + /** + * A unique identifier for the account holder. + * For players, this is simply the name. For factions, it is their id. + * + * @return unique account holder id + */ + @Override + public String getId() { + return this.nation.getULID().toString(); + } + + /** + * The nation onwing this account + * @return nation object + */ + public Nation getNation() { + return nation; + } +} diff --git a/src/main/java/net/laboulangerie/gringottslands/nation/NationHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/nation/NationHolderProvider.java new file mode 100644 index 0000000..91d9fec --- /dev/null +++ b/src/main/java/net/laboulangerie/gringottslands/nation/NationHolderProvider.java @@ -0,0 +1,168 @@ +package net.laboulangerie.gringottslands.nation; + +import me.angeschossen.lands.api.LandsIntegration; +import me.angeschossen.lands.api.applicationframework.util.ULID; +import me.angeschossen.lands.api.events.nation.edit.NationRenameEvent; +import me.angeschossen.lands.api.memberholder.MemberHolder; +import me.angeschossen.lands.api.nation.Nation; +import me.angeschossen.lands.api.player.LandPlayer; + +import org.bukkit.OfflinePlayer; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.gestern.gringotts.AccountChest; +import org.gestern.gringotts.Gringotts; +import org.gestern.gringotts.GringottsAccount; +import org.gestern.gringotts.accountholder.AccountHolder; +import org.gestern.gringotts.accountholder.AccountHolderProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * The type Nation holder provider. + */ +public class NationHolderProvider implements AccountHolderProvider, Listener { + + private LandsIntegration api; + + public NationHolderProvider(LandsIntegration api) { + this.api = api; + } + + /** + * Get the AccountHolder object mapped to the given id for this provider. + * + * @param ulid id of account holder + * @return account holder for id + */ + public @Nullable AccountHolder getAccountHolder(@NotNull ULID ulid) { + Nation nation = this.api.getNationByULID(ulid); + + return getAccountHolder(nation); + } + + /** + * Get the AccountHolder object mapped to the given id for this provider. + * + * @param id id of account holder + * @return account holder for id + */ + @Override + public @Nullable AccountHolder getAccountHolder(@NotNull String id) { + try { + ULID targetUlid = ULID.fromString(id); + + return getAccountHolder(targetUlid); + } catch (IllegalArgumentException ignored) {} + + String vaultPrefix = NationAccountHolder.ACCOUNT_TYPE + "-"; + String validId = id.startsWith(vaultPrefix) ? id.substring(vaultPrefix.length()) : id; + + return getAccountHolder(ULID.fromString(validId)); + } + + /** + * Get the AccountHolder object mapped to the given id for this provider. + * + * @param uuid id of account holder + * @return account holder for id + */ + @Override + public @Nullable AccountHolder getAccountHolder(@NotNull UUID uuid) { + return null; + } + + /** + * Get a AccountHolder for the nation of which player is a resident, if + * any. + * + * @param player player to get nation for + * @return AccountHolder for the nation of which player is a resident, if + * any. null otherwise. + */ + @Override + public @Nullable AccountHolder getAccountHolder(@NotNull OfflinePlayer player) { + LandPlayer resident = this.api.getLandPlayer(player.getUniqueId()); + if (resident == null) return null; + + // resident.getLands().stream().f + + return null; + } + + /** + * Gets type. + * + * @return the type + */ + @Override + public String getType() { + return NationAccountHolder.ACCOUNT_TYPE; + } + + /** + * Gets account names. + * + * @return the account names + */ + @Override + public @NotNull Set getAccountNames() { + return this.api.getNations().stream().map(MemberHolder::getName).collect(Collectors.toSet()); + } + + /** + * Gets account holder. + * + * @param nation the nation + * @return the account holder + */ + public @Nullable AccountHolder getAccountHolder(@Nullable Nation nation) { + if (nation == null) { + return null; + } + + return new NationAccountHolder(nation); + } + + /** + * Rename nation. + * + * @param event the event + */ + @EventHandler + public void renameNation(NationRenameEvent event) { + Nation nation = event.getNation(); + + AccountHolder holder = this.getAccountHolder(nation); + + if (holder == null) { + return; + } + + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + + if (account == null) { + return; + } + + Gringotts.instance.getDao().retrieveChests(account).forEach(AccountChest::updateSign); + } + + /** + * Calculate start balance. + * + * @param event the event + */ + // @EventHandler + // public void calculateStartBalance(CalculateStartBalanceEvent event) { + // if (!event.holder.getType().equals(getType())) { + // return; + // } + + // event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.nationStartBalance); + // } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..5c63d8b --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,10 @@ +# supported languages: "custom" (default, english), "de" (german), "fr" (french), and "pt-BR" (brazilian portuguese). +language: custom + +# changes the required sign name for the creation of town/nation vaults +# Example: [town vault] +land_sign_vault_name: 'land' +nation_sign_vault_name: 'nation' + +# Prevents players from creating a vault outside a town if set to true +vaults_only_in_lands: false diff --git a/src/main/resources/i18n/messages_de.yml b/src/main/resources/i18n/messages_de.yml new file mode 100644 index 0000000..8c762de --- /dev/null +++ b/src/main/resources/i18n/messages_de.yml @@ -0,0 +1,4 @@ +noLandVaultPerm: "Du kannst hier keinen Town-Tresor erstellen." +noLandResident: "Du kannst keine Town-Tresor erstellen, weil du nicht Bürger einer Town bist." +noNationVaultPerm: "Du kannst hier keine Nation-Tresore erstellen." +notInNation: "Du kannst keine Nation-Tresore erstellen, weil du nicht Bürger einer Nation bist" diff --git a/src/main/resources/i18n/messages_fr.yml b/src/main/resources/i18n/messages_fr.yml new file mode 100644 index 0000000..5abfd48 --- /dev/null +++ b/src/main/resources/i18n/messages_fr.yml @@ -0,0 +1,6 @@ +noLandVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de ville ici." +noLandResident: "Impossible de créer un coffre-fort de ville : Vous n'êtes pas résident d'une ville." +noNationVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de nation ici." +notInNation: "Impossible de créer un coffre-fort de nation : Vous n'appartenez pas à une nation." +vaultNotInLand: "Vous ne pouvez pas créer de coffre-fort en dehors des villes." +tooManyVaults: "Vous ne pouvez pas créer plus de coffre-fort ! Max : %max" diff --git a/src/main/resources/i18n/messages_pt-BR.yml b/src/main/resources/i18n/messages_pt-BR.yml new file mode 100644 index 0000000..d2ac5ef --- /dev/null +++ b/src/main/resources/i18n/messages_pt-BR.yml @@ -0,0 +1,4 @@ +noLandVaultPerm: "Você não tem permissão para criar cofres de cidade aqui." +noLandResident: "Não é possível criar cofre de cidade: Você não pertence a uma cidade." +noNationVaultPerm: "Você não tem permissão para criar cofres de nação aqui." +notInNation: "Não é possível criar cofre de nação: Você não pertence a uma nação." diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml new file mode 100644 index 0000000..02024dc --- /dev/null +++ b/src/main/resources/messages.yml @@ -0,0 +1,5 @@ +noLandVaultPerm: "You do not have permission to create town vaults here." +noLandResident: "Cannot create town vault: You are not resident of a town." +noNationVaultPerm: "You do not have permission to create nation vaults here." +notInNation: "Cannot create nation vault: You do not belong to a nation." +vaultNotInLand: "You cannot create vaults outside of towns." diff --git a/target/classes/config.yml b/target/classes/config.yml new file mode 100644 index 0000000..5c63d8b --- /dev/null +++ b/target/classes/config.yml @@ -0,0 +1,10 @@ +# supported languages: "custom" (default, english), "de" (german), "fr" (french), and "pt-BR" (brazilian portuguese). +language: custom + +# changes the required sign name for the creation of town/nation vaults +# Example: [town vault] +land_sign_vault_name: 'land' +nation_sign_vault_name: 'nation' + +# Prevents players from creating a vault outside a town if set to true +vaults_only_in_lands: false diff --git a/target/classes/i18n/messages_de.yml b/target/classes/i18n/messages_de.yml new file mode 100644 index 0000000..8c762de --- /dev/null +++ b/target/classes/i18n/messages_de.yml @@ -0,0 +1,4 @@ +noLandVaultPerm: "Du kannst hier keinen Town-Tresor erstellen." +noLandResident: "Du kannst keine Town-Tresor erstellen, weil du nicht Bürger einer Town bist." +noNationVaultPerm: "Du kannst hier keine Nation-Tresore erstellen." +notInNation: "Du kannst keine Nation-Tresore erstellen, weil du nicht Bürger einer Nation bist" diff --git a/target/classes/i18n/messages_fr.yml b/target/classes/i18n/messages_fr.yml new file mode 100644 index 0000000..5abfd48 --- /dev/null +++ b/target/classes/i18n/messages_fr.yml @@ -0,0 +1,6 @@ +noLandVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de ville ici." +noLandResident: "Impossible de créer un coffre-fort de ville : Vous n'êtes pas résident d'une ville." +noNationVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de nation ici." +notInNation: "Impossible de créer un coffre-fort de nation : Vous n'appartenez pas à une nation." +vaultNotInLand: "Vous ne pouvez pas créer de coffre-fort en dehors des villes." +tooManyVaults: "Vous ne pouvez pas créer plus de coffre-fort ! Max : %max" diff --git a/target/classes/i18n/messages_pt-BR.yml b/target/classes/i18n/messages_pt-BR.yml new file mode 100644 index 0000000..d2ac5ef --- /dev/null +++ b/target/classes/i18n/messages_pt-BR.yml @@ -0,0 +1,4 @@ +noLandVaultPerm: "Você não tem permissão para criar cofres de cidade aqui." +noLandResident: "Não é possível criar cofre de cidade: Você não pertence a uma cidade." +noNationVaultPerm: "Você não tem permissão para criar cofres de nação aqui." +notInNation: "Não é possível criar cofre de nação: Você não pertence a uma nação." diff --git a/target/classes/messages.yml b/target/classes/messages.yml new file mode 100644 index 0000000..02024dc --- /dev/null +++ b/target/classes/messages.yml @@ -0,0 +1,5 @@ +noLandVaultPerm: "You do not have permission to create town vaults here." +noLandResident: "Cannot create town vault: You are not resident of a town." +noNationVaultPerm: "You do not have permission to create nation vaults here." +notInNation: "Cannot create nation vault: You do not belong to a nation." +vaultNotInLand: "You cannot create vaults outside of towns." diff --git a/target/classes/net/laboulangerie/gringottslands/GringottsLand.class b/target/classes/net/laboulangerie/gringottslands/GringottsLand.class deleted file mode 100644 index 1b549b8d6632f9a65929320d58d7c52b7844e931..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 zcmb7A%TB{E5FDpz(}X}udE9#g4mA?T0vBEqiVza0cc-<2X|R!#@L!yeIPd{{6k=U9 zLZDo@%>Qe-tl*UlZIeIYaMQX;qyvboTbA4E~v!%LpBWF}mn6B&pK!rhdw# zy%$*_8HTBuiDD|Oa(pHF)q^S-4%7d|oG|o_zR=FeZ5_nea9cy8&sEu|TQN4B8r_-N z&g7+9#`tyb*d2xu=nncc5HgpaFd)XMGOFE!H}qer@emQZXA-eS7_a&m>%^FgLFk5$ js5ZmN&u~O0KnS0#+6*Xhi^1@(K|%(DR)cM__ptK~l__Hz diff --git a/target/classes/net/laboulangerie/gringottslands/GringottsLands.class b/target/classes/net/laboulangerie/gringottslands/GringottsLands.class new file mode 100644 index 0000000000000000000000000000000000000000..320e0023030e7dd8c80c51758a99439885b8618e GIT binary patch literal 4485 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 literal 0 HcmV?d00001 diff --git a/target/classes/net/laboulangerie/gringottslands/LandsDependency.class b/target/classes/net/laboulangerie/gringottslands/LandsDependency.class new file mode 100644 index 0000000000000000000000000000000000000000..e2982a941d8040bd5387397ddfa2a06714c2f195 GIT binary patch literal 5465 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 PDqTj=|IR}L_{V<%t2bMC literal 0 HcmV?d00001 diff --git a/target/classes/net/laboulangerie/gringottslands/LandsLanguage.class b/target/classes/net/laboulangerie/gringottslands/LandsLanguage.class new file mode 100644 index 0000000000000000000000000000000000000000..f8e2597824a60a2d6bee5b6932c2b94097342835 GIT binary patch literal 3290 zcmbVOYj@K|5WR~->^K69p@xK)N&}6Z5R>vKkPt#b0x6E6n3$&Y!P;IcB8uedkv4tN z{-YL73#F$VKKJy$^dIzeb|tX#fZ~49YDY7(bLY;^=+A$iJ_B$OKPIt_VZ;`G(c(2H zu()jq*Azv=HEqN3eUBs!uUL{#dKdvWL=s&LJMZ&VPDZv-oUwxyhOW}(@>PbDrOup< zG3>G(>A%VY%fBgH@|7*My;po03aRZ3)ouyTYzW(D*ljyy?wgJsv+T7Uf6flYWU?xK zmZeCZz|cEWUYH-KUM?-nR2W9@b{=eMyl$Dc=}#~u2J=MxldgXRj}c)<(9>A{lY8pT?$ylnc#x??v@BXCuYicQlJ#aVhx$Him$YL+VDsD^hi zz_6XSTGkrFt^eUDL>l;}Rcr=!T@q8AGH0XLu@sIoq(crR%P9;poLzJRz2WG@n!dzW zh2Eksrst8Z?mK#&;Q2zQDr@M9N>5)Bt{CY>0mDfQF&t8b@~T56suK+7;w;>#-4}I# zEXGSD$!``VQDn$$tVPM$sD>m`DfFapn&JF3w>O z@q|amZUL3%MT`4OG_o3kcu!ZHz^w~84CIWF_w&UJ8Ijx&w2Eoatq)vMn2P0B@-^OR zg~-d0nQ|Q8qxf6%!e4S4UK%a9NqoU@v|SFSz3MCr`rDAzK#IJ{>vX}_GX!47vkz~{xLlA^|o4HOjBvFy9QA)ml=jQoO=O7vd#R9kdLiQdni zZ;Qs1=wf!FEt*uKsqA!HG$X@HC|nbi5MU1_GDq0<(JqI6?5Du`aFo^)v^zzbXK0-y znlMR<)Bogyf)1!7 z>w1Ci>~N<6LBstn!BuhXe~daIDy$mF*&sq8a` z>CAtVCm62%!<0?sSJtu&4prNh7=oGe#yOJ-BJ|w^m7k|1Tzz07=S4LK)Y^_?7^t@P7tUYOEQ7MSJ z%wsF*gB^Fc&Jl)CD|vs!+!f$~m&P}DWP`yg8!1K6-bvdG!{LmkSK_7G-kxm6CDoM8 zdVF0G>yn;`Z2A$!xEo^(eOI9bOd!V4u_HDailL{4n#d+?bKl~o?O)xOPzRz?lSt}Z zIMU9i_hANeZp<JjOi3Y%}MwA{s`bg~OUs{G`%x@#VCdUY4HA+$cR4k9UkO zfo9Ih6|!7SCrtVRN3sp!3yGyka;%;HdK^pr-0uM0$;g!H=9U8j1KiFOJ1G{>LHJIJ zN)+?o)HkqVu*)6{93yyykQMehg8f!F==@Hv?S}~EijG4J=8iD@k*aLCN!O6Y;iY~8 zx`;W10B%s1TNZ+&==?VNy(ERPJG7bIa8-KLoey>Bdz@wLx}1Lk9*cM z{E5$FC%*d#H&_=5!%_aR=qHSRLBxjlR&y@TMId0LiOhdS=0_Y4=)D({m}-#C(KvjS zp+gK8U)iIl#U!78)joKF>G2O2c-h&QUUJTp21k_S@UFffi=H6y1MKQL8x}0iMJ!qO F)NjXmh7te( literal 0 HcmV?d00001 diff --git a/target/classes/net/laboulangerie/gringottslands/land/LandAccountHolder.class b/target/classes/net/laboulangerie/gringottslands/land/LandAccountHolder.class new file mode 100644 index 0000000000000000000000000000000000000000..6543cf1bcb1530cd2ec7ef49c6a2d37b6e5f9d28 GIT binary patch literal 2181 zcmbVMYjfK~6g_Jvk!#D1>&BrETKY&@+o4rk3ZZpcNZf=3oChQ^lrPNM-q@;Ttw&my z$-jab9+Q6H2Qd65hP#p)E6!swe9&We?>T$!xp(*Pf8YHD;01m(kYJd1g|ZypkOPOi zZQ&zBXjuR$5PmAzPKMueht~+!=@z zG7Mu{9K&p_CoC=BZ+4{b3pWt$TfA=%;oW6ItXL zlEqT}0vM)DWMDE()@)a740;XW?eK;pw0ha(PMv$U9!Ha7s$=^M&uahEaFTDdh1%df z+F`0#I_^*gAL6Eg8w_{PVTXyUxWNU-T7q$4Og+y9W5Zfg7NS$n^(3 z;Z-sy<6{GJly=Y+BiopGfQMwxp7fS^v%_#J+Tj#BT~wp@K4b0a&VHYAAE&>ymd^DP z6HoDJ==W}I?G?iUrFgohyx({1Cf7Odc~qaDrPsBB-8H(Rn`hp{=i2U+l3_oG?D|+S z+&`0Dw|H>=r~^_C?=@O{<`IK+f{!(Q@*0C~*H)Hrm96%zuu2tO#FzNez!y}n)1pj# zgj-aqeo$G4Yp3%uq_^e3Yl;w+e}kSZF4D>*{jJbig1+hUpU9Qxe#hlsX_P>L-WQ1r$YBhZh$W9{8cm1M_yAXE zM7V&J5gXlG5$99-GQC#*4VMpao#7W6g`5+?%JqQD45K10rrVrmw5oNA)~X62!)=DS zcbEkZP)cAZFdYQVVhZd$um5UQnMnGaZNG`UW$RoLvSvw`z!)KiF`@Tl@IVDZbj(pYz&{m jB9;i3L^W{#6_)9%J+IN+2EN5Mc4$U7^De%}Yh3*g#(Wn* literal 0 HcmV?d00001 diff --git a/target/classes/net/laboulangerie/gringottslands/land/LandHolderProvider.class b/target/classes/net/laboulangerie/gringottslands/land/LandHolderProvider.class new file mode 100644 index 0000000000000000000000000000000000000000..87d03495673f68295dc6e8f9144be884ecc28baa GIT binary patch literal 6176 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 Date: Thu, 21 Nov 2024 19:19:20 +0100 Subject: [PATCH 02/14] Update Gringotts dependency --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index e326d6e..c1f29a8 100644 --- a/pom.xml +++ b/pom.xml @@ -46,9 +46,9 @@ provided - com.github.nikosgram - gringotts - 2.12.3 + com.github.LaBoulangerie + Gringotts + dev-2b46a143f4-1 provided From 7f86462ee0269955fecbd63683b6114961eb40b9 Mon Sep 17 00:00:00 2001 From: Clem Fern Date: Thu, 21 Nov 2024 19:26:02 +0100 Subject: [PATCH 03/14] wip 2 --- .gitignore | 1 + .../gringottslands/LandsConfiguration.java | 3 - .../gringottslands/LandsDependency.java | 22 --- .../land/LandAccountHolder.java | 5 + .../land/LandHolderProvider.java | 23 ++- .../nation/NationAccountHolder.java | 71 -------- .../nation/NationHolderProvider.java | 168 ------------------ target/classes/config.yml | 10 -- target/classes/i18n/messages_de.yml | 4 - target/classes/i18n/messages_fr.yml | 6 - target/classes/i18n/messages_pt-BR.yml | 4 - target/classes/messages.yml | 5 - .../gringottslands/GringottsLands.class | Bin 4485 -> 0 bytes .../gringottslands/LandsConfiguration.class | Bin 2114 -> 0 bytes .../gringottslands/LandsDependency.class | Bin 5465 -> 0 bytes .../gringottslands/LandsLanguage.class | Bin 3290 -> 0 bytes .../gringottslands/LandsPermissions.class | Bin 1606 -> 0 bytes .../land/LandAccountHolder.class | Bin 2181 -> 0 bytes .../land/LandHolderProvider.class | Bin 6176 -> 0 bytes .../nation/NationAccountHolder.class | Bin 2211 -> 0 bytes .../nation/NationHolderProvider.class | Bin 6272 -> 0 bytes target/classes/plugin.yml | 6 - target/gringotts-lands.jar | Bin 19898 -> 0 bytes target/maven-archiver/pom.properties | 5 - .../compile/default-compile/createdFiles.lst | 0 .../compile/default-compile/inputFiles.lst | 9 - 26 files changed, 21 insertions(+), 321 deletions(-) create mode 100644 .gitignore delete mode 100644 src/main/java/net/laboulangerie/gringottslands/nation/NationAccountHolder.java delete mode 100644 src/main/java/net/laboulangerie/gringottslands/nation/NationHolderProvider.java delete mode 100644 target/classes/config.yml delete mode 100644 target/classes/i18n/messages_de.yml delete mode 100644 target/classes/i18n/messages_fr.yml delete mode 100644 target/classes/i18n/messages_pt-BR.yml delete mode 100644 target/classes/messages.yml delete mode 100644 target/classes/net/laboulangerie/gringottslands/GringottsLands.class delete mode 100644 target/classes/net/laboulangerie/gringottslands/LandsConfiguration.class delete mode 100644 target/classes/net/laboulangerie/gringottslands/LandsDependency.class delete mode 100644 target/classes/net/laboulangerie/gringottslands/LandsLanguage.class delete mode 100644 target/classes/net/laboulangerie/gringottslands/LandsPermissions.class delete mode 100644 target/classes/net/laboulangerie/gringottslands/land/LandAccountHolder.class delete mode 100644 target/classes/net/laboulangerie/gringottslands/land/LandHolderProvider.class delete mode 100644 target/classes/net/laboulangerie/gringottslands/nation/NationAccountHolder.class delete mode 100644 target/classes/net/laboulangerie/gringottslands/nation/NationHolderProvider.class delete mode 100644 target/classes/plugin.yml delete mode 100644 target/gringotts-lands.jar delete mode 100644 target/maven-archiver/pom.properties delete mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst delete mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f97022 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target/ \ No newline at end of file diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java index 69b06cf..7033ffb 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java @@ -11,7 +11,6 @@ public enum LandsConfiguration { */ public String language = "custom"; public String landSignTypeName = "land"; - public String nationSignTypeName = "nation"; public boolean vaultsOnlyInLands = false; public long landStartBalance = 0; @@ -20,9 +19,7 @@ public enum LandsConfiguration { public void readConfig(FileConfiguration savedConfig) { CONF.language = savedConfig.getString("language", "custom"); CONF.landSignTypeName = savedConfig.getString("land_sign_type_name", "land"); - CONF.nationSignTypeName = savedConfig.getString("nation_sign_type_name", "nation"); CONF.vaultsOnlyInLands = savedConfig.getBoolean("vaults_only_in_lands", false); CONF.landStartBalance = savedConfig.getLong("land_start_balance", 0); - CONF.nationStartBalance = savedConfig.getLong("nation_start_balance", 0); } } diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java index 4bb4515..c343e31 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java @@ -12,14 +12,10 @@ import me.angeschossen.lands.api.LandsIntegration; import me.angeschossen.lands.api.land.Land; -import me.angeschossen.lands.api.nation.Nation; import net.laboulangerie.gringottslands.land.LandAccountHolder; import net.laboulangerie.gringottslands.land.LandHolderProvider; -import net.laboulangerie.gringottslands.nation.NationAccountHolder; -import net.laboulangerie.gringottslands.nation.NationHolderProvider; public class LandsDependency implements Dependency, Listener { - private final NationHolderProvider nationHolderProvider; private final LandHolderProvider landHolderProvider; private final Gringotts gringotts; private final Plugin plugin; @@ -42,7 +38,6 @@ public LandsDependency(Gringotts gringotts, Plugin plugin) { this.id = "lands"; this.api = LandsIntegration.of(plugin); - this.nationHolderProvider = new NationHolderProvider(this.api); this.landHolderProvider = new LandHolderProvider(this.api); } @@ -74,10 +69,8 @@ public Plugin getPlugin() { public void onEnable() { Bukkit.getPluginManager().registerEvents(this, this.gringotts); Bukkit.getPluginManager().registerEvents(this.landHolderProvider, this.gringotts); - Bukkit.getPluginManager().registerEvents(this.nationHolderProvider, this.gringotts); Gringotts.instance.registerAccountHolderProvider(LandAccountHolder.ACCOUNT_TYPE, this.landHolderProvider); - Gringotts.instance.registerAccountHolderProvider(NationAccountHolder.ACCOUNT_TYPE, this.nationHolderProvider); } /** @@ -117,21 +110,6 @@ public void vaultCreated(PlayerVaultCreationEvent event) { } owner = this.landHolderProvider.getAccountHolder(land); - } else if (event.getType().equals(LandsConfiguration.CONF.nationSignTypeName)) { - if (!LandsPermissions.CREATE_VAULT_NATION.isAllowed(player)) { - player.sendMessage(LandsLanguage.LANG.noNationVaultPerm); - - return; - } - - Nation nation = this.api.getNationByName(line2String); - if (nation == null) { - // TODO: no nation found - // player.sendMessage(LandsLanguage.LANG.notInNation); - return; - } - - owner = this.nationHolderProvider.getAccountHolder(nation); } else { return; } diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java b/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java index acdd715..8c42e3a 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java @@ -65,4 +65,9 @@ public String getId() { public Land getLand() { return this.land; } + + @Override + public boolean hasPermission(String arg0) { + return false; + } } diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index 06033b7..e2ae3bb 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -6,15 +6,18 @@ import me.angeschossen.lands.api.land.Land; import me.angeschossen.lands.api.memberholder.MemberHolder; import me.angeschossen.lands.api.player.LandPlayer; +import net.laboulangerie.gringottslands.LandsConfiguration; import org.bukkit.OfflinePlayer; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.gestern.gringotts.AccountChest; +import org.gestern.gringotts.Configuration; import org.gestern.gringotts.Gringotts; import org.gestern.gringotts.GringottsAccount; import org.gestern.gringotts.accountholder.AccountHolder; import org.gestern.gringotts.accountholder.AccountHolderProvider; +import org.gestern.gringotts.event.CalculateStartBalanceEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,6 +40,7 @@ public LandHolderProvider(LandsIntegration api) { * @return account holder for id */ public @Nullable AccountHolder getAccountHolder(@NotNull ULID ulid) { + System.out.println("LandHolderProvider.getAccountHolder ULID " + ulid); Land land = this.api.getLandByULID(ulid); return getAccountHolder(land); @@ -50,6 +54,7 @@ public LandHolderProvider(LandsIntegration api) { */ @Override public @Nullable AccountHolder getAccountHolder(@NotNull String id) { + System.out.println("LandHolderProvider.getAccountHolder String " + id); try { ULID targetUlid = ULID.fromString(id); @@ -70,6 +75,7 @@ public LandHolderProvider(LandsIntegration api) { */ @Override public @Nullable AccountHolder getAccountHolder(@NotNull UUID uuid) { + System.out.println("LandHolderProvider.getAccountHolder UUID " + uuid); return null; } @@ -82,6 +88,7 @@ public LandHolderProvider(LandsIntegration api) { */ @Override public @Nullable AccountHolder getAccountHolder(@NotNull OfflinePlayer player) { + System.out.println("LandHolderProvider.getAccountHolder OfflinePlayer " + player); LandPlayer resident = this.api.getLandPlayer(player.getUniqueId()); if (resident == null) return null; @@ -154,12 +161,12 @@ public void renameLand(LandRenameEvent event) { * * @param event the event */ - // @EventHandler - // public void calculateStartBalance(CalculateStartBalanceEvent event) { - // if (!event.holder.getType().equals(getType())) { - // return; - // } - - // event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.townStartBalance); - // } + @EventHandler + public void calculateStartBalance(CalculateStartBalanceEvent event) { + if (!event.holder.getType().equals(getType())) { + return; + } + + event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.landStartBalance); + } } diff --git a/src/main/java/net/laboulangerie/gringottslands/nation/NationAccountHolder.java b/src/main/java/net/laboulangerie/gringottslands/nation/NationAccountHolder.java deleted file mode 100644 index 96231f9..0000000 --- a/src/main/java/net/laboulangerie/gringottslands/nation/NationAccountHolder.java +++ /dev/null @@ -1,71 +0,0 @@ -package net.laboulangerie.gringottslands.nation; - -import me.angeschossen.lands.api.nation.Nation; - -import org.gestern.gringotts.accountholder.AccountHolder; - -/** - * The type Nation account holder. - */ -public class NationAccountHolder implements AccountHolder { - public static final String ACCOUNT_TYPE = "nation"; - private final Nation nation; - - /** - * Instantiates a new Nation account holder. - * - * @param nation the nation - */ - NationAccountHolder(Nation nation) { - this.nation = nation; - } - - /** - * Return name of the account holder. - * - * @return name of the account holder - */ - @Override - public String getName() { - return this.nation.getName(); - } - - /** - * Send message to the account holder. - * - * @param message to send - */ - @Override - public void sendMessage(String message) { - this.nation.getOnlinePlayers().forEach(player -> player.sendMessage(message)); - } - - /** - * Type of the account holder. For instance "faction" or "player". - * - * @return account holder type - */ - @Override - public String getType() { - return ACCOUNT_TYPE; - } - - /** - * A unique identifier for the account holder. - * For players, this is simply the name. For factions, it is their id. - * - * @return unique account holder id - */ - @Override - public String getId() { - return this.nation.getULID().toString(); - } - - /** - * The nation onwing this account - * @return nation object - */ - public Nation getNation() { - return nation; - } -} diff --git a/src/main/java/net/laboulangerie/gringottslands/nation/NationHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/nation/NationHolderProvider.java deleted file mode 100644 index 91d9fec..0000000 --- a/src/main/java/net/laboulangerie/gringottslands/nation/NationHolderProvider.java +++ /dev/null @@ -1,168 +0,0 @@ -package net.laboulangerie.gringottslands.nation; - -import me.angeschossen.lands.api.LandsIntegration; -import me.angeschossen.lands.api.applicationframework.util.ULID; -import me.angeschossen.lands.api.events.nation.edit.NationRenameEvent; -import me.angeschossen.lands.api.memberholder.MemberHolder; -import me.angeschossen.lands.api.nation.Nation; -import me.angeschossen.lands.api.player.LandPlayer; - -import org.bukkit.OfflinePlayer; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.gestern.gringotts.AccountChest; -import org.gestern.gringotts.Gringotts; -import org.gestern.gringotts.GringottsAccount; -import org.gestern.gringotts.accountholder.AccountHolder; -import org.gestern.gringotts.accountholder.AccountHolderProvider; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - -/** - * The type Nation holder provider. - */ -public class NationHolderProvider implements AccountHolderProvider, Listener { - - private LandsIntegration api; - - public NationHolderProvider(LandsIntegration api) { - this.api = api; - } - - /** - * Get the AccountHolder object mapped to the given id for this provider. - * - * @param ulid id of account holder - * @return account holder for id - */ - public @Nullable AccountHolder getAccountHolder(@NotNull ULID ulid) { - Nation nation = this.api.getNationByULID(ulid); - - return getAccountHolder(nation); - } - - /** - * Get the AccountHolder object mapped to the given id for this provider. - * - * @param id id of account holder - * @return account holder for id - */ - @Override - public @Nullable AccountHolder getAccountHolder(@NotNull String id) { - try { - ULID targetUlid = ULID.fromString(id); - - return getAccountHolder(targetUlid); - } catch (IllegalArgumentException ignored) {} - - String vaultPrefix = NationAccountHolder.ACCOUNT_TYPE + "-"; - String validId = id.startsWith(vaultPrefix) ? id.substring(vaultPrefix.length()) : id; - - return getAccountHolder(ULID.fromString(validId)); - } - - /** - * Get the AccountHolder object mapped to the given id for this provider. - * - * @param uuid id of account holder - * @return account holder for id - */ - @Override - public @Nullable AccountHolder getAccountHolder(@NotNull UUID uuid) { - return null; - } - - /** - * Get a AccountHolder for the nation of which player is a resident, if - * any. - * - * @param player player to get nation for - * @return AccountHolder for the nation of which player is a resident, if - * any. null otherwise. - */ - @Override - public @Nullable AccountHolder getAccountHolder(@NotNull OfflinePlayer player) { - LandPlayer resident = this.api.getLandPlayer(player.getUniqueId()); - if (resident == null) return null; - - // resident.getLands().stream().f - - return null; - } - - /** - * Gets type. - * - * @return the type - */ - @Override - public String getType() { - return NationAccountHolder.ACCOUNT_TYPE; - } - - /** - * Gets account names. - * - * @return the account names - */ - @Override - public @NotNull Set getAccountNames() { - return this.api.getNations().stream().map(MemberHolder::getName).collect(Collectors.toSet()); - } - - /** - * Gets account holder. - * - * @param nation the nation - * @return the account holder - */ - public @Nullable AccountHolder getAccountHolder(@Nullable Nation nation) { - if (nation == null) { - return null; - } - - return new NationAccountHolder(nation); - } - - /** - * Rename nation. - * - * @param event the event - */ - @EventHandler - public void renameNation(NationRenameEvent event) { - Nation nation = event.getNation(); - - AccountHolder holder = this.getAccountHolder(nation); - - if (holder == null) { - return; - } - - GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); - - if (account == null) { - return; - } - - Gringotts.instance.getDao().retrieveChests(account).forEach(AccountChest::updateSign); - } - - /** - * Calculate start balance. - * - * @param event the event - */ - // @EventHandler - // public void calculateStartBalance(CalculateStartBalanceEvent event) { - // if (!event.holder.getType().equals(getType())) { - // return; - // } - - // event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.nationStartBalance); - // } -} diff --git a/target/classes/config.yml b/target/classes/config.yml deleted file mode 100644 index 5c63d8b..0000000 --- a/target/classes/config.yml +++ /dev/null @@ -1,10 +0,0 @@ -# supported languages: "custom" (default, english), "de" (german), "fr" (french), and "pt-BR" (brazilian portuguese). -language: custom - -# changes the required sign name for the creation of town/nation vaults -# Example: [town vault] -land_sign_vault_name: 'land' -nation_sign_vault_name: 'nation' - -# Prevents players from creating a vault outside a town if set to true -vaults_only_in_lands: false diff --git a/target/classes/i18n/messages_de.yml b/target/classes/i18n/messages_de.yml deleted file mode 100644 index 8c762de..0000000 --- a/target/classes/i18n/messages_de.yml +++ /dev/null @@ -1,4 +0,0 @@ -noLandVaultPerm: "Du kannst hier keinen Town-Tresor erstellen." -noLandResident: "Du kannst keine Town-Tresor erstellen, weil du nicht Bürger einer Town bist." -noNationVaultPerm: "Du kannst hier keine Nation-Tresore erstellen." -notInNation: "Du kannst keine Nation-Tresore erstellen, weil du nicht Bürger einer Nation bist" diff --git a/target/classes/i18n/messages_fr.yml b/target/classes/i18n/messages_fr.yml deleted file mode 100644 index 5abfd48..0000000 --- a/target/classes/i18n/messages_fr.yml +++ /dev/null @@ -1,6 +0,0 @@ -noLandVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de ville ici." -noLandResident: "Impossible de créer un coffre-fort de ville : Vous n'êtes pas résident d'une ville." -noNationVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de nation ici." -notInNation: "Impossible de créer un coffre-fort de nation : Vous n'appartenez pas à une nation." -vaultNotInLand: "Vous ne pouvez pas créer de coffre-fort en dehors des villes." -tooManyVaults: "Vous ne pouvez pas créer plus de coffre-fort ! Max : %max" diff --git a/target/classes/i18n/messages_pt-BR.yml b/target/classes/i18n/messages_pt-BR.yml deleted file mode 100644 index d2ac5ef..0000000 --- a/target/classes/i18n/messages_pt-BR.yml +++ /dev/null @@ -1,4 +0,0 @@ -noLandVaultPerm: "Você não tem permissão para criar cofres de cidade aqui." -noLandResident: "Não é possível criar cofre de cidade: Você não pertence a uma cidade." -noNationVaultPerm: "Você não tem permissão para criar cofres de nação aqui." -notInNation: "Não é possível criar cofre de nação: Você não pertence a uma nação." diff --git a/target/classes/messages.yml b/target/classes/messages.yml deleted file mode 100644 index 02024dc..0000000 --- a/target/classes/messages.yml +++ /dev/null @@ -1,5 +0,0 @@ -noLandVaultPerm: "You do not have permission to create town vaults here." -noLandResident: "Cannot create town vault: You are not resident of a town." -noNationVaultPerm: "You do not have permission to create nation vaults here." -notInNation: "Cannot create nation vault: You do not belong to a nation." -vaultNotInLand: "You cannot create vaults outside of towns." diff --git a/target/classes/net/laboulangerie/gringottslands/GringottsLands.class b/target/classes/net/laboulangerie/gringottslands/GringottsLands.class deleted file mode 100644 index 320e0023030e7dd8c80c51758a99439885b8618e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4485 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 diff --git a/target/classes/net/laboulangerie/gringottslands/LandsDependency.class b/target/classes/net/laboulangerie/gringottslands/LandsDependency.class deleted file mode 100644 index e2982a941d8040bd5387397ddfa2a06714c2f195..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5465 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 PDqTj=|IR}L_{V<%t2bMC diff --git a/target/classes/net/laboulangerie/gringottslands/LandsLanguage.class b/target/classes/net/laboulangerie/gringottslands/LandsLanguage.class deleted file mode 100644 index f8e2597824a60a2d6bee5b6932c2b94097342835..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3290 zcmbVOYj@K|5WR~->^K69p@xK)N&}6Z5R>vKkPt#b0x6E6n3$&Y!P;IcB8uedkv4tN z{-YL73#F$VKKJy$^dIzeb|tX#fZ~49YDY7(bLY;^=+A$iJ_B$OKPIt_VZ;`G(c(2H zu()jq*Azv=HEqN3eUBs!uUL{#dKdvWL=s&LJMZ&VPDZv-oUwxyhOW}(@>PbDrOup< zG3>G(>A%VY%fBgH@|7*My;po03aRZ3)ouyTYzW(D*ljyy?wgJsv+T7Uf6flYWU?xK zmZeCZz|cEWUYH-KUM?-nR2W9@b{=eMyl$Dc=}#~u2J=MxldgXRj}c)<(9>A{lY8pT?$ylnc#x??v@BXCuYicQlJ#aVhx$Him$YL+VDsD^hi zz_6XSTGkrFt^eUDL>l;}Rcr=!T@q8AGH0XLu@sIoq(crR%P9;poLzJRz2WG@n!dzW zh2Eksrst8Z?mK#&;Q2zQDr@M9N>5)Bt{CY>0mDfQF&t8b@~T56suK+7;w;>#-4}I# zEXGSD$!``VQDn$$tVPM$sD>m`DfFapn&JF3w>O z@q|amZUL3%MT`4OG_o3kcu!ZHz^w~84CIWF_w&UJ8Ijx&w2Eoatq)vMn2P0B@-^OR zg~-d0nQ|Q8qxf6%!e4S4UK%a9NqoU@v|SFSz3MCr`rDAzK#IJ{>vX}_GX!47vkz~{xLlA^|o4HOjBvFy9QA)ml=jQoO=O7vd#R9kdLiQdni zZ;Qs1=wf!FEt*uKsqA!HG$X@HC|nbi5MU1_GDq0<(JqI6?5Du`aFo^)v^zzbXK0-y znlMR<)Bogyf)1!7 z>w1Ci>~N<6LBstn!BuhXe~daIDy$mF*&sq8a` z>CAtVCm62%!<0?sSJtu&4prNh7=oGe#yOJ-BJ|w^m7k|1Tzz07=S4LK)Y^_?7^t@P7tUYOEQ7MSJ z%wsF*gB^Fc&Jl)CD|vs!+!f$~m&P}DWP`yg8!1K6-bvdG!{LmkSK_7G-kxm6CDoM8 zdVF0G>yn;`Z2A$!xEo^(eOI9bOd!V4u_HDailL{4n#d+?bKl~o?O)xOPzRz?lSt}Z zIMU9i_hANeZp<JjOi3Y%}MwA{s`bg~OUs{G`%x@#VCdUY4HA+$cR4k9UkO zfo9Ih6|!7SCrtVRN3sp!3yGyka;%;HdK^pr-0uM0$;g!H=9U8j1KiFOJ1G{>LHJIJ zN)+?o)HkqVu*)6{93yyykQMehg8f!F==@Hv?S}~EijG4J=8iD@k*aLCN!O6Y;iY~8 zx`;W10B%s1TNZ+&==?VNy(ERPJG7bIa8-KLoey>Bdz@wLx}1Lk9*cM z{E5$FC%*d#H&_=5!%_aR=qHSRLBxjlR&y@TMId0LiOhdS=0_Y4=)D({m}-#C(KvjS zp+gK8U)iIl#U!78)joKF>G2O2c-h&QUUJTp21k_S@UFffi=H6y1MKQL8x}0iMJ!qO F)NjXmh7te( diff --git a/target/classes/net/laboulangerie/gringottslands/land/LandAccountHolder.class b/target/classes/net/laboulangerie/gringottslands/land/LandAccountHolder.class deleted file mode 100644 index 6543cf1bcb1530cd2ec7ef49c6a2d37b6e5f9d28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2181 zcmbVMYjfK~6g_Jvk!#D1>&BrETKY&@+o4rk3ZZpcNZf=3oChQ^lrPNM-q@;Ttw&my z$-jab9+Q6H2Qd65hP#p)E6!swe9&We?>T$!xp(*Pf8YHD;01m(kYJd1g|ZypkOPOi zZQ&zBXjuR$5PmAzPKMueht~+!=@z zG7Mu{9K&p_CoC=BZ+4{b3pWt$TfA=%;oW6ItXL zlEqT}0vM)DWMDE()@)a740;XW?eK;pw0ha(PMv$U9!Ha7s$=^M&uahEaFTDdh1%df z+F`0#I_^*gAL6Eg8w_{PVTXyUxWNU-T7q$4Og+y9W5Zfg7NS$n^(3 z;Z-sy<6{GJly=Y+BiopGfQMwxp7fS^v%_#J+Tj#BT~wp@K4b0a&VHYAAE&>ymd^DP z6HoDJ==W}I?G?iUrFgohyx({1Cf7Odc~qaDrPsBB-8H(Rn`hp{=i2U+l3_oG?D|+S z+&`0Dw|H>=r~^_C?=@O{<`IK+f{!(Q@*0C~*H)Hrm96%zuu2tO#FzNez!y}n)1pj# zgj-aqeo$G4Yp3%uq_^e3Yl;w+e}kSZF4D>*{jJbig1+hUpU9Qxe#hlsX_P>L-WQ1r$YBhZh$W9{8cm1M_yAXE zM7V&J5gXlG5$99-GQC#*4VMpao#7W6g`5+?%JqQD45K10rrVrmw5oNA)~X62!)=DS zcbEkZP)cAZFdYQVVhZd$um5UQnMnGaZNG`UW$RoLvSvw`z!)KiF`@Tl@IVDZbj(pYz&{m jB9;i3L^W{#6_)9%J+IN+2EN5Mc4$U7^De%}Yh3*g#(Wn* diff --git a/target/classes/net/laboulangerie/gringottslands/land/LandHolderProvider.class b/target/classes/net/laboulangerie/gringottslands/land/LandHolderProvider.class deleted file mode 100644 index 87d03495673f68295dc6e8f9144be884ecc28baa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6176 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 Date: Thu, 21 Nov 2024 19:57:12 +0100 Subject: [PATCH 04/14] Update Gringotts again --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c1f29a8..b5b31c5 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ com.github.LaBoulangerie Gringotts - dev-2b46a143f4-1 + dev-SNAPSHOT provided From a17ec0c9a35083aab8685b5e44901dd92ca58fd0 Mon Sep 17 00:00:00 2001 From: Clem <20025949+Clem-Fern@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:03:28 +0100 Subject: [PATCH 05/14] Update .gitignore --- .gitignore | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9f97022..2f43530 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,17 @@ -target/ \ No newline at end of file +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Eclipse m2e generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath From 15fb47918db8c77dd36cce828d1d4a31fdfcc319 Mon Sep 17 00:00:00 2001 From: Clem Fern Date: Fri, 29 Nov 2024 18:46:36 +0100 Subject: [PATCH 06/14] wip: Update Land Balance on AccountBalanceChange event --- pom.xml | 6 +++--- .../land/LandHolderProvider.java | 21 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index b5b31c5..836362d 100644 --- a/pom.xml +++ b/pom.xml @@ -46,9 +46,9 @@ provided - com.github.LaBoulangerie - Gringotts - dev-SNAPSHOT + minecraftwars + gringotts + 3.0.1-SNAPSHOT provided diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index e2ae3bb..cbc91b2 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -17,6 +17,7 @@ import org.gestern.gringotts.GringottsAccount; import org.gestern.gringotts.accountholder.AccountHolder; import org.gestern.gringotts.accountholder.AccountHolderProvider; +import org.gestern.gringotts.event.AccountBalanceChangeEvent; import org.gestern.gringotts.event.CalculateStartBalanceEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -89,12 +90,6 @@ public LandHolderProvider(LandsIntegration api) { @Override public @Nullable AccountHolder getAccountHolder(@NotNull OfflinePlayer player) { System.out.println("LandHolderProvider.getAccountHolder OfflinePlayer " + player); - LandPlayer resident = this.api.getLandPlayer(player.getUniqueId()); - if (resident == null) return null; - - - // resident.getLands().stream().f - return null; } @@ -169,4 +164,18 @@ public void calculateStartBalance(CalculateStartBalanceEvent event) { event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.landStartBalance); } + + /** + * Calculate start balance. + * + * @param event the event + */ + @EventHandler + public void onBalanceChange(AccountBalanceChangeEvent event) { + if (!event.holder.getType().equals(this.getType())) return; + LandAccountHolder lHolder = (LandAccountHolder) this.getAccountHolder(event.holder.getId()); + double update = event.balance - lHolder.getLand().getBalance(); + System.out.println("Balance change detected for " + lHolder.getId() + " " + update); + lHolder.getLand().modifyBalance(update); + } } From 92c541df25d739c2ffc04344c7b76cf34b73accf Mon Sep 17 00:00:00 2001 From: Clem Fern Date: Fri, 29 Nov 2024 22:20:48 +0100 Subject: [PATCH 07/14] wip: handle land bank event --- .../gringottslands/LandsDependency.java | 2 +- .../land/LandHolderProvider.java | 148 ++++++++++++++---- 2 files changed, 119 insertions(+), 31 deletions(-) diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java index c343e31..7fe77de 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java @@ -38,7 +38,7 @@ public LandsDependency(Gringotts gringotts, Plugin plugin) { this.id = "lands"; this.api = LandsIntegration.of(plugin); - this.landHolderProvider = new LandHolderProvider(this.api); + this.landHolderProvider = new LandHolderProvider(this.api, this.gringotts); } diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index cbc91b2..adf2c39 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -2,21 +2,27 @@ import me.angeschossen.lands.api.LandsIntegration; import me.angeschossen.lands.api.applicationframework.util.ULID; +import me.angeschossen.lands.api.events.LandCreateEvent; import me.angeschossen.lands.api.events.LandRenameEvent; +import me.angeschossen.lands.api.events.land.bank.LandBankBalanceChangedEvent; +import me.angeschossen.lands.api.events.land.bank.LandBankDepositEvent; +import me.angeschossen.lands.api.events.land.bank.LandBankWithdrawEvent; import me.angeschossen.lands.api.land.Land; import me.angeschossen.lands.api.memberholder.MemberHolder; -import me.angeschossen.lands.api.player.LandPlayer; import net.laboulangerie.gringottslands.LandsConfiguration; import org.bukkit.OfflinePlayer; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.scheduler.BukkitRunnable; import org.gestern.gringotts.AccountChest; import org.gestern.gringotts.Configuration; import org.gestern.gringotts.Gringotts; import org.gestern.gringotts.GringottsAccount; import org.gestern.gringotts.accountholder.AccountHolder; import org.gestern.gringotts.accountholder.AccountHolderProvider; +import org.gestern.gringotts.api.Account; +import org.gestern.gringotts.api.TransactionResult; import org.gestern.gringotts.event.AccountBalanceChangeEvent; import org.gestern.gringotts.event.CalculateStartBalanceEvent; import org.jetbrains.annotations.NotNull; @@ -29,9 +35,11 @@ public class LandHolderProvider implements AccountHolderProvider, Listener { private LandsIntegration api; + private Gringotts gringotts; - public LandHolderProvider(LandsIntegration api) { + public LandHolderProvider(LandsIntegration api, Gringotts gringotts) { this.api = api; + this.gringotts = gringotts; } /** @@ -41,9 +49,7 @@ public LandHolderProvider(LandsIntegration api) { * @return account holder for id */ public @Nullable AccountHolder getAccountHolder(@NotNull ULID ulid) { - System.out.println("LandHolderProvider.getAccountHolder ULID " + ulid); Land land = this.api.getLandByULID(ulid); - return getAccountHolder(land); } @@ -55,17 +61,11 @@ public LandHolderProvider(LandsIntegration api) { */ @Override public @Nullable AccountHolder getAccountHolder(@NotNull String id) { - System.out.println("LandHolderProvider.getAccountHolder String " + id); try { - ULID targetUlid = ULID.fromString(id); - - return getAccountHolder(targetUlid); - } catch (IllegalArgumentException ignored) {} - - String vaultPrefix = LandAccountHolder.ACCOUNT_TYPE + "-"; - String validId = id.startsWith(vaultPrefix) ? id.substring(vaultPrefix.length()) : id; - - return getAccountHolder(ULID.fromString(validId)); + return getAccountHolder(ULID.fromString(id)); + } catch(IllegalArgumentException e) { + return null; + } } /** @@ -76,8 +76,7 @@ public LandHolderProvider(LandsIntegration api) { */ @Override public @Nullable AccountHolder getAccountHolder(@NotNull UUID uuid) { - System.out.println("LandHolderProvider.getAccountHolder UUID " + uuid); - return null; + throw new UnsupportedOperationException("Unimplemented method 'getAccountHolder'"); } /** @@ -89,8 +88,7 @@ public LandHolderProvider(LandsIntegration api) { */ @Override public @Nullable AccountHolder getAccountHolder(@NotNull OfflinePlayer player) { - System.out.println("LandHolderProvider.getAccountHolder OfflinePlayer " + player); - return null; + throw new UnsupportedOperationException("Unimplemented method 'getAccountHolder'"); } /** @@ -128,7 +126,30 @@ public String getType() { } /** - * Rename town. + * Create land. + * + * @param event the event + */ + @EventHandler + public void createLand(LandCreateEvent event) { + Land land = event.getLand(); + AccountHolder holder = getAccountHolder(land); + + if (holder == null) { + return; + } + + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + + if (account == null) { + return; + } + + Gringotts.instance.getDao().retrieveChests(account).forEach(AccountChest::updateSign); + } + + /** + * Rename land. * * @param event the event */ @@ -165,17 +186,84 @@ public void calculateStartBalance(CalculateStartBalanceEvent event) { event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.landStartBalance); } - /** - * Calculate start balance. - * - * @param event the event - */ + // @EventHandler + // public void onBalanceChange(AccountBalanceChangeEvent event) { + // if (!event.holder.getType().equals(this.getType())) return; + // double balance = Configuration.CONF.getCurrency().getDisplayValue(event.balance); + // LandAccountHolder lHolder = (LandAccountHolder) this.getAccountHolder(event.holder.getId()); + // Account acc = Gringotts.instance.getEco().account(event.holder.getId()); + // if (lHolder.getLand().getBalance() == acc.balance()) return; + // System.out.println("Land Balance before change " + lHolder.getId() + " " + lHolder.getLand().getBalance()); + // System.out.println("Balance change detected for " + lHolder.getId() + " " + balance); + // lHolder.getLand().setBalance(balance); + // } + + @EventHandler + public void onLandBankBalanceChanged(LandBankBalanceChangedEvent event) { + if (event.getEventName().equals(LandBankDepositEvent.class.getSimpleName())) return; + if (event.getEventName().equals(LandBankWithdrawEvent.class.getSimpleName())) return; + + Land land = event.getLand(); + + AccountHolder holder = getAccountHolder(land); + + if (holder == null) { + return; + } + + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + if (account.getBalance() != event.getNow()) { + System.out.println("Land Balance change detected for " + land.getULID() + " from " + event.getPrevious() + " to " + event.getNow()); + long update = Configuration.CONF.getCurrency().getCentValue(event.getNow() - event.getPrevious()); + TransactionResult result; + if (update > 0) { + result = account.add(update); + } else { + result = account.remove(Math.abs(update)); + } + + if (result != TransactionResult.SUCCESS) { + throw new IllegalStateException(account.owner.getId() + " account transaction error for " + (event.getNow() - event.getPrevious()) + " " + result); + } + } + } + + @EventHandler + public void onLandBankDeposit(LandBankDepositEvent event) { + Land land = event.getLand(); + + AccountHolder holder = getAccountHolder(land); + + if (holder == null) { + event.setCancelled(true); + return; + } + + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + System.out.println("Land deposit on " + land.getULID() + " of " + event.getValue()); + long value = Configuration.CONF.getCurrency().getCentValue(event.getValue()); + if (account.add(value) != TransactionResult.SUCCESS) { + event.setCancelled(true); + } + } + @EventHandler - public void onBalanceChange(AccountBalanceChangeEvent event) { - if (!event.holder.getType().equals(this.getType())) return; - LandAccountHolder lHolder = (LandAccountHolder) this.getAccountHolder(event.holder.getId()); - double update = event.balance - lHolder.getLand().getBalance(); - System.out.println("Balance change detected for " + lHolder.getId() + " " + update); - lHolder.getLand().modifyBalance(update); + public void onLandBankWithdraw(LandBankWithdrawEvent event) { + Land land = event.getLand(); + + AccountHolder holder = getAccountHolder(land); + + if (holder == null) { + event.setCancelled(true); + return; + } + + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + System.out.println("Land withdraw on " + land.getULID() + " of " + event.getValue()); + long value = Configuration.CONF.getCurrency().getCentValue(event.getValue()); + if (account.remove(value) != TransactionResult.SUCCESS) { + event.setCancelled(true); + } } + } From d30f8e2ad1ad7a98f506e30ace6f0eedcfe45d87 Mon Sep 17 00:00:00 2001 From: Clem Date: Tue, 3 Dec 2024 21:33:57 +0100 Subject: [PATCH 08/14] clean up --- .../gringottslands/LandsConfiguration.java | 1 - .../laboulangerie/gringottslands/LandsDependency.java | 2 +- .../laboulangerie/gringottslands/LandsLanguage.java | 6 ------ .../gringottslands/LandsPermissions.java | 6 +----- .../gringottslands/land/LandAccountHolder.java | 4 ++-- .../gringottslands/land/LandHolderProvider.java | 11 +++-------- src/main/resources/config.yml | 10 ++++++---- src/main/resources/i18n/messages_de.yml | 2 -- src/main/resources/i18n/messages_fr.yml | 2 -- src/main/resources/i18n/messages_pt-BR.yml | 2 -- src/main/resources/messages.yml | 2 -- 11 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java index 7033ffb..727ee76 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java @@ -14,7 +14,6 @@ public enum LandsConfiguration { public boolean vaultsOnlyInLands = false; public long landStartBalance = 0; - public long nationStartBalance = 0; public void readConfig(FileConfiguration savedConfig) { CONF.language = savedConfig.getString("language", "custom"); diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java index 7fe77de..c343e31 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java @@ -38,7 +38,7 @@ public LandsDependency(Gringotts gringotts, Plugin plugin) { this.id = "lands"; this.api = LandsIntegration.of(plugin); - this.landHolderProvider = new LandHolderProvider(this.api, this.gringotts); + this.landHolderProvider = new LandHolderProvider(this.api); } diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java b/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java index a51a722..0c47977 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java @@ -11,8 +11,6 @@ public enum LandsLanguage { public String noLandVaultPerm; public String noLandResident; - public String noNationVaultPerm; - public String notInNation; public String vaultNotInLand; public void readLanguage(FileConfiguration savedLanguage) { @@ -23,10 +21,6 @@ public void readLanguage(FileConfiguration savedLanguage) { "You do not have permission to create land vaults here."); LANG.noLandResident = translator.apply("noLandResident", "Cannot create land vault: You are not resident of a land."); - LANG.noNationVaultPerm = translator.apply("NoNationVaultPerm", - "You do not have permission to create nation vaults here."); - LANG.notInNation = translator.apply("notInNation", - "Cannot create nation vault: You do not belong to a nation."); LANG.vaultNotInLand = translator.apply("vaultNotInLand", "You cannot create vaults outside of lands."); } diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsPermissions.java b/src/main/java/net/laboulangerie/gringottslands/LandsPermissions.java index e1441f4..30fbe9d 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsPermissions.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsPermissions.java @@ -9,11 +9,7 @@ public enum LandsPermissions { /** * Create vault land permissions. */ - CREATE_VAULT_LAND("gringotts.createvault.land"), - /** - * Create vault nation permissions. - */ - CREATE_VAULT_NATION("gringotts.createvault.nation"); + CREATE_VAULT_LAND("gringotts.createvault.land"); /** * The Node. diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java b/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java index 8c42e3a..0cb8e78 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandAccountHolder.java @@ -59,8 +59,8 @@ public String getId() { } /** - * The town onwing this account - * @return town object + * The land onwing this account + * @return land object */ public Land getLand() { return this.land; diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index adf2c39..414bba2 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -14,16 +14,13 @@ import org.bukkit.OfflinePlayer; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.scheduler.BukkitRunnable; import org.gestern.gringotts.AccountChest; import org.gestern.gringotts.Configuration; import org.gestern.gringotts.Gringotts; import org.gestern.gringotts.GringottsAccount; import org.gestern.gringotts.accountholder.AccountHolder; import org.gestern.gringotts.accountholder.AccountHolderProvider; -import org.gestern.gringotts.api.Account; import org.gestern.gringotts.api.TransactionResult; -import org.gestern.gringotts.event.AccountBalanceChangeEvent; import org.gestern.gringotts.event.CalculateStartBalanceEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,11 +32,9 @@ public class LandHolderProvider implements AccountHolderProvider, Listener { private LandsIntegration api; - private Gringotts gringotts; - public LandHolderProvider(LandsIntegration api, Gringotts gringotts) { + public LandHolderProvider(LandsIntegration api) { this.api = api; - this.gringotts = gringotts; } /** @@ -82,7 +77,7 @@ public LandHolderProvider(LandsIntegration api, Gringotts gringotts) { /** * Get a AccountHolder for the land of which player is a resident, if any. * - * @param player player to get town for + * @param player player to get land for * @return AccountHolder for the land of which player is a resident, if * any. null otherwise. */ @@ -114,7 +109,7 @@ public String getType() { /** * Gets account holder. * - * @param town the town + * @param Land the land * @return the account holder */ public @Nullable AccountHolder getAccountHolder(@Nullable Land land) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5c63d8b..2c3c88c 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,10 +1,12 @@ # supported languages: "custom" (default, english), "de" (german), "fr" (french), and "pt-BR" (brazilian portuguese). language: custom -# changes the required sign name for the creation of town/nation vaults -# Example: [town vault] +# changes the required sign name for the creation of land vaults +# Example: [land vault] land_sign_vault_name: 'land' -nation_sign_vault_name: 'nation' -# Prevents players from creating a vault outside a town if set to true +# Prevents players from creating a vault outside a land if set to true vaults_only_in_lands: false + +# balance to start an account with (purely virtual) +land_start_balance: 0 \ No newline at end of file diff --git a/src/main/resources/i18n/messages_de.yml b/src/main/resources/i18n/messages_de.yml index 8c762de..2731035 100644 --- a/src/main/resources/i18n/messages_de.yml +++ b/src/main/resources/i18n/messages_de.yml @@ -1,4 +1,2 @@ noLandVaultPerm: "Du kannst hier keinen Town-Tresor erstellen." noLandResident: "Du kannst keine Town-Tresor erstellen, weil du nicht Bürger einer Town bist." -noNationVaultPerm: "Du kannst hier keine Nation-Tresore erstellen." -notInNation: "Du kannst keine Nation-Tresore erstellen, weil du nicht Bürger einer Nation bist" diff --git a/src/main/resources/i18n/messages_fr.yml b/src/main/resources/i18n/messages_fr.yml index 5abfd48..97e41b9 100644 --- a/src/main/resources/i18n/messages_fr.yml +++ b/src/main/resources/i18n/messages_fr.yml @@ -1,6 +1,4 @@ noLandVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de ville ici." noLandResident: "Impossible de créer un coffre-fort de ville : Vous n'êtes pas résident d'une ville." -noNationVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de nation ici." -notInNation: "Impossible de créer un coffre-fort de nation : Vous n'appartenez pas à une nation." vaultNotInLand: "Vous ne pouvez pas créer de coffre-fort en dehors des villes." tooManyVaults: "Vous ne pouvez pas créer plus de coffre-fort ! Max : %max" diff --git a/src/main/resources/i18n/messages_pt-BR.yml b/src/main/resources/i18n/messages_pt-BR.yml index d2ac5ef..0e2bebf 100644 --- a/src/main/resources/i18n/messages_pt-BR.yml +++ b/src/main/resources/i18n/messages_pt-BR.yml @@ -1,4 +1,2 @@ noLandVaultPerm: "Você não tem permissão para criar cofres de cidade aqui." noLandResident: "Não é possível criar cofre de cidade: Você não pertence a uma cidade." -noNationVaultPerm: "Você não tem permissão para criar cofres de nação aqui." -notInNation: "Não é possível criar cofre de nação: Você não pertence a uma nação." diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 02024dc..01779bd 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -1,5 +1,3 @@ noLandVaultPerm: "You do not have permission to create town vaults here." noLandResident: "Cannot create town vault: You are not resident of a town." -noNationVaultPerm: "You do not have permission to create nation vaults here." -notInNation: "Cannot create nation vault: You do not belong to a nation." vaultNotInLand: "You cannot create vaults outside of towns." From fe2c5723fcd088cca7c616a69637e57cd902755a Mon Sep 17 00:00:00 2001 From: Clem Date: Tue, 3 Dec 2024 23:10:23 +0100 Subject: [PATCH 09/14] fix events & messages Ok: - vault content update - land deposit - land withdraw - rename land To test: - vault outside land - delete land (entry in Gringotts bdd ?) - land taxes --- pom.xml | 2 +- .../gringottslands/LandsDependency.java | 5 +- .../gringottslands/LandsLanguage.java | 6 +- .../land/LandHolderProvider.java | 145 ++++++++---------- src/main/resources/i18n/messages_de.yml | 2 - src/main/resources/i18n/messages_fr.yml | 3 +- src/main/resources/i18n/messages_pt-BR.yml | 2 - src/main/resources/messages.yml | 6 +- 8 files changed, 74 insertions(+), 97 deletions(-) delete mode 100644 src/main/resources/i18n/messages_de.yml delete mode 100644 src/main/resources/i18n/messages_pt-BR.yml diff --git a/pom.xml b/pom.xml index 836362d..3faffd5 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ io.papermc.paper paper-api - 1.20.2-R0.1-SNAPSHOT + 1.21.1-R0.1-SNAPSHOT provided diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java index c343e31..006d893 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java @@ -38,7 +38,7 @@ public LandsDependency(Gringotts gringotts, Plugin plugin) { this.id = "lands"; this.api = LandsIntegration.of(plugin); - this.landHolderProvider = new LandHolderProvider(this.api); + this.landHolderProvider = new LandHolderProvider(this.gringotts, this.api); } @@ -104,8 +104,7 @@ public void vaultCreated(PlayerVaultCreationEvent event) { Land land = this.api.getLandByName(line2String); if (land == null) { - // TODO: no land found - // player.sendMessage(LandsLanguage.LANG.noLandResident); + player.sendMessage(LandsLanguage.LANG.noLandFound); return; } diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java b/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java index 0c47977..3e78e19 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java @@ -10,7 +10,7 @@ public enum LandsLanguage { LANG; public String noLandVaultPerm; - public String noLandResident; + public String noLandFound; public String vaultNotInLand; public void readLanguage(FileConfiguration savedLanguage) { @@ -19,8 +19,8 @@ public void readLanguage(FileConfiguration savedLanguage) { LANG.noLandVaultPerm = translator.apply("noLandPerm", "You do not have permission to create land vaults here."); - LANG.noLandResident = translator.apply("noLandResident", - "Cannot create land vault: You are not resident of a land."); + LANG.noLandFound = translator.apply("noLandFound", + "Cannot create land vault: Land not found."); LANG.vaultNotInLand = translator.apply("vaultNotInLand", "You cannot create vaults outside of lands."); } diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index 414bba2..76db653 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -2,7 +2,7 @@ import me.angeschossen.lands.api.LandsIntegration; import me.angeschossen.lands.api.applicationframework.util.ULID; -import me.angeschossen.lands.api.events.LandCreateEvent; +import me.angeschossen.lands.api.events.LandDeleteEvent; import me.angeschossen.lands.api.events.LandRenameEvent; import me.angeschossen.lands.api.events.land.bank.LandBankBalanceChangedEvent; import me.angeschossen.lands.api.events.land.bank.LandBankDepositEvent; @@ -14,6 +14,7 @@ import org.bukkit.OfflinePlayer; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.scheduler.BukkitRunnable; import org.gestern.gringotts.AccountChest; import org.gestern.gringotts.Configuration; import org.gestern.gringotts.Gringotts; @@ -21,6 +22,7 @@ import org.gestern.gringotts.accountholder.AccountHolder; import org.gestern.gringotts.accountholder.AccountHolderProvider; import org.gestern.gringotts.api.TransactionResult; +import org.gestern.gringotts.event.AccountBalanceChangeEvent; import org.gestern.gringotts.event.CalculateStartBalanceEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,9 +33,11 @@ public class LandHolderProvider implements AccountHolderProvider, Listener { + private Gringotts gringotts; private LandsIntegration api; - - public LandHolderProvider(LandsIntegration api) { + + public LandHolderProvider(Gringotts gringotts, LandsIntegration api) { + this.gringotts = gringotts; this.api = api; } @@ -58,7 +62,7 @@ public LandHolderProvider(LandsIntegration api) { public @Nullable AccountHolder getAccountHolder(@NotNull String id) { try { return getAccountHolder(ULID.fromString(id)); - } catch(IllegalArgumentException e) { + } catch (IllegalArgumentException e) { return null; } } @@ -79,7 +83,7 @@ public LandHolderProvider(LandsIntegration api) { * * @param player player to get land for * @return AccountHolder for the land of which player is a resident, if - * any. null otherwise. + * any. null otherwise. */ @Override public @Nullable AccountHolder getAccountHolder(@NotNull OfflinePlayer player) { @@ -121,37 +125,52 @@ public String getType() { } /** - * Create land. + * Rename land. * * @param event the event */ @EventHandler - public void createLand(LandCreateEvent event) { - Land land = event.getLand(); - AccountHolder holder = getAccountHolder(land); + public void renameLand(LandRenameEvent event) { + ULID id = event.getLand().getULID(); - if (holder == null) { - return; - } + new BukkitRunnable() { + @Override + public void run() { + LandAccountHolder holder = (LandAccountHolder) getAccountHolder(id); + if (holder == null) + return; - GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + if (account == null) + return; - if (account == null) { + Gringotts.instance.getDao().retrieveChests(account).forEach(AccountChest::updateSign); + } + }.runTask(this.gringotts); + } + + /** + * Calculate start balance. + * + * @param event the event + */ + @EventHandler + public void calculateStartBalance(CalculateStartBalanceEvent event) { + if (!event.holder.getType().equals(getType())) { return; } - Gringotts.instance.getDao().retrieveChests(account).forEach(AccountChest::updateSign); + event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.landStartBalance); } /** - * Rename land. + * Delete land. * * @param event the event */ @EventHandler - public void renameLand(LandRenameEvent event) { + public void deleteLand(LandDeleteEvent event) { Land land = event.getLand(); - AccountHolder holder = getAccountHolder(land); if (holder == null) { @@ -164,39 +183,39 @@ public void renameLand(LandRenameEvent event) { return; } - Gringotts.instance.getDao().retrieveChests(account).forEach(AccountChest::updateSign); + Gringotts.instance.getDao().deleteAccount(account); } - /** - * Calculate start balance. - * - * @param event the event - */ @EventHandler - public void calculateStartBalance(CalculateStartBalanceEvent event) { - if (!event.holder.getType().equals(getType())) { + public void onBalanceChange(AccountBalanceChangeEvent event) { + if (!event.holder.getType().equals(this.getType())) + return; + + double balance = Configuration.CONF.getCurrency().getDisplayValue(event.balance); + LandAccountHolder holder = (LandAccountHolder) this.getAccountHolder(event.holder.getId()); + + if (holder == null) { return; } - event.startValue = Configuration.CONF.getCurrency().getCentValue(LandsConfiguration.CONF.landStartBalance); - } + System.out.println("Balance change detected for " + holder.getId() + " " + balance); - // @EventHandler - // public void onBalanceChange(AccountBalanceChangeEvent event) { - // if (!event.holder.getType().equals(this.getType())) return; - // double balance = Configuration.CONF.getCurrency().getDisplayValue(event.balance); - // LandAccountHolder lHolder = (LandAccountHolder) this.getAccountHolder(event.holder.getId()); - // Account acc = Gringotts.instance.getEco().account(event.holder.getId()); - // if (lHolder.getLand().getBalance() == acc.balance()) return; - // System.out.println("Land Balance before change " + lHolder.getId() + " " + lHolder.getLand().getBalance()); - // System.out.println("Balance change detected for " + lHolder.getId() + " " + balance); - // lHolder.getLand().setBalance(balance); - // } + if (holder.getLand().getBalance() == balance) + return; + System.out.println("Land Balance before change " + holder.getId() + " " + holder.getLand().getBalance()); + + holder.getLand().setBalance(balance); + } @EventHandler public void onLandBankBalanceChanged(LandBankBalanceChangedEvent event) { - if (event.getEventName().equals(LandBankDepositEvent.class.getSimpleName())) return; - if (event.getEventName().equals(LandBankWithdrawEvent.class.getSimpleName())) return; + System.out.println("onLandBankBalanceChanged " + event.getEventName()); + System.out.println("onLandBankBalanceChanged " + event.getClass()); + if (event.getEventName().equals(LandBankDepositEvent.class.getSimpleName())) + return; // TODO: to fix + if (event.getEventName().equals(LandBankWithdrawEvent.class.getSimpleName())) + return; // TODO: to fix + // land event duplication Land land = event.getLand(); @@ -208,7 +227,8 @@ public void onLandBankBalanceChanged(LandBankBalanceChangedEvent event) { GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); if (account.getBalance() != event.getNow()) { - System.out.println("Land Balance change detected for " + land.getULID() + " from " + event.getPrevious() + " to " + event.getNow()); + System.out.println("Land Balance change detected for " + land.getULID() + " from " + event.getPrevious() + + " to " + event.getNow()); long update = Configuration.CONF.getCurrency().getCentValue(event.getNow() - event.getPrevious()); TransactionResult result; if (update > 0) { @@ -218,47 +238,10 @@ public void onLandBankBalanceChanged(LandBankBalanceChangedEvent event) { } if (result != TransactionResult.SUCCESS) { - throw new IllegalStateException(account.owner.getId() + " account transaction error for " + (event.getNow() - event.getPrevious()) + " " + result); + throw new IllegalStateException(account.owner.getId() + " account transaction error for " + + (event.getNow() - event.getPrevious()) + " " + result); } } } - @EventHandler - public void onLandBankDeposit(LandBankDepositEvent event) { - Land land = event.getLand(); - - AccountHolder holder = getAccountHolder(land); - - if (holder == null) { - event.setCancelled(true); - return; - } - - GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); - System.out.println("Land deposit on " + land.getULID() + " of " + event.getValue()); - long value = Configuration.CONF.getCurrency().getCentValue(event.getValue()); - if (account.add(value) != TransactionResult.SUCCESS) { - event.setCancelled(true); - } - } - - @EventHandler - public void onLandBankWithdraw(LandBankWithdrawEvent event) { - Land land = event.getLand(); - - AccountHolder holder = getAccountHolder(land); - - if (holder == null) { - event.setCancelled(true); - return; - } - - GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); - System.out.println("Land withdraw on " + land.getULID() + " of " + event.getValue()); - long value = Configuration.CONF.getCurrency().getCentValue(event.getValue()); - if (account.remove(value) != TransactionResult.SUCCESS) { - event.setCancelled(true); - } - } - } diff --git a/src/main/resources/i18n/messages_de.yml b/src/main/resources/i18n/messages_de.yml deleted file mode 100644 index 2731035..0000000 --- a/src/main/resources/i18n/messages_de.yml +++ /dev/null @@ -1,2 +0,0 @@ -noLandVaultPerm: "Du kannst hier keinen Town-Tresor erstellen." -noLandResident: "Du kannst keine Town-Tresor erstellen, weil du nicht Bürger einer Town bist." diff --git a/src/main/resources/i18n/messages_fr.yml b/src/main/resources/i18n/messages_fr.yml index 97e41b9..ce59c04 100644 --- a/src/main/resources/i18n/messages_fr.yml +++ b/src/main/resources/i18n/messages_fr.yml @@ -1,4 +1,3 @@ noLandVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de ville ici." -noLandResident: "Impossible de créer un coffre-fort de ville : Vous n'êtes pas résident d'une ville." +noLandFound: "Impossible de créer un coffre-fort de ville : La ville spécifiée n'existe pas." vaultNotInLand: "Vous ne pouvez pas créer de coffre-fort en dehors des villes." -tooManyVaults: "Vous ne pouvez pas créer plus de coffre-fort ! Max : %max" diff --git a/src/main/resources/i18n/messages_pt-BR.yml b/src/main/resources/i18n/messages_pt-BR.yml deleted file mode 100644 index 0e2bebf..0000000 --- a/src/main/resources/i18n/messages_pt-BR.yml +++ /dev/null @@ -1,2 +0,0 @@ -noLandVaultPerm: "Você não tem permissão para criar cofres de cidade aqui." -noLandResident: "Não é possível criar cofre de cidade: Você não pertence a uma cidade." diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 01779bd..04f707c 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -1,3 +1,3 @@ -noLandVaultPerm: "You do not have permission to create town vaults here." -noLandResident: "Cannot create town vault: You are not resident of a town." -vaultNotInLand: "You cannot create vaults outside of towns." +noLandVaultPerm: "You do not have permission to create land vaults here." +noLandFound: "Cannot create land vault: Land not found." +vaultNotInLand: "You cannot create vaults outside of lands." From ea569c447bf628f93a280a8f1874ab1841dcaacb Mon Sep 17 00:00:00 2001 From: Clem Date: Fri, 6 Dec 2024 13:55:10 +0100 Subject: [PATCH 10/14] code cleanup --- .../gringottslands/GringottsLands.java | 4 ++++ .../land/LandHolderProvider.java | 19 ++++--------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java b/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java index 5d106e3..9041054 100644 --- a/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java +++ b/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java @@ -12,9 +12,11 @@ import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; +import java.util.logging.Logger; public class GringottsLands extends JavaPlugin { private static final String MESSAGES_YML = "messages.yml"; + public static Logger LOGGER; @Override public void onLoad() { @@ -34,6 +36,8 @@ public void onLoad() { saveDefaultConfig(); // saves default configuration if no config.yml exists yet reloadConfig(); + LOGGER = this.getLogger(); + Gringotts.instance.getDependencies().getDependency("lands").ifPresent(Dependency::onLoad); } diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index 76db653..4e2089c 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -5,10 +5,9 @@ import me.angeschossen.lands.api.events.LandDeleteEvent; import me.angeschossen.lands.api.events.LandRenameEvent; import me.angeschossen.lands.api.events.land.bank.LandBankBalanceChangedEvent; -import me.angeschossen.lands.api.events.land.bank.LandBankDepositEvent; -import me.angeschossen.lands.api.events.land.bank.LandBankWithdrawEvent; import me.angeschossen.lands.api.land.Land; import me.angeschossen.lands.api.memberholder.MemberHolder; +import net.laboulangerie.gringottslands.GringottsLands; import net.laboulangerie.gringottslands.LandsConfiguration; import org.bukkit.OfflinePlayer; @@ -198,25 +197,16 @@ public void onBalanceChange(AccountBalanceChangeEvent event) { return; } - System.out.println("Balance change detected for " + holder.getId() + " " + balance); - if (holder.getLand().getBalance() == balance) return; - System.out.println("Land Balance before change " + holder.getId() + " " + holder.getLand().getBalance()); + + GringottsLands.LOGGER.fine("Replicate Gringotts account balance change detected on Land " + holder.getId() + " - " + balance); holder.getLand().setBalance(balance); } @EventHandler public void onLandBankBalanceChanged(LandBankBalanceChangedEvent event) { - System.out.println("onLandBankBalanceChanged " + event.getEventName()); - System.out.println("onLandBankBalanceChanged " + event.getClass()); - if (event.getEventName().equals(LandBankDepositEvent.class.getSimpleName())) - return; // TODO: to fix - if (event.getEventName().equals(LandBankWithdrawEvent.class.getSimpleName())) - return; // TODO: to fix - // land event duplication - Land land = event.getLand(); AccountHolder holder = getAccountHolder(land); @@ -227,8 +217,7 @@ public void onLandBankBalanceChanged(LandBankBalanceChangedEvent event) { GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); if (account.getBalance() != event.getNow()) { - System.out.println("Land Balance change detected for " + land.getULID() + " from " + event.getPrevious() - + " to " + event.getNow()); + GringottsLands.LOGGER.fine("Replicate Land Balance change (from " + event.getPrevious() + " to " + event.getNow() + ") on account " + land.getULID()); long update = Configuration.CONF.getCurrency().getCentValue(event.getNow() - event.getPrevious()); TransactionResult result; if (update > 0) { From 5de8518018d1d3dd762b8830f0f032340ea9d163 Mon Sep 17 00:00:00 2001 From: Clem Date: Fri, 6 Dec 2024 13:55:28 +0100 Subject: [PATCH 11/14] fix land withdraw --- .../land/LandHolderProvider.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index 4e2089c..5c2d26f 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -5,6 +5,7 @@ import me.angeschossen.lands.api.events.LandDeleteEvent; import me.angeschossen.lands.api.events.LandRenameEvent; import me.angeschossen.lands.api.events.land.bank.LandBankBalanceChangedEvent; +import me.angeschossen.lands.api.events.land.bank.LandBankWithdrawEvent; import me.angeschossen.lands.api.land.Land; import me.angeschossen.lands.api.memberholder.MemberHolder; import net.laboulangerie.gringottslands.GringottsLands; @@ -20,6 +21,7 @@ import org.gestern.gringotts.GringottsAccount; import org.gestern.gringotts.accountholder.AccountHolder; import org.gestern.gringotts.accountholder.AccountHolderProvider; +import org.gestern.gringotts.api.Account; import org.gestern.gringotts.api.TransactionResult; import org.gestern.gringotts.event.AccountBalanceChangeEvent; import org.gestern.gringotts.event.CalculateStartBalanceEvent; @@ -233,4 +235,21 @@ public void onLandBankBalanceChanged(LandBankBalanceChangedEvent event) { } } + @EventHandler + public void onLandBankWithdraw(LandBankWithdrawEvent event) { + Land land = event.getLand(); + + AccountHolder holder = getAccountHolder(land); + + if (holder == null) { + return; + } + + Account account = Gringotts.instance.getEco().getAccount(holder.getId()); + long value = Configuration.CONF.getCurrency().getCentValue(event.getValue()); + if (!account.has(value)) { + event.setCancelled(true); + } + } + } From 1eccea3d0eee887f22dc51c28152a669a73dd776 Mon Sep 17 00:00:00 2001 From: Clem Fern Date: Sun, 8 Dec 2024 20:40:12 +0100 Subject: [PATCH 12/14] wip --- .../gringottslands/GringottsLands.java | 19 ++-- .../gringottslands/LandsConfiguration.java | 3 + .../gringottslands/LandsDependency.java | 17 ++++ .../land/LandHolderProvider.java | 99 ++++++++++++------- src/main/resources/config.yml | 5 +- 5 files changed, 98 insertions(+), 45 deletions(-) diff --git a/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java b/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java index 9041054..5c89792 100644 --- a/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java +++ b/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java @@ -12,24 +12,31 @@ import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; +import java.util.logging.Level; import java.util.logging.Logger; public class GringottsLands extends JavaPlugin { private static final String MESSAGES_YML = "messages.yml"; public static Logger LOGGER; + private LandsDependency landsDependency; + @Override public void onLoad() { try { Plugin plugin = Gringotts.instance.getDependencies() .hookPlugin("Lands", "me.angeschossen.lands.Lands", "7.9.5"); + this.landsDependency = new LandsDependency(Gringotts.instance, plugin); + if (plugin != null && Gringotts.instance.getDependencies() - .registerDependency(new LandsDependency(Gringotts.instance, plugin))) { + .registerDependency(this.landsDependency)) { getLogger().warning("Lands plugin is already assigned into the dependencies."); } } catch (IllegalArgumentException e) { getLogger().warning("Looks like Lands plugin is not compatible with Gringotts"); + this.onDisable(); + return; } // load and init configuration @@ -37,18 +44,16 @@ public void onLoad() { reloadConfig(); LOGGER = this.getLogger(); + if (LandsConfiguration.CONF.debug) { + LOGGER.setLevel(Level.ALL); + } Gringotts.instance.getDependencies().getDependency("lands").ifPresent(Dependency::onLoad); } @Override public void onEnable() { - - } - - @Override - public void onDisable() { - + this.landsDependency.checkLandBalanceConsistency(); } /** diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java index 727ee76..58660d6 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java @@ -15,10 +15,13 @@ public enum LandsConfiguration { public boolean vaultsOnlyInLands = false; public long landStartBalance = 0; + public boolean debug = false; + public void readConfig(FileConfiguration savedConfig) { CONF.language = savedConfig.getString("language", "custom"); CONF.landSignTypeName = savedConfig.getString("land_sign_type_name", "land"); CONF.vaultsOnlyInLands = savedConfig.getBoolean("vaults_only_in_lands", false); CONF.landStartBalance = savedConfig.getLong("land_start_balance", 0); + CONF.debug = savedConfig.getBoolean("debug", false); } } diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java index 006d893..1b98450 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java @@ -5,7 +5,9 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.plugin.Plugin; +import org.gestern.gringotts.Configuration; import org.gestern.gringotts.Gringotts; +import org.gestern.gringotts.GringottsAccount; import org.gestern.gringotts.accountholder.AccountHolder; import org.gestern.gringotts.api.dependency.Dependency; import org.gestern.gringotts.event.PlayerVaultCreationEvent; @@ -73,6 +75,21 @@ public void onEnable() { Gringotts.instance.registerAccountHolderProvider(LandAccountHolder.ACCOUNT_TYPE, this.landHolderProvider); } + public void checkLandBalanceConsistency() { + // Check gringotts/lands balance consistency + for (Land land : this.api.getLands()) { + GringottsLands.LOGGER.fine("Check Land " + land.getULID() + " balance consistency."); + AccountHolder holder = this.landHolderProvider.getAccountHolder(land); + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + double landBalance = land.getBalance(); + double balance = Configuration.CONF.getCurrency().getDisplayValue(account.getBalance()); + if (landBalance != balance) { + GringottsLands.LOGGER.severe("Update Land " + land.getULID() + " balance to resolve inconsistency. (current: " + landBalance + " gringotts: " + balance + ")" ); + land.setBalance(balance); + } + } + } + /** * Vault created. * diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index 5c2d26f..07b3345 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -5,6 +5,7 @@ import me.angeschossen.lands.api.events.LandDeleteEvent; import me.angeschossen.lands.api.events.LandRenameEvent; import me.angeschossen.lands.api.events.land.bank.LandBankBalanceChangedEvent; +import me.angeschossen.lands.api.events.land.bank.LandBankDepositEvent; import me.angeschossen.lands.api.events.land.bank.LandBankWithdrawEvent; import me.angeschossen.lands.api.land.Land; import me.angeschossen.lands.api.memberholder.MemberHolder; @@ -21,7 +22,6 @@ import org.gestern.gringotts.GringottsAccount; import org.gestern.gringotts.accountholder.AccountHolder; import org.gestern.gringotts.accountholder.AccountHolderProvider; -import org.gestern.gringotts.api.Account; import org.gestern.gringotts.api.TransactionResult; import org.gestern.gringotts.event.AccountBalanceChangeEvent; import org.gestern.gringotts.event.CalculateStartBalanceEvent; @@ -174,10 +174,6 @@ public void deleteLand(LandDeleteEvent event) { Land land = event.getLand(); AccountHolder holder = getAccountHolder(land); - if (holder == null) { - return; - } - GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); if (account == null) { @@ -187,69 +183,98 @@ public void deleteLand(LandDeleteEvent event) { Gringotts.instance.getDao().deleteAccount(account); } + /** + * Gringotts Account Balance Change. + * + * @param event the event + */ @EventHandler public void onBalanceChange(AccountBalanceChangeEvent event) { - if (!event.holder.getType().equals(this.getType())) + GringottsLands.LOGGER.fine(event.toString()); + + if (!event.holder.getType().equals(this.getType())) { + GringottsLands.LOGGER.fine(event + ": ignore holder type " + event.holder.getType()); return; + } double balance = Configuration.CONF.getCurrency().getDisplayValue(event.balance); LandAccountHolder holder = (LandAccountHolder) this.getAccountHolder(event.holder.getId()); if (holder == null) { + GringottsLands.LOGGER.warning(event + ": gringotts account holder not found."); return; } - if (holder.getLand().getBalance() == balance) + if (holder.getLand().getBalance() == balance) { + GringottsLands.LOGGER.fine(event + ": ingore, gringotts account/land balance are identical."); return; + } - GringottsLands.LOGGER.fine("Replicate Gringotts account balance change detected on Land " + holder.getId() + " - " + balance); - + GringottsLands.LOGGER.fine(event + ": replicate Gringotts account balance change on Land."); holder.getLand().setBalance(balance); } + /** + * Land Balance Change. + * + * @param event the event + */ @EventHandler public void onLandBankBalanceChanged(LandBankBalanceChangedEvent event) { - Land land = event.getLand(); + GringottsLands.LOGGER.fine(LogLandBankBalanceChangedEvent(event)); + Land land = event.getLand(); AccountHolder holder = getAccountHolder(land); + GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); + double balance = Configuration.CONF.getCurrency().getDisplayValue(account.getBalance()); - if (holder == null) { + if (event.getNow() == balance) { + GringottsLands.LOGGER.fine(LogLandBankBalanceChangedEvent(event) + ": ignore, gringotts account/land balance are identical."); return; } + + GringottsLands.LOGGER.fine(LogLandBankBalanceChangedEvent(event) + ": replicate Land balance change on Gringotts account."); + long update = Configuration.CONF.getCurrency().getCentValue(event.getNow() - event.getPrevious()); + TransactionResult result; + if (update > 0) { + GringottsLands.LOGGER.fine(LogLandBankBalanceChangedEvent(event) + ": add " + update + " to Gringotts account."); + result = account.add(update); + } else { + GringottsLands.LOGGER.fine(LogLandBankBalanceChangedEvent(event) + ": remove " + update + " from Gringotts account."); + result = account.remove(Math.abs(update)); + } - GringottsAccount account = Gringotts.instance.getAccounting().getAccount(holder); - if (account.getBalance() != event.getNow()) { - GringottsLands.LOGGER.fine("Replicate Land Balance change (from " + event.getPrevious() + " to " + event.getNow() + ") on account " + land.getULID()); - long update = Configuration.CONF.getCurrency().getCentValue(event.getNow() - event.getPrevious()); - TransactionResult result; - if (update > 0) { - result = account.add(update); - } else { - result = account.remove(Math.abs(update)); - } - - if (result != TransactionResult.SUCCESS) { - throw new IllegalStateException(account.owner.getId() + " account transaction error for " - + (event.getNow() - event.getPrevious()) + " " + result); - } + if (result != TransactionResult.SUCCESS) { + throw new IllegalStateException(account.owner.getId() + " account transaction error for " + (event.getNow() - event.getPrevious()) + " " + result); } } + /** + * Player Withdraw from Land + * + * @param event the event + */ @EventHandler public void onLandBankWithdraw(LandBankWithdrawEvent event) { - Land land = event.getLand(); - - AccountHolder holder = getAccountHolder(land); + GringottsLands.LOGGER.fine(event.getLogInfo()); + event.getLandPlayer().getPlayer().sendMessage("Land withdraw not supported by Gringotts integration."); + event.setCancelled(true); + } - if (holder == null) { - return; - } + /** + * Player Deposit to a Land + * + * @param event the event + */ + @EventHandler + public void onLandBankDeposit(LandBankDepositEvent event) { + GringottsLands.LOGGER.fine(event.getLogInfo()); + event.getLandPlayer().getPlayer().sendMessage("Land deposit not supported by Gringotts integration."); + event.setCancelled(true); + } - Account account = Gringotts.instance.getEco().getAccount(holder.getId()); - long value = Configuration.CONF.getCurrency().getCentValue(event.getValue()); - if (!account.has(value)) { - event.setCancelled(true); - } + private static String LogLandBankBalanceChangedEvent(LandBankBalanceChangedEvent event) { + return event.getClass().getSimpleName() + "{land=" + event.getLand().getULID() + ",previous=" + event.getPrevious() + ",now=" + event.getNow() + "}"; } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 2c3c88c..6794c7a 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -9,4 +9,7 @@ land_sign_vault_name: 'land' vaults_only_in_lands: false # balance to start an account with (purely virtual) -land_start_balance: 0 \ No newline at end of file +land_start_balance: 0 + +# Plugin debug +debug: false \ No newline at end of file From d57b252c22957193a63b63b737ec1ff256af4d02 Mon Sep 17 00:00:00 2001 From: Clem Fern Date: Thu, 19 Dec 2024 22:09:37 +0100 Subject: [PATCH 13/14] wip: ref --- .../gringottslands/GringottsLands.java | 15 ++++-- .../gringottslands/LandsDependency.java | 53 ++++++++----------- .../land/LandHolderProvider.java | 6 +-- 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java b/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java index 5c89792..56c08be 100644 --- a/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java +++ b/src/main/java/net/laboulangerie/gringottslands/GringottsLands.java @@ -16,20 +16,27 @@ import java.util.logging.Logger; public class GringottsLands extends JavaPlugin { - private static final String MESSAGES_YML = "messages.yml"; + + public static GringottsLands instance; public static Logger LOGGER; + private static final String MESSAGES_YML = "messages.yml"; + private LandsDependency landsDependency; + public GringottsLands() { + instance = this; + } + @Override public void onLoad() { try { - Plugin plugin = Gringotts.instance.getDependencies() + Plugin lands = Gringotts.instance.getDependencies() .hookPlugin("Lands", "me.angeschossen.lands.Lands", "7.9.5"); - this.landsDependency = new LandsDependency(Gringotts.instance, plugin); + this.landsDependency = new LandsDependency(lands); - if (plugin != null && Gringotts.instance.getDependencies() + if (lands != null && Gringotts.instance.getDependencies() .registerDependency(this.landsDependency)) { getLogger().warning("Lands plugin is already assigned into the dependencies."); } diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java index 1b98450..9d770a0 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java @@ -19,28 +19,25 @@ public class LandsDependency implements Dependency, Listener { private final LandHolderProvider landHolderProvider; - private final Gringotts gringotts; - private final Plugin plugin; + private final Plugin lands; private final String id; private final LandsIntegration api; /** * Instantiates a new Lands dependency. * - * @param gringotts the gringotts - * @param plugin the plugin + * @param lands the plugin */ - public LandsDependency(Gringotts gringotts, Plugin plugin) { - if (plugin == null) { - throw new NullPointerException("'plugin' is null"); + public LandsDependency(Plugin lands) { + if (lands == null) { + throw new NullPointerException("'lands' is null"); } - this.gringotts = gringotts; - this.plugin = plugin; + this.lands = lands; this.id = "lands"; - this.api = LandsIntegration.of(plugin); - this.landHolderProvider = new LandHolderProvider(this.gringotts, this.api); + this.api = LandsIntegration.of(lands); + this.landHolderProvider = new LandHolderProvider(this.api); } @@ -61,7 +58,7 @@ public String getId() { */ @Override public Plugin getPlugin() { - return this.plugin; + return this.lands; } /** @@ -69,8 +66,8 @@ public Plugin getPlugin() { */ @Override public void onEnable() { - Bukkit.getPluginManager().registerEvents(this, this.gringotts); - Bukkit.getPluginManager().registerEvents(this.landHolderProvider, this.gringotts); + Bukkit.getPluginManager().registerEvents(this, Gringotts.instance); + Bukkit.getPluginManager().registerEvents(this.landHolderProvider, Gringotts.instance); Gringotts.instance.registerAccountHolderProvider(LandAccountHolder.ACCOUNT_TYPE, this.landHolderProvider); } @@ -110,30 +107,24 @@ public void vaultCreated(PlayerVaultCreationEvent event) { Player player = event.getCause().getPlayer(); - AccountHolder owner; - - if (event.getType().equals(LandsConfiguration.CONF.landSignTypeName)) { - if (!LandsPermissions.CREATE_VAULT_LAND.isAllowed(player)) { - player.sendMessage(LandsLanguage.LANG.noLandVaultPerm); - - return; - } - - Land land = this.api.getLandByName(line2String); - if (land == null) { - player.sendMessage(LandsLanguage.LANG.noLandFound); - return; - } + if (!event.getType().equals(LandsConfiguration.CONF.landSignTypeName)) { + return; + + } - owner = this.landHolderProvider.getAccountHolder(land); - } else { + if (!LandsPermissions.CREATE_VAULT_LAND.isAllowed(player)) { + player.sendMessage(LandsLanguage.LANG.noLandVaultPerm); return; } - if (owner == null) { + Land land = this.api.getLandByName(line2String); + if (land == null) { + player.sendMessage(LandsLanguage.LANG.noLandFound); return; } + AccountHolder owner = this.landHolderProvider.getAccountHolder(land); + if (LandsConfiguration.CONF.vaultsOnlyInLands && this.api.getArea(event.getCause().getBlock().getLocation()) == null) { event.getCause().getPlayer().sendMessage(LandsLanguage.LANG.vaultNotInLand); return; diff --git a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java index 07b3345..b02f011 100644 --- a/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java +++ b/src/main/java/net/laboulangerie/gringottslands/land/LandHolderProvider.java @@ -34,11 +34,9 @@ public class LandHolderProvider implements AccountHolderProvider, Listener { - private Gringotts gringotts; private LandsIntegration api; - public LandHolderProvider(Gringotts gringotts, LandsIntegration api) { - this.gringotts = gringotts; + public LandHolderProvider(LandsIntegration api) { this.api = api; } @@ -147,7 +145,7 @@ public void run() { Gringotts.instance.getDao().retrieveChests(account).forEach(AccountChest::updateSign); } - }.runTask(this.gringotts); + }.runTask(GringottsLands.instance); } /** From 26f386759937c1a30f47d61178879cc15e0d78e1 Mon Sep 17 00:00:00 2001 From: Clem Fern Date: Thu, 19 Dec 2024 22:27:25 +0100 Subject: [PATCH 14/14] wip: land vault limit --- .../gringottslands/LandsConfiguration.java | 3 +++ .../laboulangerie/gringottslands/LandsDependency.java | 5 +++++ .../laboulangerie/gringottslands/LandsLanguage.java | 11 +++++------ src/main/resources/config.yml | 3 +++ src/main/resources/i18n/messages_fr.yml | 1 + src/main/resources/messages.yml | 1 + 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java index 58660d6..a939795 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsConfiguration.java @@ -12,6 +12,8 @@ public enum LandsConfiguration { public String language = "custom"; public String landSignTypeName = "land"; + public int maxLandVaults = -1; + public boolean vaultsOnlyInLands = false; public long landStartBalance = 0; @@ -20,6 +22,7 @@ public enum LandsConfiguration { public void readConfig(FileConfiguration savedConfig) { CONF.language = savedConfig.getString("language", "custom"); CONF.landSignTypeName = savedConfig.getString("land_sign_type_name", "land"); + CONF.maxLandVaults = savedConfig.getInt("max_land_vaults", -1); CONF.vaultsOnlyInLands = savedConfig.getBoolean("vaults_only_in_lands", false); CONF.landStartBalance = savedConfig.getLong("land_start_balance", 0); CONF.debug = savedConfig.getBoolean("debug", false); diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java index 9d770a0..516dba7 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsDependency.java @@ -130,6 +130,11 @@ public void vaultCreated(PlayerVaultCreationEvent event) { return; } + if (LandsConfiguration.CONF.maxLandVaults != -1 && ((int) Gringotts.instance.getDao().retrieveChests().stream().filter(c -> c.account.owner.getId().equals(land.getULID().toString())).count() + 1) > LandsConfiguration.CONF.maxLandVaults) { + event.getCause().getPlayer().sendMessage(LandsLanguage.LANG.tooManyVaults); + return; + } + event.setOwner(owner); event.setValid(true); } diff --git a/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java b/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java index 3e78e19..18d5fcd 100644 --- a/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java +++ b/src/main/java/net/laboulangerie/gringottslands/LandsLanguage.java @@ -12,16 +12,15 @@ public enum LandsLanguage { public String noLandVaultPerm; public String noLandFound; public String vaultNotInLand; + public String tooManyVaults; public void readLanguage(FileConfiguration savedLanguage) { - BiFunction translator = (path, - def) -> translateColors(savedLanguage.getString(path, def)); + BiFunction translator = (path, def) -> translateColors(savedLanguage.getString(path, def)); - LANG.noLandVaultPerm = translator.apply("noLandPerm", - "You do not have permission to create land vaults here."); - LANG.noLandFound = translator.apply("noLandFound", - "Cannot create land vault: Land not found."); + LANG.noLandVaultPerm = translator.apply("noLandPerm", "You do not have permission to create land vaults here."); + LANG.noLandFound = translator.apply("noLandFound", "Cannot create land vault: Land not found."); LANG.vaultNotInLand = translator.apply("vaultNotInLand", "You cannot create vaults outside of lands."); + LANG.tooManyVaults = translator.apply("tooManyVaults", "You cannot create more vaults! Max: %max"); } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6794c7a..af78429 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -8,6 +8,9 @@ land_sign_vault_name: 'land' # Prevents players from creating a vault outside a land if set to true vaults_only_in_lands: false +# Maximum number of vaults a town can own, set to -1 for infinite number of vaults +max_land_vaults: -1 + # balance to start an account with (purely virtual) land_start_balance: 0 diff --git a/src/main/resources/i18n/messages_fr.yml b/src/main/resources/i18n/messages_fr.yml index ce59c04..f402de5 100644 --- a/src/main/resources/i18n/messages_fr.yml +++ b/src/main/resources/i18n/messages_fr.yml @@ -1,3 +1,4 @@ noLandVaultPerm: "Vous n'avez pas la permission de créer un coffre-fort de ville ici." noLandFound: "Impossible de créer un coffre-fort de ville : La ville spécifiée n'existe pas." vaultNotInLand: "Vous ne pouvez pas créer de coffre-fort en dehors des villes." +tooManyVaults: "Vous ne pouvez pas créer plus de coffre-fort ! Max : %max" \ No newline at end of file diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 04f707c..d6f2fdb 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -1,3 +1,4 @@ noLandVaultPerm: "You do not have permission to create land vaults here." noLandFound: "Cannot create land vault: Land not found." vaultNotInLand: "You cannot create vaults outside of lands." +tooManyVaults: "You cannot create more vaults! Max: %max" \ No newline at end of file