Ça dépend de comment est structurer ton code, normalement tu devrais avoir une classe pour représenter une instance de mini-jeu et il te suffit d'y ajouter des fonctions pour sauvegarder et charger ;
Java:
public class GameInstance {
private static final AtomicInteger LAST_ID = new AtomicInteger(0);
private static final String FILENAME = "internal/GameInstances.dat";
private static final Map<Integer, GameInstance> INSTANCES = new HashMap<>();
private final int id;
private final Set<UUID> players;
private final Map<UUID, Integer> stats;
public GameInstance() {
this.id = LAST_ID.incrementAndGet();
this.players = new HashSet<>();
this.stats = new HashMap<>();
INSTANCES.put(this.id, this);
}
private GameInstance(int id, Set<UUID> players, Map<UUID, Integer> stats) {
this.id = id;
this.players = players;
this.stats = stats;
INSTANCES.put(this.id, this);
}
public static void loadAll(JavaPlugin plugin) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), FILENAME));
Set<String> keys = config.getKeys(false);
for(String key : keys) {
final int id;
try {
id = Integer.parseInt(key);
if(id <= 0) {
throw new NumberFormatException();
}
}
catch(NumberFormatException ignored) {
plugin.getLogger().warning("GameInstances: invalid key `" + key + '`');
continue;
}
LAST_ID.updateAndGet(prev -> Math.max(id, prev));
try {
load(config, id);
}
catch(Exception e) {
plugin.getLogger().severe("GameInstances: unable to load key `" + key + '`');
}
}
}
@SuppressWarnings({ "unchecked", "ConstantConditions" })
private static GameInstance load(YamlConfiguration config, int id) {
ConfigurationSection section = config.getConfigurationSection(String.valueOf(id));
Set<UUID> players = (Set<UUID>) section.get("players");
Map<UUID, Integer> stats = (Map<UUID, Integer>) section.get("stats");
return new GameInstance(id, players, stats);
}
public static void saveAll(JavaPlugin plugin) {
YamlConfiguration config = new YamlConfiguration();
for(GameInstance instance : INSTANCES.values()) {
instance.saveInto(config);
}
try {
config.save(new File(plugin.getDataFolder(), FILENAME));
}
catch(IOException e) {
plugin.getLogger().log(Level.SEVERE, "GameInstances: unable to save on disk", e);
}
}
private void saveInto(YamlConfiguration config) {
ConfigurationSection section = config.createSection(String.valueOf(this.id));
section.set("players", this.players);
section.set("stats", this.stats);
}
public int getId() {
return this.id;
}
public boolean addPlayer(UUID playerId) {
return this.players.add(playerId);
}
public boolean addPlayer(Player player) {
return this.addPlayer(player.getUniqueId());
}
public boolean removePlayer(UUID playerId) {
return this.players.remove(playerId);
}
public boolean removePlayer(Player player) {
return this.removePlayer(player.getUniqueId());
}
@UnmodifiableView
public Set<UUID> playerIds() {
return Collections.unmodifiableSet(this.players);
}
public Stream<OfflinePlayer> offlinePlayers() {
return this.players.stream().map(Bukkit::getOfflinePlayer);
}
public Stream<Player> onlinePlayers() {
return this.players.stream().map(Bukkit::getPlayer).filter(Objects::nonNull);
}
public int incrementKillsFor(Player player) {
if(!this.players.contains(player.getUniqueId())) {
throw new IllegalArgumentException("Cannot increment stats for someone does not participate in this GameInstance");
}
return this.stats.compute(player.getUniqueId(), (playerId, currentVal) -> ((currentVal == null) ? 1 : currentVal + 1));
}
public int getKillsFor(UUID playerId) {
return this.stats.getOrDefault(playerId, 0);
}
public int getKillsFor(Player player) {
return this.getKillsFor(player.getUniqueId());
}
}
Java:
public class PlaygroundPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
GameInstance.loadAll(this);
}
@Override
public void onDisable() {
GameInstance.saveAll(this);
}
}
Pour éviter de perdre des données il faudrait rajouter une variable pour ne pas sauvegarder si jamais le fichier n'a pas été chargé (si tu as une exception dans ton
onEnable()
, il se peut que tu n'aies pas encore chargé le fichier entièrement, mais Bukkit appellera quand même le
onDisable()
de ton plugin, ce qui resauvegardera partiellement le fichier).
De la même façon si le serveur s'arrête brutalement pendant une sauvegarde, la mémoire sera libérée et le fichier sur le disque dur ne sera probablement pas entier, donc généralement pour sauvegarder dans un fichier
A
, l'on sauvegarde dans
A.tmp
, puis une fois que tout a été écrit on supprime
A
puis on renomme
A.tmp
en
A
; il faut donc aussi gérer le cas où
A.tmp
existe mais pas
A
au chargement (arrêt pendant le renommage).