From a43e080538436dbada933504e84f0c44e24f92a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20=C3=81d=C3=A1m?= Date: Fri, 25 Nov 2022 12:44:46 +0200 Subject: [PATCH] implement proper serialization --- src/main/java/com/vamk/tbg/Main.java | 15 +++- .../com/vamk/tbg/combat/AbstractMove.java | 4 - .../java/com/vamk/tbg/combat/BuffMove.java | 3 - .../com/vamk/tbg/combat/CombatRegistry.java | 19 +++++ .../java/com/vamk/tbg/combat/CureMove.java | 3 - .../java/com/vamk/tbg/combat/DebuffMove.java | 3 - .../vamk/tbg/combat/GenericAttackMove.java | 3 - .../java/com/vamk/tbg/combat/HealAllMove.java | 3 - .../java/com/vamk/tbg/combat/HealMove.java | 3 - src/main/java/com/vamk/tbg/combat/Move.java | 4 +- .../com/vamk/tbg/combat/SplashDamageMove.java | 3 - .../tbg/effect/BleedingEffectHandler.java | 14 ++-- .../vamk/tbg/effect/RegenEffectHandler.java | 14 ++-- .../vamk/tbg/effect/StatusEffectHandler.java | 7 +- src/main/java/com/vamk/tbg/game/Entity.java | 43 ++++++----- .../com/vamk/tbg/game/EntitySnapshot.java | 10 +++ src/main/java/com/vamk/tbg/game/Game.java | 75 ++++++++++++------- .../java/com/vamk/tbg/game/GameState.java | 6 +- src/main/java/com/vamk/tbg/util/IOUtil.java | 13 ++++ 19 files changed, 152 insertions(+), 93 deletions(-) create mode 100644 src/main/java/com/vamk/tbg/combat/CombatRegistry.java create mode 100644 src/main/java/com/vamk/tbg/game/EntitySnapshot.java diff --git a/src/main/java/com/vamk/tbg/Main.java b/src/main/java/com/vamk/tbg/Main.java index 55162f3..7bb5a5a 100644 --- a/src/main/java/com/vamk/tbg/Main.java +++ b/src/main/java/com/vamk/tbg/Main.java @@ -10,6 +10,8 @@ import java.io.IOException; import java.util.logging.Logger; +import static com.vamk.tbg.game.GameState.FILEPATH; + public class Main { public static void main(String[] args) { @@ -28,6 +30,17 @@ private Bootstrap() { } private void launch() { + if (IOUtil.fileExists(FILEPATH)) { + try { + GameState state = IOUtil.readObject(GameState.class, FILEPATH); + this.game.importState(state); + IOUtil.remove(FILEPATH); + } catch (ClassNotFoundException | IOException ex) { + LOGGER.severe("Failed to read game state from file"); + ex.printStackTrace(); + } + } + this.game.launch(); this.window.dispose(); } @@ -36,7 +49,7 @@ private void handleForceShutdown() { LOGGER.info("Force shutdown initiated, writing game state to file"); GameState state = this.game.exportState(); try { - IOUtil.writeObject(state, GameState.FILEPATH); + IOUtil.writeObject(state, FILEPATH); } catch (IOException ex) { LOGGER.severe("Failed to write game state to file"); ex.printStackTrace(); diff --git a/src/main/java/com/vamk/tbg/combat/AbstractMove.java b/src/main/java/com/vamk/tbg/combat/AbstractMove.java index f080026..587978c 100644 --- a/src/main/java/com/vamk/tbg/combat/AbstractMove.java +++ b/src/main/java/com/vamk/tbg/combat/AbstractMove.java @@ -2,11 +2,7 @@ import com.vamk.tbg.game.Entity; -import java.io.Serial; - public abstract class AbstractMove implements Move { - @Serial - private static final long serialVersionUID = 1008816914619703220L; private final String id; private final boolean attack; diff --git a/src/main/java/com/vamk/tbg/combat/BuffMove.java b/src/main/java/com/vamk/tbg/combat/BuffMove.java index 64663cc..9403fa6 100644 --- a/src/main/java/com/vamk/tbg/combat/BuffMove.java +++ b/src/main/java/com/vamk/tbg/combat/BuffMove.java @@ -5,7 +5,6 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; -import java.io.Serial; import java.util.logging.Logger; import static com.vamk.tbg.util.RandomUtil.chance; @@ -15,8 +14,6 @@ public class BuffMove extends AbstractMove { private static final int REGEN_CHANCE = 40; private static final int LIFESTEAL_CHANCE = 10; private static final int CAFFEINATED_CHANCE = 5; - @Serial - private static final long serialVersionUID = 9096256805043526477L; public BuffMove() { super("BUFF", false); diff --git a/src/main/java/com/vamk/tbg/combat/CombatRegistry.java b/src/main/java/com/vamk/tbg/combat/CombatRegistry.java new file mode 100644 index 0000000..11cd35e --- /dev/null +++ b/src/main/java/com/vamk/tbg/combat/CombatRegistry.java @@ -0,0 +1,19 @@ +package com.vamk.tbg.combat; + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public final class CombatRegistry { + private final Map moves; + + public CombatRegistry() { + this.moves = Stream.of(new BuffMove(), new CureMove(), new DebuffMove(), new GenericAttackMove(), new HealAllMove(), new HealMove(), new SplashDamageMove()) + .collect(Collectors.toMap(Move::getId, Function.identity())); + } + + public Move findMove(String id) { + return this.moves.get(id); + } +} diff --git a/src/main/java/com/vamk/tbg/combat/CureMove.java b/src/main/java/com/vamk/tbg/combat/CureMove.java index 1a936b0..dbd2c8a 100644 --- a/src/main/java/com/vamk/tbg/combat/CureMove.java +++ b/src/main/java/com/vamk/tbg/combat/CureMove.java @@ -5,13 +5,10 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; -import java.io.Serial; import java.util.logging.Logger; public class CureMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(CureMove.class); - @Serial - private static final long serialVersionUID = 4985779855365158332L; public CureMove() { super("MOVE", false); diff --git a/src/main/java/com/vamk/tbg/combat/DebuffMove.java b/src/main/java/com/vamk/tbg/combat/DebuffMove.java index e78d117..4daa90a 100644 --- a/src/main/java/com/vamk/tbg/combat/DebuffMove.java +++ b/src/main/java/com/vamk/tbg/combat/DebuffMove.java @@ -5,7 +5,6 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; -import java.io.Serial; import java.util.logging.Logger; import static com.vamk.tbg.util.RandomUtil.chance; @@ -15,8 +14,6 @@ public class DebuffMove extends AbstractMove { private static final int BLEEDING_CHANCE = 50; private static final int FROZEN_CHANCE = 10; private static final int CONFUSED_CHANCE = 5; - @Serial - private static final long serialVersionUID = 3531606415607174312L; public DebuffMove() { super("DEBUFF", true); diff --git a/src/main/java/com/vamk/tbg/combat/GenericAttackMove.java b/src/main/java/com/vamk/tbg/combat/GenericAttackMove.java index 7e65c2f..fa9e488 100644 --- a/src/main/java/com/vamk/tbg/combat/GenericAttackMove.java +++ b/src/main/java/com/vamk/tbg/combat/GenericAttackMove.java @@ -5,14 +5,11 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; -import java.io.Serial; import java.util.Random; import java.util.logging.Logger; public class GenericAttackMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(GenericAttackMove.class); - @Serial - private static final long serialVersionUID = 7741676913360830574L; private final transient Random random; public GenericAttackMove() { diff --git a/src/main/java/com/vamk/tbg/combat/HealAllMove.java b/src/main/java/com/vamk/tbg/combat/HealAllMove.java index b292c08..6ecb060 100644 --- a/src/main/java/com/vamk/tbg/combat/HealAllMove.java +++ b/src/main/java/com/vamk/tbg/combat/HealAllMove.java @@ -4,13 +4,10 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; -import java.io.Serial; import java.util.logging.Logger; public class HealAllMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(HealAllMove.class); - @Serial - private static final long serialVersionUID = -1552305301295494669L; public HealAllMove() { super("HEAL_ALL", false); diff --git a/src/main/java/com/vamk/tbg/combat/HealMove.java b/src/main/java/com/vamk/tbg/combat/HealMove.java index ff19b83..44fd79c 100644 --- a/src/main/java/com/vamk/tbg/combat/HealMove.java +++ b/src/main/java/com/vamk/tbg/combat/HealMove.java @@ -5,7 +5,6 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; -import java.io.Serial; import java.util.logging.Logger; import static com.vamk.tbg.util.RandomUtil.chance; @@ -14,8 +13,6 @@ public class HealMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(HealMove.class); private static final int REGENERATION_CHANCE = 15; private static final int LIFESTEAL_CHANCE = 10; - @Serial - private static final long serialVersionUID = -8821620767840800124L; public HealMove() { super("HEAL", false); diff --git a/src/main/java/com/vamk/tbg/combat/Move.java b/src/main/java/com/vamk/tbg/combat/Move.java index 4e30ceb..2964d82 100644 --- a/src/main/java/com/vamk/tbg/combat/Move.java +++ b/src/main/java/com/vamk/tbg/combat/Move.java @@ -3,9 +3,7 @@ import com.vamk.tbg.game.Entity; import com.vamk.tbg.game.MoveContext; -import java.io.Serializable; - -public interface Move extends Serializable { +public interface Move { String getId(); diff --git a/src/main/java/com/vamk/tbg/combat/SplashDamageMove.java b/src/main/java/com/vamk/tbg/combat/SplashDamageMove.java index 5d3e5e2..99ddb8e 100644 --- a/src/main/java/com/vamk/tbg/combat/SplashDamageMove.java +++ b/src/main/java/com/vamk/tbg/combat/SplashDamageMove.java @@ -5,7 +5,6 @@ import com.vamk.tbg.game.MoveContext; import com.vamk.tbg.util.LogUtil; -import java.io.Serial; import java.util.logging.Logger; import static com.vamk.tbg.util.RandomUtil.chance; @@ -13,8 +12,6 @@ public class SplashDamageMove extends AbstractMove { private static final Logger LOGGER = LogUtil.getLogger(SplashDamageMove.class); private static final int BLEEDING_CHANCE = 50; - @Serial - private static final long serialVersionUID = 1791438698674539499L; public SplashDamageMove() { super("SPLASH_DAMAGE", true); diff --git a/src/main/java/com/vamk/tbg/effect/BleedingEffectHandler.java b/src/main/java/com/vamk/tbg/effect/BleedingEffectHandler.java index b20f9f2..f681a75 100644 --- a/src/main/java/com/vamk/tbg/effect/BleedingEffectHandler.java +++ b/src/main/java/com/vamk/tbg/effect/BleedingEffectHandler.java @@ -9,20 +9,18 @@ public class BleedingEffectHandler implements StatusEffectHandler { private static final Logger LOGGER = LogUtil.getLogger(BleedingEffectHandler.class); private final Random random; - private final Entity entity; - public BleedingEffectHandler(Entity entity) { + public BleedingEffectHandler() { this.random = new Random(); - this.entity = entity; } @Override - public void tick() { - if (!this.entity.hasEffect(StatusEffect.BLEEDING)) return; + public void applyTo(Entity entity) { + if (!entity.hasEffect(StatusEffect.BLEEDING)) return; // TODO make this configurable - int damage = this.random.nextInt(Math.max((int) (this.entity.getMaxHealth() * 0.05), 1)); - this.entity.damage(damage); - LOGGER.info("Entity %d loses %d health to bleeding".formatted(this.entity.getId(), damage)); + int damage = this.random.nextInt(Math.max((int) (entity.getMaxHealth() * 0.05), 1)); + entity.damage(damage); + LOGGER.info("Entity %d loses %d health to bleeding".formatted(entity.getId(), damage)); } } diff --git a/src/main/java/com/vamk/tbg/effect/RegenEffectHandler.java b/src/main/java/com/vamk/tbg/effect/RegenEffectHandler.java index 831fb7b..9f60680 100644 --- a/src/main/java/com/vamk/tbg/effect/RegenEffectHandler.java +++ b/src/main/java/com/vamk/tbg/effect/RegenEffectHandler.java @@ -9,20 +9,18 @@ public class RegenEffectHandler implements StatusEffectHandler { private static final Logger LOGGER = LogUtil.getLogger(RegenEffectHandler.class); private final Random random; - private final Entity entity; - public RegenEffectHandler(Entity entity) { + public RegenEffectHandler() { this.random = new Random(); - this.entity = entity; } @Override - public void tick() { - if (!this.entity.hasEffect(StatusEffect.REGENERATION)) return; + public void applyTo(Entity entity) { + if (!entity.hasEffect(StatusEffect.REGENERATION)) return; // TODO make this configurable - int hp = this.random.nextInt(Math.max((int) (this.entity.getMaxHealth() * 0.01), 1)); - this.entity.heal(hp); - LOGGER.info("Entity %d gains %d health thanks to regeneration".formatted(this.entity.getId(), hp)); + int hp = this.random.nextInt(Math.max((int) (entity.getMaxHealth() * 0.01), 1)); + entity.heal(hp); + LOGGER.info("Entity %d gains %d health thanks to regeneration".formatted(entity.getId(), hp)); } } diff --git a/src/main/java/com/vamk/tbg/effect/StatusEffectHandler.java b/src/main/java/com/vamk/tbg/effect/StatusEffectHandler.java index a0419e1..4aed1e8 100644 --- a/src/main/java/com/vamk/tbg/effect/StatusEffectHandler.java +++ b/src/main/java/com/vamk/tbg/effect/StatusEffectHandler.java @@ -1,5 +1,8 @@ package com.vamk.tbg.effect; -import com.vamk.tbg.util.Tickable; +import com.vamk.tbg.game.Entity; -public interface StatusEffectHandler extends Tickable {} +public interface StatusEffectHandler { + + void applyTo(Entity entity); +} diff --git a/src/main/java/com/vamk/tbg/game/Entity.java b/src/main/java/com/vamk/tbg/game/Entity.java index 5e83264..d5764af 100644 --- a/src/main/java/com/vamk/tbg/game/Entity.java +++ b/src/main/java/com/vamk/tbg/game/Entity.java @@ -2,10 +2,8 @@ import com.vamk.tbg.Constants; import com.vamk.tbg.combat.Move; -import com.vamk.tbg.effect.BleedingEffectHandler; -import com.vamk.tbg.effect.RegenEffectHandler; +import com.vamk.tbg.combat.CombatRegistry; import com.vamk.tbg.effect.StatusEffect; -import com.vamk.tbg.effect.StatusEffectHandler; import com.vamk.tbg.signal.SignalDispatcher; import com.vamk.tbg.signal.impl.EffectsUpdatedSignal; import com.vamk.tbg.signal.impl.EntityDeathSignal; @@ -13,8 +11,6 @@ import com.vamk.tbg.util.LogUtil; import com.vamk.tbg.util.Tickable; -import java.io.Serial; -import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -24,31 +20,27 @@ import java.util.logging.Logger; import java.util.stream.Collectors; -public class Entity implements Serializable, Tickable { - @Serial - private static final long serialVersionUID = 6101117327941388691L; +public class Entity implements Tickable { private final Map activeEffects; - private final transient Set effectHandlers; private final int id; private final boolean hostile; private final int maxHealth; private int health; private final List moves; - private final transient SignalDispatcher dispatcher; + private final SignalDispatcher dispatcher; - public Entity(int id, boolean hostile, int maxHealth, List moves, SignalDispatcher dispatcher) { + public Entity(int id, boolean hostile, int health, int maxHealth, List moves, SignalDispatcher dispatcher) { this.id = id; this.hostile = hostile; + this.health = health; this.maxHealth = maxHealth; - this.health = maxHealth; this.moves = moves; this.dispatcher = dispatcher; - this.activeEffects = new HashMap<>(); - this.effectHandlers = Set.of( - new BleedingEffectHandler(this), - new RegenEffectHandler(this) - ); + } + + public Entity(int id, boolean hostile, int maxHealth, List moves, SignalDispatcher dispatcher) { + this(id, hostile, maxHealth, maxHealth, moves, dispatcher); } public int getId() { @@ -143,9 +135,13 @@ public void cure() { this.dispatcher.dispatch(new EffectsUpdatedSignal(this)); } + public EntitySnapshot createSnapshot() { + List moves = this.moves.stream().map(Move::getId).toList(); + return new EntitySnapshot(this.id, this.hostile, this.health, this.maxHealth, moves); + } + @Override public void tick() { - this.effectHandlers.forEach(Tickable::tick); Set expired = new HashSet<>(); for (Map.Entry entry : this.activeEffects.entrySet()) { int rounds = entry.getValue() - 1; @@ -183,10 +179,12 @@ public int hashCode() { static final class Factory { private static final Logger LOGGER = LogUtil.getLogger(Factory.class); private final SignalDispatcher dispatcher; + private final CombatRegistry combatRegistry; private final AtomicInteger nextId; Factory(SignalDispatcher dispatcher) { this.dispatcher = dispatcher; + this.combatRegistry = new CombatRegistry(); this.nextId = new AtomicInteger(0); } @@ -195,5 +193,14 @@ Entity create(boolean hostile, int maxHeath, List moves) { LOGGER.info("Created entity %s".formatted(entity)); return entity; } + + Entity create(EntitySnapshot snapshot) { + List moves = snapshot.moves().stream() + .map(this.combatRegistry::findMove) + .toList(); + Entity entity = new Entity(snapshot.id(), snapshot.hostile(), snapshot.health(), snapshot.maxHealth(), moves, this.dispatcher); + LOGGER.info("Restored entity %s".formatted(entity)); + return entity; + } } } diff --git a/src/main/java/com/vamk/tbg/game/EntitySnapshot.java b/src/main/java/com/vamk/tbg/game/EntitySnapshot.java new file mode 100644 index 0000000..185f290 --- /dev/null +++ b/src/main/java/com/vamk/tbg/game/EntitySnapshot.java @@ -0,0 +1,10 @@ +package com.vamk.tbg.game; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +public record EntitySnapshot (int id, boolean hostile, int health, int maxHealth, List moves) implements Serializable { + @Serial + private static final long serialVersionUID = 1L; +} diff --git a/src/main/java/com/vamk/tbg/game/Game.java b/src/main/java/com/vamk/tbg/game/Game.java index a171e63..218bbe3 100644 --- a/src/main/java/com/vamk/tbg/game/Game.java +++ b/src/main/java/com/vamk/tbg/game/Game.java @@ -1,11 +1,15 @@ package com.vamk.tbg.game; import com.vamk.tbg.combat.BuffMove; +import com.vamk.tbg.combat.CombatRegistry; import com.vamk.tbg.combat.DebuffMove; import com.vamk.tbg.combat.GenericAttackMove; import com.vamk.tbg.combat.HealAllMove; import com.vamk.tbg.combat.Move; +import com.vamk.tbg.effect.BleedingEffectHandler; +import com.vamk.tbg.effect.RegenEffectHandler; import com.vamk.tbg.effect.StatusEffect; +import com.vamk.tbg.effect.StatusEffectHandler; import com.vamk.tbg.signal.SignalDispatcher; import com.vamk.tbg.signal.impl.EntityDeathSignal; import com.vamk.tbg.signal.impl.EntityPlaysSignal; @@ -18,6 +22,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.logging.Logger; public class Game { @@ -25,12 +30,15 @@ public class Game { private final SignalDispatcher dispatcher; private final Entity.Factory entityFactory; private final List entities; + private final Set effectHandlers; private Cursor cursor; + private boolean importedState = false; public Game(SignalDispatcher dispatcher) { this.dispatcher = dispatcher; this.entityFactory = new Entity.Factory(dispatcher); this.entities = new ArrayList<>(); + this.effectHandlers = Set.of(new BleedingEffectHandler(), new RegenEffectHandler()); } public void launch() { @@ -39,26 +47,51 @@ public void launch() { LOGGER.info("Shutting down, thank you :)"); } + public boolean isFinished() { + int hostiles = (int) this.entities.stream().filter(Entity::isHostile).count(); + return !(hostiles > 0 && this.entities.size() - hostiles > 0); + } + + public GameState exportState() { + List entities = this.entities.stream().map(Entity::createSnapshot).toList(); + return new GameState(entities, this.cursor.getInternalCursor()); + } + + public void importState(GameState state) { + LOGGER.info("Restoring previous game state..."); + List entities = state.getEntities().stream().map(this.entityFactory::create).toList(); + this.entities.addAll(entities); + this.cursor = new Cursor<>(this.entities, state.getCursor()); + this.importedState = true; + } + private void prepare() { - LOGGER.info("Preparing game, spawning entities..."); this.dispatcher.subscribe(EntityDeathSignal.class, this::onEntityDeath); - // TODO read moves from config (entity presets?) - List moves = List.of( - new BuffMove(), - new HealAllMove(), - new DebuffMove(), - new GenericAttackMove() - ); - - // TODO read i from config - // TODO read maxHealth from config - for (int i = 0; i < 3; i++) { - this.entities.add(this.entityFactory.create(false, 1000, moves)); - this.entities.add(this.entityFactory.create(true, 1000, moves)); + /* + * If a previously exported game state was restored, we don't + * need to ge through this setup process. + */ + if (!this.importedState) { + LOGGER.info("Preparing game, spawning entities..."); + // TODO read moves from config (entity presets?) + List moves = List.of( + new BuffMove(), + new HealAllMove(), + new DebuffMove(), + new GenericAttackMove() + ); + + // TODO read i from config + // TODO read maxHealth from config + for (int i = 0; i < 3; i++) { + this.entities.add(this.entityFactory.create(false, 1000, moves)); + this.entities.add(this.entityFactory.create(true, 1000, moves)); + } + + RandomUtil.randomize(this.entities); + this.cursor = new Cursor<>(this.entities); } - RandomUtil.randomize(this.entities); - this.cursor = new Cursor<>(this.entities); this.dispatcher.dispatch(new GameReadySignal(this.entities)); LOGGER.info("Done!"); } @@ -83,6 +116,7 @@ private void play(Entity entity) { * skipping their round. */ entity.tick(); + this.effectHandlers.forEach(x -> x.applyTo(entity)); // FROZEN rids the entity from this round if (!entity.hasEffect(StatusEffect.FROZEN)) { Move move; @@ -116,13 +150,4 @@ private void play(Entity entity) { // CAFFEINATED grants another turn if (entity.hasEffect(StatusEffect.CAFFEINATED)) play(entity); } - - public boolean isFinished() { - int hostiles = (int) this.entities.stream().filter(Entity::isHostile).count(); - return !(hostiles > 0 && this.entities.size() - hostiles > 0); - } - - public GameState exportState() { - return new GameState(this.entities, this.cursor.getInternalCursor()); - } } diff --git a/src/main/java/com/vamk/tbg/game/GameState.java b/src/main/java/com/vamk/tbg/game/GameState.java index bced04a..0851d32 100644 --- a/src/main/java/com/vamk/tbg/game/GameState.java +++ b/src/main/java/com/vamk/tbg/game/GameState.java @@ -8,15 +8,15 @@ public class GameState implements Serializable { public static final String FILEPATH = "gamestate.dat"; @Serial private static final long serialVersionUID = -7970394955414240184L; - private final List entities; + private final List entities; private final int cursor; - public GameState(List entities, int cursor) { + public GameState(List entities, int cursor) { this.entities = entities; this.cursor = cursor; } - public List getEntities() { + public List getEntities() { return this.entities; } diff --git a/src/main/java/com/vamk/tbg/util/IOUtil.java b/src/main/java/com/vamk/tbg/util/IOUtil.java index dc787a8..71c2a87 100644 --- a/src/main/java/com/vamk/tbg/util/IOUtil.java +++ b/src/main/java/com/vamk/tbg/util/IOUtil.java @@ -6,6 +6,9 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; public final class IOUtil { @@ -25,4 +28,14 @@ public static O readObject(Class type, String path) return type.cast(result); } } + + public static boolean fileExists(String path) { + Path file = Paths.get(path); + return Files.exists(file); + } + + public static void remove(String path) throws IOException { + Path file = Paths.get(path); + Files.deleteIfExists(file); + } }