diff --git a/src/client/java/minicraft/entity/ExplosionTileTicker.java b/src/client/java/minicraft/entity/ExplosionTileTicker.java new file mode 100644 index 000000000..5331a82f4 --- /dev/null +++ b/src/client/java/minicraft/entity/ExplosionTileTicker.java @@ -0,0 +1,56 @@ +package minicraft.entity; + +import minicraft.gfx.Screen; +import minicraft.level.Level; +import minicraft.level.tile.ExplodedTile; +import minicraft.level.tile.Tile; +import minicraft.level.tile.Tiles; + +// This is a kind of tile entity. Maybe this should be savable. +public class ExplosionTileTicker extends Entity { + private static final int EXPLOSION_TIME = 18; // 18 ticks == 0.3 second + + private final Level level; + private final int x, y, r; + + private int tick = 0; + + public ExplosionTileTicker(Level level, int x, int y, int r) { + super(0, 0); + this.level = level; + this.x = x; + this.y = y; + this.r = r; + level.setAreaTiles(x, y, r, Tiles.get("explode"), 0, ExplosionTileTicker::explodeBlacklistCheck); + } + + public static void addTicker(Level level, int x, int y, int r) { + level.add(new ExplosionTileTicker(level, x, y, r), x * 16 + 8, y * 16 + 8); + } + + private static boolean explodeBlacklistCheck(Tile tile, int x, int y) { + return !Tiles.explosionBlacklist.contains(tile.id); + } + + private static boolean explodedTileCheck(Tile tile, int x, int y) { + return tile instanceof ExplodedTile; + } + + @Override + public void render(Screen screen) {} + + @Override + public void tick() { + if (tick == EXPLOSION_TIME) { // Does the explosion + if (level.depth != 1) { + level.setAreaTiles(x, y, r, Tiles.get("hole"), 0, ExplosionTileTicker::explodedTileCheck); + } else { + level.setAreaTiles(x, y, r, Tiles.get("Infinite Fall"), 0, ExplosionTileTicker::explodedTileCheck); + } + + remove(); + } + + tick++; + } +} diff --git a/src/client/java/minicraft/entity/furniture/Tnt.java b/src/client/java/minicraft/entity/furniture/Tnt.java index 1cee58557..de02d17c7 100644 --- a/src/client/java/minicraft/entity/furniture/Tnt.java +++ b/src/client/java/minicraft/entity/furniture/Tnt.java @@ -3,6 +3,7 @@ import minicraft.core.io.Sound; import minicraft.entity.Direction; import minicraft.entity.Entity; +import minicraft.entity.ExplosionTileTicker; import minicraft.entity.mob.Mob; import minicraft.entity.mob.Player; import minicraft.gfx.Color; @@ -23,17 +24,13 @@ import java.awt.event.ActionListener; import java.util.List; -public class Tnt extends Furniture implements ActionListener { +public class Tnt extends Furniture { private static int FUSE_TIME = 90; private static int BLAST_RADIUS = 32; private static int BLAST_DAMAGE = 75; private int ftik = 0; private boolean fuseLit = false; - private Timer explodeTimer; - private Level levelSave; - - private final String[] explosionBlacklist = new String[] { "hard rock", "obsidian wall", "stairs up", "stairs down" }; /** * Creates a new tnt furniture. @@ -42,8 +39,6 @@ public Tnt() { super("Tnt", new LinkedSprite(SpriteType.Entity, "tnt"), new LinkedSprite(SpriteType.Item, "tnt"), 3, 2); fuseLit = false; ftik = 0; - - explodeTimer = new Timer(300, this); } @Override @@ -88,11 +83,7 @@ public void tick() { AchievementsDisplay.setAchievement("minicraft.achievement.demolition", true); Sound.play("explode"); - - level.setAreaTiles(xt, yt, 1, Tiles.get("explode"), 0, explosionBlacklist); - - levelSave = level; - explodeTimer.start(); + ExplosionTileTicker.addTicker(level, xt, yt, 1); super.remove(); } } @@ -107,23 +98,6 @@ public void render(Screen screen) { super.render(screen); } - /** - * Does the explosion. - */ - public void actionPerformed(ActionEvent e) { - explodeTimer.stop(); - int xt = x >> 4; - int yt = (y - 2) >> 4; - - if (levelSave.depth != 1) { - levelSave.setAreaTiles(xt, yt, 1, Tiles.get("hole"), 0, explosionBlacklist); - } else { - levelSave.setAreaTiles(xt, yt, 1, Tiles.get("Infinite Fall"), 0, explosionBlacklist); - } - - levelSave = null; - } - @Override public boolean interact(Player player, Item heldItem, Direction attackDir) { if (heldItem instanceof PowerGloveItem) { diff --git a/src/client/java/minicraft/entity/mob/Creeper.java b/src/client/java/minicraft/entity/mob/Creeper.java index 4b9d7138c..94860cc37 100644 --- a/src/client/java/minicraft/entity/mob/Creeper.java +++ b/src/client/java/minicraft/entity/mob/Creeper.java @@ -5,6 +5,7 @@ import minicraft.core.io.Sound; import minicraft.entity.Direction; import minicraft.entity.Entity; +import minicraft.entity.ExplosionTileTicker; import minicraft.entity.furniture.Spawner; import minicraft.gfx.Point; import minicraft.gfx.Screen; @@ -30,8 +31,6 @@ public class Creeper extends EnemyMob { private int fuseTime = 0; private boolean fuseLit = false; - private final String[] explosionBlacklist = new String[] { "hard rock", "obsidian wall", "raw obsidian" }; - public Creeper(int lvl) { super(lvl, sprites, 10, 50); } @@ -120,12 +119,7 @@ public void tick() { } } if (!hasSpawner) { - if (level.depth != 1) { - level.setAreaTiles(tilePosition.x, tilePosition.y, 0, Tiles.get("hole"), 0, explosionBlacklist); - } else { - level.setAreaTiles(tilePosition.x, tilePosition.y, 0, Tiles.get("Infinite Fall"), 0, explosionBlacklist); - } - + ExplosionTileTicker.addTicker(level, tilePosition.x, tilePosition.y, 0); } } diff --git a/src/client/java/minicraft/level/Level.java b/src/client/java/minicraft/level/Level.java index 3009b1888..f466a1318 100644 --- a/src/client/java/minicraft/level/Level.java +++ b/src/client/java/minicraft/level/Level.java @@ -908,10 +908,10 @@ public void setAreaTiles(int xt, int yt, int r, Tile tile, int data, boolean ove } } - public void setAreaTiles(int xt, int yt, int r, Tile tile, int data, String[] blacklist) { + public void setAreaTiles(int xt, int yt, int r, Tile tile, int data, TileCheck condition) { for (int y = yt - r; y <= yt + r; y++) { for (int x = xt - r; x <= xt + r; x++) { - if (!Arrays.asList(blacklist).contains(getTile(x, y).name.toLowerCase())) + if (condition.check(getTile(x, y), x, y)) setTile(x, y, tile, data); } } diff --git a/src/client/java/minicraft/level/tile/Tiles.java b/src/client/java/minicraft/level/tile/Tiles.java index 7380454a6..d9695a044 100644 --- a/src/client/java/minicraft/level/tile/Tiles.java +++ b/src/client/java/minicraft/level/tile/Tiles.java @@ -11,7 +11,11 @@ import minicraft.util.Logging; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; public final class Tiles { /// Idea: to save tile names while saving space, I could encode the names in base 64 in the save file...^M @@ -21,6 +25,10 @@ public final class Tiles { private static HashMap tiles = new HashMap<>(); + // Standard tile explosion blacklist + // Tiles (as IDs) included cannot be damaged by explosions such as by TNTs and creepers. + public static final Set explosionBlacklist; + public static void initTileList() { Logging.TILES.debug("Initializing tile list..."); @@ -193,6 +201,20 @@ static void add(int id, Tile tile) { oldids.set(53, "torch green wool"); oldids.set(54, "torch yellow wool"); oldids.set(55, "torch black wool"); + + explosionBlacklist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( + (short) 4, // Stairs Up + (short) 5, // Stairs Down + (short) 22, // Hard Rock + (short) 28, // Obsidian Door + (short) 31, // Obsidian + (short) 34, // Obsidian Wall + (short) 44, // Raw Obsidian + (short) 46, // Ornate Obsidian + (short) 47, // Boss Wall + (short) 48, // Boss Floor + (short) 49 // Boss Door + ))); } private static int overflowCheck = 0;