9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-31 12:56:43 +00:00

checkpoint - 22

This commit is contained in:
XiaoMoMi
2024-07-04 00:15:44 +08:00
parent f3d21e466d
commit 274055dfce
91 changed files with 420 additions and 5956 deletions

View File

@@ -17,6 +17,7 @@
package net.momirealms.customfishing.api.event;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import org.bukkit.Location;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
@@ -30,11 +31,13 @@ public class FishingLootSpawnEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private final Location location;
private final Item item;
private final Loot loot;
private boolean isCancelled;
public FishingLootSpawnEvent(@NotNull Player who, Location location, Item item) {
public FishingLootSpawnEvent(@NotNull Player who, Location location, Loot loot, Item item) {
super(who);
this.item = item;
this.loot = loot;
this.location = location;
this.isCancelled = false;
}
@@ -57,6 +60,10 @@ public class FishingLootSpawnEvent extends PlayerEvent implements Cancellable {
return item;
}
public Loot getLoot() {
return loot;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlerList;

View File

@@ -17,6 +17,8 @@
package net.momirealms.customfishing.api.event;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player;
@@ -24,14 +26,9 @@ import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Optional;
/**
* This class represents an event that occurs when a player gets a result from fishing.
*/
public class FishingResultEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
@@ -39,21 +36,12 @@ public class FishingResultEvent extends PlayerEvent implements Cancellable {
private final Result result;
private final Loot loot;
private final FishHook fishHook;
private final Map<String, String> args;
private Context<Player> context;
/**
* Constructs a new FishingResultEvent.
*
* @param who The player who triggered the event.
* @param result The result of the fishing action (SUCCESS or FAILURE).
* @param loot The loot received from fishing.
* @param args A map of placeholders and their corresponding values.
*/
public FishingResultEvent(@NotNull Player who, Result result, FishHook fishHook, Loot loot, Map<String, String> args) {
super(who);
public FishingResultEvent(@NotNull Context<Player> context, Result result, FishHook fishHook, Loot loot) {
super(context.getHolder());
this.result = result;
this.loot = loot;
this.args = args;
this.fishHook = fishHook;
}
@@ -77,87 +65,31 @@ public class FishingResultEvent extends PlayerEvent implements Cancellable {
isCancelled = cancel;
}
/**
* Gets the value associated with a specific argument key.
* Usage example event.getArg("{x}")
*
* @param key The argument key enclosed in curly braces, e.g., "{amount}".
* @return The value associated with the argument key, or null if not found.
*/
public String getArg(String key) {
return args.get(key);
}
/**
* Set the value associated with a specific argument key.
* @param key key
* @param value value
* @return previous value
*/
@Nullable
public String setArg(String key, String value) {
return args.put(key, value);
}
/**
* Gets the result of the fishing action.
*
* @return The fishing result, which can be either SUCCESS or FAILURE.
*/
public Result getResult() {
return result;
}
/**
* Get the fish hook entity.
*
* @return fish hook
*/
public FishHook getFishHook() {
return fishHook;
}
/**
* Gets the loot received from fishing.
*
* @return The loot obtained from the fishing action.
*/
public Loot getLoot() {
return loot;
}
/**
* Gets the amount of loot received.
* This value is determined by the "multiple-loot" effect.
* If you want to get the amount of item spawned, listen to FishingLootSpawnEvent
*
* @return The amount of loot received, or 1 if the loot is block or entity
*/
public int getAmount() {
return Integer.parseInt(Optional.ofNullable(getArg("{amount}")).orElse("1"));
}
/**
* Set the loot amount (Only works for items)
*
* @param amount amount
*/
public void setAmount(int amount) {
setArg("{amount}", String.valueOf(amount));
}
/**
* Set the score to get in competition
*
* @param score score
*/
public void setScore(double score) {
setArg("{SCORE}", String.valueOf(score));
context.arg(ContextKeys.CUSTOM_SCORE, score);
}
public Context<Player> getContext() {
return context;
}
public int getAmount() {
if (result == Result.FAILURE) return 0;
return Optional.ofNullable(context.arg(ContextKeys.AMOUNT)).orElse(1);
}
/**
* An enumeration representing possible fishing results (SUCCESS or FAILURE).
*/
public enum Result {
SUCCESS,
FAILURE

View File

@@ -18,7 +18,8 @@
package net.momirealms.customfishing.api.mechanic.competition;
import net.kyori.adventure.util.Index;
import net.momirealms.customfishing.common.locale.StandardLocales;
import net.momirealms.customfishing.common.locale.MessageConstants;
import net.momirealms.customfishing.common.locale.TranslationManager;
import net.momirealms.customfishing.common.util.RandomUtils;
import org.apache.logging.log4j.util.Supplier;
import org.apache.logging.log4j.util.TriConsumer;
@@ -31,12 +32,12 @@ public final class CompetitionGoal {
public static final CompetitionGoal CATCH_AMOUNT = new CompetitionGoal(
"catch_amount",
((rankingProvider, player, score) -> rankingProvider.refreshData(player, 1)),
() -> Optional.ofNullable(StandardLocales.GOAL_CATCH_AMOUNT).orElse("catch_amount")
() -> Optional.ofNullable(TranslationManager.miniMessageTranslation(MessageConstants.GOAL_CATCH_AMOUNT.build().key())).orElse("catch_amount")
);
public static final CompetitionGoal TOTAL_SCORE = new CompetitionGoal(
"total_score",
(RankingProvider::refreshData),
() -> Optional.ofNullable(StandardLocales.GOAL_TOTAL_SCORE).orElse("total_score")
() -> Optional.ofNullable(TranslationManager.miniMessageTranslation(MessageConstants.GOAL_TOTAL_SCORE.build().key())).orElse("total_score")
);
public static final CompetitionGoal MAX_SIZE = new CompetitionGoal(
"max_size",
@@ -45,7 +46,7 @@ public final class CompetitionGoal {
rankingProvider.setData(player, score);
}
}),
() -> Optional.ofNullable(StandardLocales.GOAL_MAX_SIZE).orElse("max_size")
() -> Optional.ofNullable(TranslationManager.miniMessageTranslation(MessageConstants.GOAL_MAX_SIZE.build().key())).orElse("max_size")
);
public static final CompetitionGoal MIN_SIZE = new CompetitionGoal(
"min_size",
@@ -54,12 +55,12 @@ public final class CompetitionGoal {
rankingProvider.setData(player, score);
}
}),
() -> Optional.ofNullable(StandardLocales.GOAL_MIN_SIZE).orElse("min_size")
() -> Optional.ofNullable(TranslationManager.miniMessageTranslation(MessageConstants.GOAL_MIN_SIZE.build().key())).orElse("min_size")
);
public static final CompetitionGoal TOTAL_SIZE = new CompetitionGoal(
"total_size",
(RankingProvider::refreshData),
() -> Optional.ofNullable(StandardLocales.GOAL_TOTAL_SIZE).orElse("total_size")
() -> Optional.ofNullable(TranslationManager.miniMessageTranslation(MessageConstants.GOAL_TOTAL_SIZE.build().key())).orElse("total_size")
);
public static final CompetitionGoal RANDOM = new CompetitionGoal(
"random",

View File

@@ -73,6 +73,8 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
protected boolean allowSameTotemType;
protected EventPriority eventPriority;
protected Requirement<Player>[] mechanicRequirements;
protected Requirement<Player>[] skipGameRequirements;
protected Requirement<Player>[] autoFishingRequirements;
protected boolean enableBag;
protected List<TriConsumer<Effect, Context<Player>, Integer>> globalEffects;
@@ -193,6 +195,14 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
return instance.mechanicRequirements;
}
public static Requirement<Player>[] autoFishingRequirements() {
return instance.autoFishingRequirements;
}
public static Requirement<Player>[] skipGameRequirements() {
return instance.skipGameRequirements;
}
public static List<TriConsumer<Effect, Context<Player>, Integer>> globalEffects() {
return instance.globalEffects;
}

View File

@@ -50,7 +50,7 @@ public class ConfigType {
MechanicType.register(id, MechanicType.ROD);
RodConfigParser config = new RodConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
//BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier(), MechanicType.ROD);
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}
@@ -62,7 +62,7 @@ public class ConfigType {
MechanicType.register(id, MechanicType.BAIT);
BaitConfigParser config = new BaitConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
//BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier(), MechanicType.BAIT);
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}
@@ -74,7 +74,7 @@ public class ConfigType {
MechanicType.register(id, MechanicType.HOOK);
HookConfigParser config = new HookConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
//BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier(), MechanicType.HOOK);
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
BukkitCustomFishingPlugin.getInstance().getHookManager().registerHook(config.getHook());
@@ -87,7 +87,7 @@ public class ConfigType {
MechanicType.register(id, MechanicType.UTIL);
UtilConfigParser config = new UtilConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
//BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier(), MechanicType.UTIL);
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}

View File

@@ -64,6 +64,7 @@ public class ContextKeys<T> {
public static final ContextKeys<String> REST = of("rest", String.class);
public static final ContextKeys<String> REST_FORMATTED = of("rest_formatted", String.class);
public static final ContextKeys<Integer> SOLD_ITEM_AMOUNT = of("sold_item_amount", Integer.class);
public static final ContextKeys<Integer> AMOUNT = of("amount", Integer.class);
public static final ContextKeys<Double> WEIGHT = of("0", Double.class);
public static final ContextKeys<String> TIME_LEFT = of("time_left", String.class);

View File

@@ -1,6 +1,7 @@
package net.momirealms.customfishing.api.mechanic.fishing;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.event.FishingResultEvent;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.competition.CompetitionGoal;
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
@@ -17,10 +18,12 @@ import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager;
import net.momirealms.customfishing.api.util.EventUtils;
import net.momirealms.customfishing.common.helper.AdventureHelper;
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
import net.momirealms.customfishing.common.util.TriConsumer;
import net.momirealms.customfishing.common.util.TriFunction;
import net.momirealms.sparrow.heart.SparrowHeart;
import org.bukkit.Statistic;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
@@ -141,7 +144,7 @@ public class CustomFishingHook {
}
public void destroy() {
task.cancel();
if (task != null) task.cancel();
if (hook.isValid()) hook.remove();
if (hookMechanic != null) hookMechanic.destroy();
}
@@ -165,24 +168,42 @@ public class CustomFishingHook {
if (hookMechanic != null) {
if (!hookMechanic.isHooked()) {
gears.trigger(ActionTrigger.REEL, context);
destroy();
end();
} else {
if (nextLoot.disableGame()) {
if (nextLoot.disableGame() || RequirementManager.isSatisfied(context, ConfigManager.skipGameRequirements())) {
handleSuccessfulFishing();
destroy();
end();
} else {
handleSuccessfulFishing();
destroy();
end();
}
}
} else {
gears.trigger(ActionTrigger.REEL, context);
destroy();
end();
}
}
private void end() {
plugin.getFishingManager().destroy(context.getHolder().getUniqueId());
}
public void onBite() {
plugin.getEventManager().trigger(context, nextLoot.id(), MechanicType.getTypeByID(nextLoot.id()), ActionTrigger.BITE);
gears.trigger(ActionTrigger.BITE, context);
if (RequirementManager.isSatisfied(context, ConfigManager.autoFishingRequirements())) {
handleSuccessfulFishing();
SparrowHeart.getInstance().swingHand(context.getHolder(), gears.getRodSlot());
end();
scheduleNextFishing();
}
if (nextLoot.instantGame()) {
}
}
private void scheduleNextFishing() {
}
public void onLand() {
@@ -190,10 +211,12 @@ public class CustomFishingHook {
}
public void onEscape() {
plugin.getEventManager().trigger(context, nextLoot.id(), MechanicType.getTypeByID(nextLoot.id()), ActionTrigger.ESCAPE);
gears.trigger(ActionTrigger.ESCAPE, context);
}
public void onLure() {
plugin.getEventManager().trigger(context, nextLoot.id(), MechanicType.getTypeByID(nextLoot.id()), ActionTrigger.LURE);
gears.trigger(ActionTrigger.LURE, context);
}
@@ -206,9 +229,7 @@ public class CustomFishingHook {
context.arg(ContextKeys.HOOK_Z, hook.getLocation().getBlockZ());
gears.trigger(ActionTrigger.FAILURE, context);
String id = context.arg(ContextKeys.ID);
BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, MechanicType.getTypeByID(id), ActionTrigger.FAILURE);
plugin.getEventManager().trigger(context, nextLoot.id(), MechanicType.getTypeByID(nextLoot.id()), ActionTrigger.FAILURE);
}
private void handleSuccessfulFishing() {
@@ -222,43 +243,55 @@ public class CustomFishingHook {
LootType lootType = context.arg(ContextKeys.LOOT);
Objects.requireNonNull(lootType, "Missing loot type");
Objects.requireNonNull(tempFinalEffect, "Missing final effects");
int amount;
if (lootType == LootType.ITEM) {
amount = (int) tempFinalEffect.multipleLootChance();
amount += Math.random() < (tempFinalEffect.multipleLootChance() - amount) ? 2 : 1;
} else {
amount = 1;
}
// set the amount of loot
context.arg(ContextKeys.AMOUNT, amount);
FishingResultEvent event = new FishingResultEvent(context, FishingResultEvent.Result.SUCCESS, hook, nextLoot);
if (EventUtils.fireAndCheckCancel(event)) {
return;
}
switch (lootType) {
case ITEM -> {
int amount = (int) tempFinalEffect.multipleLootChance();
amount += Math.random() < (tempFinalEffect.multipleLootChance() - amount) ? 2 : 1;
for (int i = 0; i < amount; i++) {
plugin.getScheduler().sync().runLater(() -> {
Item item = plugin.getItemManager().dropItemLoot(context, gears.getItem(FishingGears.GearType.ROD).stream().findAny().orElseThrow().right(), hook);
if (item != null) {
if (Objects.equals(context.arg(ContextKeys.NICK), "UNDEFINED")) {
ItemStack stack = item.getItemStack();
Optional<String> displayName = plugin.getItemManager().wrap(stack).displayName();
if (displayName.isPresent()) {
context.arg(ContextKeys.NICK, AdventureHelper.jsonToMiniMessage(displayName.get()));
} else {
context.arg(ContextKeys.NICK, "<lang:" + stack.getType().translationKey() + ">");
}
if (item != null && Objects.equals(context.arg(ContextKeys.NICK), "UNDEFINED")) {
ItemStack stack = item.getItemStack();
Optional<String> displayName = plugin.getItemManager().wrap(stack).displayName();
if (displayName.isPresent()) {
context.arg(ContextKeys.NICK, AdventureHelper.jsonToMiniMessage(displayName.get()));
} else {
context.arg(ContextKeys.NICK, "<lang:" + stack.getType().translationKey() + ">");
}
}
handleSuccess();
doSuccessActions();
}, (long) ConfigManager.multipleLootSpawnDelay() * i, hook.getLocation());
}
}
case BLOCK -> {
BukkitCustomFishingPlugin.getInstance().getBlockManager().summonBlockLoot(context);
handleSuccess();
plugin.getBlockManager().summonBlockLoot(context);
doSuccessActions();
}
case ENTITY -> {
BukkitCustomFishingPlugin.getInstance().getEntityManager().summonEntityLoot(context);
handleSuccess();
plugin.getEntityManager().summonEntityLoot(context);
doSuccessActions();
}
}
gears.trigger(ActionTrigger.SUCCESS, context);
}
private void handleSuccess() {
FishingCompetition competition = BukkitCustomFishingPlugin.getInstance().getCompetitionManager().getOnGoingCompetition();
private void doSuccessActions() {
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
if (competition != null && RequirementManager.isSatisfied(context, competition.getConfig().joinRequirements())) {
Double customScore = context.arg(ContextKeys.CUSTOM_SCORE);
if (customScore != null) {
@@ -292,15 +325,15 @@ public class CustomFishingHook {
String id = context.arg(ContextKeys.ID);
Player player = context.getHolder();
MechanicType type = MechanicType.getTypeByID(id);
BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, type, ActionTrigger.SUCCESS);
plugin.getEventManager().trigger(context, id, type, ActionTrigger.SUCCESS);
player.setStatistic(Statistic.FISH_CAUGHT, player.getStatistic(Statistic.FISH_CAUGHT) + 1);
if (!nextLoot.disableStats()) {
BukkitCustomFishingPlugin.getInstance().getStorageManager().getOnlineUser(player.getUniqueId()).ifPresent(
plugin.getStorageManager().getOnlineUser(player.getUniqueId()).ifPresent(
userData -> {
userData.statistics().addAmount(id, 1);
Optional.ofNullable(context.arg(ContextKeys.SIZE)).ifPresent(size -> {
if (userData.statistics().updateSize(id, size)) {
BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, type, ActionTrigger.NEW_SIZE_RECORD);
plugin.getEventManager().trigger(context, id, type, ActionTrigger.NEW_SIZE_RECORD);
}
});
}

View File

@@ -11,9 +11,9 @@ import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager;
import net.momirealms.customfishing.api.storage.user.UserData;
import net.momirealms.customfishing.common.util.Pair;
import net.momirealms.customfishing.common.util.TriConsumer;
import net.momirealms.sparrow.heart.feature.inventory.HandSlot;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@@ -42,6 +42,7 @@ public class FishingGears {
private final HashMap<GearType, Collection<Pair<String, ItemStack>>> gears = new HashMap<>();
private final ArrayList<EffectModifier> modifiers = new ArrayList<>();
private boolean canFish = true;
private HandSlot rodSlot;
public static void fishingGearsConsumers(BiConsumer<Context<Player>, FishingGears> fishingGearsConsumers) {
FishingGears.fishingGearsConsumers = fishingGearsConsumers;
@@ -70,6 +71,10 @@ public class FishingGears {
return modifiers;
}
public HandSlot getRodSlot() {
return rodSlot;
}
@NotNull
public Collection<Pair<String, ItemStack>> getItem(GearType type) {
return gears.getOrDefault(type, List.of());
@@ -86,6 +91,7 @@ public class FishingGears {
String rodID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(rodOnMainHand ? mainHandItem : offHandItem);
fishingGears.gears.put(GearType.ROD, List.of(Pair.of(rodID, rodOnMainHand ? mainHandItem : offHandItem)));
context.arg(ContextKeys.ROD, rodID);
fishingGears.rodSlot = rodOnMainHand ? HandSlot.MAIN : HandSlot.OFF;
BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(rodID, MechanicType.ROD).ifPresent(fishingGears.modifiers::add);
// set enchantments

View File

@@ -7,6 +7,7 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.Optional;
import java.util.TreeSet;
import java.util.function.BiConsumer;
@@ -27,7 +28,7 @@ public class CustomFishingItemImpl implements CustomFishingItem {
@Override
public String material() {
return material;
return Optional.ofNullable(material).orElse("AIR");
}
@Override

View File

@@ -25,10 +25,13 @@ import org.jetbrains.annotations.NotNull;
public interface Loot {
boolean DEFAULT_INSTANT_GAME = false;
boolean DEFAULT_DISABLE_GAME = false;
boolean DEFAULT_DISABLE_STATS = false;
boolean DEFAULT_SHOW_IN_FINDER = false;
class DefaultProperties {
public static boolean DEFAULT_INSTANT_GAME = false;
public static boolean DEFAULT_DISABLE_GAME = false;
public static boolean DEFAULT_DISABLE_STATS = false;
public static boolean DEFAULT_SHOW_IN_FINDER = false;
}
LootType DEFAULT_TYPE = LootType.ITEM;
MathValue<Player> DEFAULT_SCORE = MathValue.plain(0);

View File

@@ -97,10 +97,10 @@ public class LootImpl implements Loot {
public static class BuilderImpl implements Builder {
private LootType type = DEFAULT_TYPE;
private boolean instantGame = DEFAULT_INSTANT_GAME;
private boolean disableGame = DEFAULT_DISABLE_GAME;
private boolean disableStatistics = DEFAULT_DISABLE_STATS;
private boolean showInFinder = DEFAULT_SHOW_IN_FINDER;
private boolean instantGame = Loot.DefaultProperties.DEFAULT_INSTANT_GAME;
private boolean disableGame = Loot.DefaultProperties.DEFAULT_DISABLE_GAME;
private boolean disableStatistics = Loot.DefaultProperties.DEFAULT_DISABLE_STATS;
private boolean showInFinder = Loot.DefaultProperties.DEFAULT_SHOW_IN_FINDER;
private String id = null;
private String nick = "UNDEFINED";
private StatisticsKeys statisticsKeys = null;