From b26fada91d46e60d2cefd76f82e7deebd862241f Mon Sep 17 00:00:00 2001 From: Zukero Date: Fri, 21 Sep 2018 19:38:24 +0200 Subject: [PATCH] Fixed "restart for locale" bugs. Fixed missing parsing of the colorfilter map properties. --- .../AndorsTrail/AndorsTrailApplication.java | 27 +- .../StartScreenActivity_MainMenu.java | 14 +- .../AndorsTrail/model/map/PredefinedMap.java | 788 +++++++++--------- .../model/map/TMXMapTranslator.java | 5 +- .../AndorsTrail/resource/tiles/TileCache.java | 248 +++--- .../src/com/gpl/rpg/AndorsTrail/util/L.java | 30 +- 6 files changed, 568 insertions(+), 544 deletions(-) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java index d6203d460..2cf7f9ce0 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java @@ -3,12 +3,13 @@ package com.gpl.rpg.AndorsTrail; import java.io.File; import java.io.IOException; import java.util.Locale; - +import android.annotation.SuppressLint; import android.app.Activity; import android.app.Application; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.os.Build; import android.os.Environment; import android.view.Window; import android.view.WindowManager; @@ -16,6 +17,7 @@ import android.view.WindowManager; import com.gpl.rpg.AndorsTrail.context.ControllerContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.controller.Constants; +import com.gpl.rpg.AndorsTrail.util.L; public final class AndorsTrailApplication extends Application { @@ -32,9 +34,9 @@ public final class AndorsTrailApplication extends Application { public static final boolean IS_RELEASE_VERSION = !CURRENT_VERSION_DISPLAY.matches(".*[a-d].*"); private final AndorsTrailPreferences preferences = new AndorsTrailPreferences(); - private final WorldContext world = new WorldContext(); - private final ControllerContext controllers = new ControllerContext(this, world); - private final WorldSetup setup = new WorldSetup(world, controllers, this); + private WorldContext world = new WorldContext(); + private ControllerContext controllers = new ControllerContext(this, world); + private WorldSetup setup = new WorldSetup(world, controllers, this); public WorldContext getWorld() { return world; } public WorldSetup getWorldSetup() { return setup; } public AndorsTrailPreferences getPreferences() { return preferences; } @@ -62,15 +64,23 @@ public final class AndorsTrailApplication extends Application { setLocale(activity); } + //Get default locale at startup, as somehow it seems that changing the app's + //configured locale impacts the value returned by Locale.getDefault() nowadays. + private final Locale defaultLocale = Locale.getDefault(); + + @SuppressLint("NewApi") public boolean setLocale(Activity context) { Resources res = context.getResources(); Configuration conf = res.getConfiguration(); - final Locale targetLocale = preferences.useLocalizedResources ? Locale.getDefault() : Locale.US; - if (targetLocale.equals(conf.locale)) return false; + final Locale targetLocale = preferences.useLocalizedResources ? defaultLocale : Locale.US; + if (targetLocale.equals(conf.locale)) { + return false; + } conf.locale = targetLocale; res.updateConfiguration(conf, res.getDisplayMetrics()); this.getResources().updateConfiguration(conf, res.getDisplayMetrics()); + return true; } @@ -127,4 +137,9 @@ public final class AndorsTrailApplication extends Application { } return false; } + public void discardWorld() { + world = new WorldContext(); + controllers = new ControllerContext(this, world); + setup = new WorldSetup(world, controllers, getApplicationContext()); + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/StartScreenActivity_MainMenu.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/StartScreenActivity_MainMenu.java index 56bfeeadf..954301187 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/StartScreenActivity_MainMenu.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/StartScreenActivity_MainMenu.java @@ -1,10 +1,12 @@ package com.gpl.rpg.AndorsTrail.activity.fragment; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; +import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; @@ -28,6 +30,7 @@ import com.gpl.rpg.AndorsTrail.controller.Constants; import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager; import com.gpl.rpg.AndorsTrail.savegames.Savegames; import com.gpl.rpg.AndorsTrail.savegames.Savegames.FileHeader; +import com.gpl.rpg.AndorsTrail.util.L; import com.gpl.rpg.AndorsTrail.util.ThemeHelper; import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory; @@ -259,18 +262,25 @@ public class StartScreenActivity_MainMenu extends Fragment { // Changing the locale after having loaded the game requires resources to // be re-loaded. Therefore, we just exit here. Toast.makeText(getActivity(), R.string.change_locale_requires_restart, Toast.LENGTH_LONG).show(); - getActivity().finish(); + doFinish(); return; } } if (ThemeHelper.changeTheme(preferences.selectedTheme)) { // Changing the theme requires a restart to re-create all activities. Toast.makeText(getActivity(), R.string.change_theme_requires_restart, Toast.LENGTH_LONG).show(); - getActivity().finish(); + doFinish(); return; } app.getWorld().tileManager.updatePreferences(preferences); } + + @SuppressLint("NewApi") + private void doFinish() { + //For Lollipop and above + ((AndorsTrailApplication)getActivity().getApplication()).discardWorld(); + getActivity().finish(); + } public interface OnNewGameRequestedListener { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java index 4502a2999..b13269174 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java @@ -1,397 +1,391 @@ -package com.gpl.rpg.AndorsTrail.model.map; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; -import com.gpl.rpg.AndorsTrail.context.ControllerContext; -import com.gpl.rpg.AndorsTrail.context.WorldContext; -import com.gpl.rpg.AndorsTrail.controller.Constants; -import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.BloodSplatter; -import com.gpl.rpg.AndorsTrail.model.actor.Monster; -import com.gpl.rpg.AndorsTrail.model.item.ItemType; -import com.gpl.rpg.AndorsTrail.model.item.Loot; -import com.gpl.rpg.AndorsTrail.model.map.MapObject.MapObjectType; -import com.gpl.rpg.AndorsTrail.util.Coord; -import com.gpl.rpg.AndorsTrail.util.CoordRect; -import com.gpl.rpg.AndorsTrail.util.L; -import com.gpl.rpg.AndorsTrail.util.Size; - -public final class PredefinedMap { - private static final long VISIT_RESET = 0; - - public final int xmlResourceId; - public final String name; - public final Size size; - public final MapObject[] eventObjects; - public final MonsterSpawnArea[] spawnAreas; - public final List initiallyActiveMapObjectGroups; - public final List activeMapObjectGroups; - public final ArrayList groundBags = new ArrayList(); - public boolean visited = false; - public long lastVisitTime = VISIT_RESET; - public String lastSeenLayoutHash = ""; - public final boolean isOutdoors; - public String currentColorFilter = null; - - public final ArrayList splatters = new ArrayList(); - - public PredefinedMap( - int xmlResourceId - , String name - , Size size - , MapObject[] eventObjects - , MonsterSpawnArea[] spawnAreas - , List initiallyActiveMapObjectGroups - , boolean isOutdoors - ) { - this.xmlResourceId = xmlResourceId; - this.name = name; - this.size = size; - this.eventObjects = eventObjects; - this.spawnAreas = spawnAreas; - this.initiallyActiveMapObjectGroups = initiallyActiveMapObjectGroups; - this.activeMapObjectGroups = new LinkedList(); - this.activeMapObjectGroups.addAll(this.initiallyActiveMapObjectGroups); - activateMapObjects(); - assert(size.width > 0); - assert(size.height > 0); - this.isOutdoors = isOutdoors; - } - - public final boolean isOutside(final Coord p) { return isOutside(p.x, p.y); } - public final boolean isOutside(final int x, final int y) { - if (x < 0) return true; - if (y < 0) return true; - if (x >= size.width) return true; - if (y >= size.height) return true; - return false; - } - public final boolean isOutside(final CoordRect area) { - if (isOutside(area.topLeft)) return true; - if (area.topLeft.x + area.size.width > size.width) return true; - if (area.topLeft.y + area.size.height > size.height) return true; - return false; - } - public boolean intersects(CoordRect area) { - return new CoordRect(new Coord(0,0), size).intersects(area); - } - - public MapObject findEventObject(MapObject.MapObjectType objectType, String name) { - for (MapObject o : eventObjects) { - if (o.type != objectType) continue; - if (!name.equals(o.id)) continue; - return o; - } - return null; - } - public List getActiveEventObjectsAt(final Coord p) { - List result = null; - for (MapObject o : eventObjects) { - if (!o.isActive) continue; - if (!o.position.contains(p)) continue; - //if (!activeMapObjectGroups.contains(o.group)) continue; - if (result == null) result = new ArrayList(); - result.add(o); - } - return result; - } - public boolean hasContainerAt(final Coord p) { - for (MapObject o : eventObjects) { - if (!o.isActive) continue; - if (o.type != MapObject.MapObjectType.container) continue; - if (!o.position.contains(p)) continue; - return true; - } - return false; - } - public Monster getMonsterAt(final CoordRect p) { - return getMonsterAt(p, null); - } - public Monster getMonsterAt(final CoordRect p, Monster exceptMe) { - for (MonsterSpawnArea a : spawnAreas) { - Monster m = a.getMonsterAt(p); - if (m != null && (exceptMe == null || exceptMe != m)) return m; - } - return null; - } - public Monster getMonsterAt(final Coord p) { return getMonsterAt(p.x, p.y); } - public Monster getMonsterAt(final int x, final int y) { - for (MonsterSpawnArea a : spawnAreas) { - Monster m = a.getMonsterAt(x, y); - if (m != null) return m; - } - return null; - } - - public Monster findSpawnedMonster(final String monsterTypeID) { - for (MonsterSpawnArea a : spawnAreas) { - Monster m = a.findSpawnedMonster(monsterTypeID); - if (m != null) return m; - } - return null; - } - - public Loot getBagAt(final Coord p) { - for (Loot l : groundBags) { - if (l.position.equals(p)) return l; - } - return null; - } - public Loot getBagOrCreateAt(final Coord position) { - Loot b = getBagAt(position); - if (b != null) return b; - boolean isContainer = hasContainerAt(position); - b = new Loot(!isContainer); - b.position.set(position); - if (isOutside(position)) { - if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - L.log("WARNING: trying to place bag outside map. Map is " + size.toString() + ", bag tried to place at " + position.toString()); - } - return b; - } - groundBags.add(b); - return b; - } - public void itemDropped(ItemType itemType, int quantity, Coord position) { - Loot l = getBagOrCreateAt(position); - l.items.addItem(itemType, quantity); - } - public void removeGroundLoot(Loot loot) { - groundBags.remove(loot); - } - public void resetForNewGame() { - for (MonsterSpawnArea a : spawnAreas) { - a.resetForNewGame(); - } - activeMapObjectGroups.clear(); - activeMapObjectGroups.addAll(initiallyActiveMapObjectGroups); - activateMapObjects(); - resetTemporaryData(); - groundBags.clear(); - visited = false; - currentColorFilter = null; - lastSeenLayoutHash = ""; - } - - public boolean isRecentlyVisited() { - if (lastVisitTime == VISIT_RESET) return false; - return (System.currentTimeMillis() - lastVisitTime) < Constants.MAP_UNVISITED_RESPAWN_DURATION_MS; - } - public void updateLastVisitTime() { - lastVisitTime = System.currentTimeMillis(); - } - public void resetTemporaryData() { - for(MonsterSpawnArea a : spawnAreas) { - if (a.isUnique) a.resetShops(); - else a.removeAllMonsters(); - } - splatters.clear(); - lastVisitTime = VISIT_RESET; - } - public boolean hasResetTemporaryData() { - return lastVisitTime == VISIT_RESET; - } - - public void createAllContainerLoot() { - for (MapObject o : eventObjects) { - if (!o.isActive) continue; - if (o.type != MapObject.MapObjectType.container) continue; - createContainerLoot(o); - } - } - - public void createContainerLoot(MapObject container) { - Loot bag = getBagOrCreateAt(container.position.topLeft); - container.dropList.createRandomLoot(bag, null); - } - - - private void activateMapObjects() { - if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) { - L.log("Applying active status to all map objects in map "+name); - } - for (MapObject o : eventObjects) { - o.isActive = activeMapObjectGroups.contains(o.group); - } - } - - public void activateMapObjectGroup(String group) { - if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) { - L.log("Applying active status to object group "+group+" in map "+name); - } - if (!activeMapObjectGroups.contains(group)) { - activeMapObjectGroups.add(group); - for (MapObject o : eventObjects) { - if (o.group.equals(group)) { - o.isActive = true; - if (o.type == MapObjectType.container) createContainerLoot(o); - } - } - } - } - - public void deactivateMapObjectGroup(String group) { - if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) { - L.log("Removing active status to object group "+group+" in map"+name); - } - if (activeMapObjectGroups.contains(group)) { - activeMapObjectGroups.remove(group); - for (MapObject o : eventObjects) { - if (o.group.equals(group)) { - o.isActive = false; - } - } - } - } - - - // ====== PARCELABLE =================================================================== - - public void readFromParcel(DataInputStream src, WorldContext world, ControllerContext controllers, int fileversion) throws IOException { - boolean shouldLoadMapData = true; - if (fileversion >= 37) shouldLoadMapData = src.readBoolean(); - - int loadedSpawnAreas = 0; - if (shouldLoadMapData) { - loadedSpawnAreas = src.readInt(); - for(int i = 0; i < loadedSpawnAreas; ++i) { - if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - if (i >= this.spawnAreas.length) { - L.log("WARNING: Trying to load monsters from savegame in map " + this.name + " for spawn #" + i + ". This will totally fail."); - } - } - if(fileversion >= 43) { - //Spawn areas now have unique IDs. Need to check as maps can change. - String id = src.readUTF(); - int j = i; - boolean found = false; - do { - if (this.spawnAreas[j].areaID.equals(id)) { - this.spawnAreas[j].readFromParcel(src, world, fileversion); - found = true; - break; - } - j = (j+1)%spawnAreas.length; - } while (j != i); - if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - if (!found) { - L.log("WARNING: Trying to load monsters from savegame in map " + this.name + " for spawn #" + id + " but this area cannot be found. This will totally fail."); - } - } - } else { - this.spawnAreas[i].readFromParcel(src, world, fileversion); - } - } - - activeMapObjectGroups.clear(); - if(fileversion >= 43) { - int activeListLength = src.readInt(); - for (int i = 0; i < activeListLength; i++) { - String activeGroupID = src.readUTF(); - activeMapObjectGroups.add(activeGroupID); - } - } else { - activeMapObjectGroups.addAll(initiallyActiveMapObjectGroups); - } - activateMapObjects(); - - groundBags.clear(); - if (fileversion <= 5) return; - - final int size2 = src.readInt(); - for(int i = 0; i < size2; ++i) { - groundBags.add(new Loot(src, world, fileversion)); - } - - if (fileversion <= 11) return; - - if (fileversion < 37) visited = src.readBoolean(); - - if (fileversion <= 15) { - if (visited) { - lastVisitTime = System.currentTimeMillis(); - createAllContainerLoot(); - } - return; - } - - if (fileversion >= 43) { - if (src.readBoolean()) { - currentColorFilter = src.readUTF(); - } else { - currentColorFilter = null; - } - } - - lastVisitTime = src.readLong(); - - if (visited) { - if (fileversion > 30 && fileversion < 36) { - /*int lastVisitVersion = */src.readInt(); - } - } - } else { - activeMapObjectGroups.clear(); - activeMapObjectGroups.addAll(initiallyActiveMapObjectGroups); - activateMapObjects(); - } - if (fileversion >= 37) { - if (fileversion < 41) visited = true; - else visited = src.readBoolean(); - } - - if (fileversion < 36) lastSeenLayoutHash = ""; - else lastSeenLayoutHash = src.readUTF(); - - for(int i = loadedSpawnAreas; i < spawnAreas.length; ++i) { - MonsterSpawnArea area = this.spawnAreas[i]; - if (area.isUnique && visited) controllers.monsterSpawnController.spawnAllInArea(this, null, area, true); - else area.resetForNewGame(); - } - } - - public boolean shouldSaveMapData(WorldContext world) { - if (!hasResetTemporaryData()) return true; - if (this == world.model.currentMap) return true; - if (!groundBags.isEmpty()) return true; - for (MonsterSpawnArea a : spawnAreas) { - if (this.visited && a.isUnique) return true; - if (a.isSpawning != a.isSpawningForNewGame) return true; - } - if (!activeMapObjectGroups.containsAll(initiallyActiveMapObjectGroups) - || !initiallyActiveMapObjectGroups.containsAll(activeMapObjectGroups)) return true; - if (currentColorFilter != null) return true; - return false; - } - - public void writeToParcel(DataOutputStream dest, WorldContext world) throws IOException { - if (shouldSaveMapData(world)) { - dest.writeBoolean(true); - dest.writeInt(spawnAreas.length); - for(MonsterSpawnArea a : spawnAreas) { - dest.writeUTF(a.areaID); - a.writeToParcel(dest); - } - dest.writeInt(activeMapObjectGroups.size()); - for(String s : activeMapObjectGroups) { - dest.writeUTF(s); - } - dest.writeInt(groundBags.size()); - for(Loot l : groundBags) { - l.writeToParcel(dest); - } - dest.writeBoolean(currentColorFilter != null); - if (currentColorFilter != null) dest.writeUTF(currentColorFilter); - dest.writeLong(lastVisitTime); - } else { - dest.writeBoolean(false); - } - dest.writeBoolean(visited); - dest.writeUTF(lastSeenLayoutHash); - } -} +package com.gpl.rpg.AndorsTrail.model.map; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; +import com.gpl.rpg.AndorsTrail.context.ControllerContext; +import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.controller.Constants; +import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.BloodSplatter; +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.model.item.ItemType; +import com.gpl.rpg.AndorsTrail.model.item.Loot; +import com.gpl.rpg.AndorsTrail.model.map.MapObject.MapObjectType; +import com.gpl.rpg.AndorsTrail.util.Coord; +import com.gpl.rpg.AndorsTrail.util.CoordRect; +import com.gpl.rpg.AndorsTrail.util.L; +import com.gpl.rpg.AndorsTrail.util.Size; + +public final class PredefinedMap { + private static final long VISIT_RESET = 0; + + public final int xmlResourceId; + public final String name; + public final Size size; + public final MapObject[] eventObjects; + public final MonsterSpawnArea[] spawnAreas; + public final List initiallyActiveMapObjectGroups; + public final List activeMapObjectGroups; + public final ArrayList groundBags = new ArrayList(); + public final String initialColorFilter; + public boolean visited = false; + public long lastVisitTime = VISIT_RESET; + public String lastSeenLayoutHash = ""; + public final boolean isOutdoors; + public String currentColorFilter = null; + + public final ArrayList splatters = new ArrayList(); + + public PredefinedMap( + int xmlResourceId + , String name + , Size size + , MapObject[] eventObjects + , MonsterSpawnArea[] spawnAreas + , List initiallyActiveMapObjectGroups + , boolean isOutdoors + , String colorFilter + ) { + this.xmlResourceId = xmlResourceId; + this.name = name; + this.size = size; + this.eventObjects = eventObjects; + this.spawnAreas = spawnAreas; + this.initiallyActiveMapObjectGroups = initiallyActiveMapObjectGroups; + this.activeMapObjectGroups = new LinkedList(); + this.activeMapObjectGroups.addAll(this.initiallyActiveMapObjectGroups); + activateMapObjects(); + assert(size.width > 0); + assert(size.height > 0); + this.isOutdoors = isOutdoors; + this.initialColorFilter = colorFilter; + } + + public final boolean isOutside(final Coord p) { return isOutside(p.x, p.y); } + public final boolean isOutside(final int x, final int y) { + if (x < 0) return true; + if (y < 0) return true; + if (x >= size.width) return true; + if (y >= size.height) return true; + return false; + } + public final boolean isOutside(final CoordRect area) { + if (isOutside(area.topLeft)) return true; + if (area.topLeft.x + area.size.width > size.width) return true; + if (area.topLeft.y + area.size.height > size.height) return true; + return false; + } + public boolean intersects(CoordRect area) { + return new CoordRect(new Coord(0,0), size).intersects(area); + } + + public MapObject findEventObject(MapObject.MapObjectType objectType, String name) { + for (MapObject o : eventObjects) { + if (o.type != objectType) continue; + if (!name.equals(o.id)) continue; + return o; + } + return null; + } + public List getActiveEventObjectsAt(final Coord p) { + List result = null; + for (MapObject o : eventObjects) { + if (!o.isActive) continue; + if (!o.position.contains(p)) continue; + //if (!activeMapObjectGroups.contains(o.group)) continue; + if (result == null) result = new ArrayList(); + result.add(o); + } + return result; + } + public boolean hasContainerAt(final Coord p) { + for (MapObject o : eventObjects) { + if (!o.isActive) continue; + if (o.type != MapObject.MapObjectType.container) continue; + if (!o.position.contains(p)) continue; + return true; + } + return false; + } + public Monster getMonsterAt(final CoordRect p) { + return getMonsterAt(p, null); + } + public Monster getMonsterAt(final CoordRect p, Monster exceptMe) { + for (MonsterSpawnArea a : spawnAreas) { + Monster m = a.getMonsterAt(p); + if (m != null && (exceptMe == null || exceptMe != m)) return m; + } + return null; + } + public Monster getMonsterAt(final Coord p) { return getMonsterAt(p.x, p.y); } + public Monster getMonsterAt(final int x, final int y) { + for (MonsterSpawnArea a : spawnAreas) { + Monster m = a.getMonsterAt(x, y); + if (m != null) return m; + } + return null; + } + + public Monster findSpawnedMonster(final String monsterTypeID) { + for (MonsterSpawnArea a : spawnAreas) { + Monster m = a.findSpawnedMonster(monsterTypeID); + if (m != null) return m; + } + return null; + } + + public Loot getBagAt(final Coord p) { + for (Loot l : groundBags) { + if (l.position.equals(p)) return l; + } + return null; + } + public Loot getBagOrCreateAt(final Coord position) { + Loot b = getBagAt(position); + if (b != null) return b; + boolean isContainer = hasContainerAt(position); + b = new Loot(!isContainer); + b.position.set(position); + if (isOutside(position)) { + if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + L.log("WARNING: trying to place bag outside map. Map is " + size.toString() + ", bag tried to place at " + position.toString()); + } + return b; + } + groundBags.add(b); + return b; + } + public void itemDropped(ItemType itemType, int quantity, Coord position) { + Loot l = getBagOrCreateAt(position); + l.items.addItem(itemType, quantity); + } + public void removeGroundLoot(Loot loot) { + groundBags.remove(loot); + } + public void resetForNewGame() { + for (MonsterSpawnArea a : spawnAreas) { + a.resetForNewGame(); + } + activeMapObjectGroups.clear(); + activeMapObjectGroups.addAll(initiallyActiveMapObjectGroups); + activateMapObjects(); + resetTemporaryData(); + groundBags.clear(); + visited = false; + currentColorFilter = initialColorFilter; + lastSeenLayoutHash = ""; + } + + public boolean isRecentlyVisited() { + if (lastVisitTime == VISIT_RESET) return false; + return (System.currentTimeMillis() - lastVisitTime) < Constants.MAP_UNVISITED_RESPAWN_DURATION_MS; + } + public void updateLastVisitTime() { + lastVisitTime = System.currentTimeMillis(); + } + public void resetTemporaryData() { + for(MonsterSpawnArea a : spawnAreas) { + if (a.isUnique) a.resetShops(); + else a.removeAllMonsters(); + } + splatters.clear(); + lastVisitTime = VISIT_RESET; + } + public boolean hasResetTemporaryData() { + return lastVisitTime == VISIT_RESET; + } + + public void createAllContainerLoot() { + for (MapObject o : eventObjects) { + if (!o.isActive) continue; + if (o.type != MapObject.MapObjectType.container) continue; + createContainerLoot(o); + } + } + + public void createContainerLoot(MapObject container) { + Loot bag = getBagOrCreateAt(container.position.topLeft); + container.dropList.createRandomLoot(bag, null); + } + + + private void activateMapObjects() { + for (MapObject o : eventObjects) { + o.isActive = activeMapObjectGroups.contains(o.group); + } + } + + public void activateMapObjectGroup(String group) { + if (!activeMapObjectGroups.contains(group)) { + activeMapObjectGroups.add(group); + for (MapObject o : eventObjects) { + if (o.group.equals(group)) { + o.isActive = true; + if (o.type == MapObjectType.container) createContainerLoot(o); + } + } + } + } + + public void deactivateMapObjectGroup(String group) { + if (activeMapObjectGroups.contains(group)) { + activeMapObjectGroups.remove(group); + for (MapObject o : eventObjects) { + if (o.group.equals(group)) { + o.isActive = false; + } + } + } + } + + + // ====== PARCELABLE =================================================================== + + public void readFromParcel(DataInputStream src, WorldContext world, ControllerContext controllers, int fileversion) throws IOException { + boolean shouldLoadMapData = true; + if (fileversion >= 37) shouldLoadMapData = src.readBoolean(); + + int loadedSpawnAreas = 0; + if (shouldLoadMapData) { + loadedSpawnAreas = src.readInt(); + for(int i = 0; i < loadedSpawnAreas; ++i) { + if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + if (i >= this.spawnAreas.length) { + L.log("WARNING: Trying to load monsters from savegame in map " + this.name + " for spawn #" + i + ". This will totally fail."); + } + } + if(fileversion >= 43) { + //Spawn areas now have unique IDs. Need to check as maps can change. + String id = src.readUTF(); + int j = i; + boolean found = false; + do { + if (this.spawnAreas[j].areaID.equals(id)) { + this.spawnAreas[j].readFromParcel(src, world, fileversion); + found = true; + break; + } + j = (j+1)%spawnAreas.length; + } while (j != i); + if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + if (!found) { + L.log("WARNING: Trying to load monsters from savegame in map " + this.name + " for spawn #" + id + " but this area cannot be found. This will totally fail."); + } + } + } else { + this.spawnAreas[i].readFromParcel(src, world, fileversion); + } + } + + activeMapObjectGroups.clear(); + if(fileversion >= 43) { + int activeListLength = src.readInt(); + for (int i = 0; i < activeListLength; i++) { + String activeGroupID = src.readUTF(); + activeMapObjectGroups.add(activeGroupID); + } + } else { + activeMapObjectGroups.addAll(initiallyActiveMapObjectGroups); + } + activateMapObjects(); + + groundBags.clear(); + if (fileversion <= 5) return; + + final int size2 = src.readInt(); + for(int i = 0; i < size2; ++i) { + groundBags.add(new Loot(src, world, fileversion)); + } + + if (fileversion <= 11) return; + + if (fileversion < 37) visited = src.readBoolean(); + + if (fileversion <= 15) { + if (visited) { + lastVisitTime = System.currentTimeMillis(); + createAllContainerLoot(); + } + return; + } + + if (fileversion >= 43) { + if (src.readBoolean()) { + currentColorFilter = src.readUTF(); + } else { + currentColorFilter = null; + } + } + + lastVisitTime = src.readLong(); + + if (visited) { + if (fileversion > 30 && fileversion < 36) { + /*int lastVisitVersion = */src.readInt(); + } + } + } else { + activeMapObjectGroups.clear(); + activeMapObjectGroups.addAll(initiallyActiveMapObjectGroups); + activateMapObjects(); + } + if (fileversion >= 37) { + if (fileversion < 41) visited = true; + else visited = src.readBoolean(); + } + + if (fileversion < 36) lastSeenLayoutHash = ""; + else lastSeenLayoutHash = src.readUTF(); + + for(int i = loadedSpawnAreas; i < spawnAreas.length; ++i) { + MonsterSpawnArea area = this.spawnAreas[i]; + if (area.isUnique && visited) controllers.monsterSpawnController.spawnAllInArea(this, null, area, true); + else area.resetForNewGame(); + } + } + + public boolean shouldSaveMapData(WorldContext world) { + if (!hasResetTemporaryData()) return true; + if (this == world.model.currentMap) return true; + if (!groundBags.isEmpty()) return true; + for (MonsterSpawnArea a : spawnAreas) { + if (this.visited && a.isUnique) return true; + if (a.isSpawning != a.isSpawningForNewGame) return true; + } + if (!activeMapObjectGroups.containsAll(initiallyActiveMapObjectGroups) + || !initiallyActiveMapObjectGroups.containsAll(activeMapObjectGroups)) return true; + if (currentColorFilter != null) return true; + return false; + } + + public void writeToParcel(DataOutputStream dest, WorldContext world) throws IOException { + if (shouldSaveMapData(world)) { + dest.writeBoolean(true); + dest.writeInt(spawnAreas.length); + for(MonsterSpawnArea a : spawnAreas) { + dest.writeUTF(a.areaID); + a.writeToParcel(dest); + } + dest.writeInt(activeMapObjectGroups.size()); + for(String s : activeMapObjectGroups) { + dest.writeUTF(s); + } + dest.writeInt(groundBags.size()); + for(Loot l : groundBags) { + l.writeToParcel(dest); + } + dest.writeBoolean(currentColorFilter != null); + if (currentColorFilter != null) dest.writeUTF(currentColorFilter); + dest.writeLong(lastVisitTime); + } else { + dest.writeBoolean(false); + } + dest.writeBoolean(visited); + dest.writeUTF(lastSeenLayoutHash); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java index 23c676dab..20aeb424f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java @@ -59,8 +59,10 @@ public final class TMXMapTranslator { assert(m.height > 0); boolean isOutdoors = false; + String colorFilter = null; for (TMXProperty p : m.properties) { if(p.name.equalsIgnoreCase("outdoors")) isOutdoors = (Integer.parseInt(p.value) != 0); + else if(p.name.equalsIgnoreCase("colorfilter")) colorFilter = p.value; else if(AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + " has unrecognized property \"" + p.name + "\"."); } @@ -212,7 +214,7 @@ public final class TMXMapTranslator { MonsterSpawnArea[] _spawnAreas = new MonsterSpawnArea[spawnAreas.size()]; _spawnAreas = spawnAreas.toArray(_spawnAreas); - result.add(new PredefinedMap(m.xmlResourceId, m.name, mapSize, _eventObjects, _spawnAreas, activeGroups, isOutdoors)); + result.add(new PredefinedMap(m.xmlResourceId, m.name, mapSize, _eventObjects, _spawnAreas, activeGroups, isOutdoors, colorFilter)); } return result; @@ -347,6 +349,7 @@ public final class TMXMapTranslator { HashSet usedTileIDs, SetOfLayerNames layerNames ) { + final MapLayer layerGround = transformMapLayer(layersPerLayerName, layerNames.groundLayerName, srcMap, tileCache, area, usedTileIDs); final MapLayer layerObjects = transformMapLayer(layersPerLayerName, layerNames.objectsLayerName, srcMap, tileCache, area, usedTileIDs); final MapLayer layerAbove = transformMapLayer(layersPerLayerName, layerNames.aboveLayersName, srcMap, tileCache, area, usedTileIDs); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCache.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCache.java index 0fde8963f..dec2c32df 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCache.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCache.java @@ -1,123 +1,125 @@ -package com.gpl.rpg.AndorsTrail.resource.tiles; - -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map.Entry; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import com.gpl.rpg.AndorsTrail.util.LruCache; - -public final class TileCache { - - private final ReferenceQueue gcQueue = new ReferenceQueue(); - private ResourceFileTile[] resourceTiles = new ResourceFileTile[1]; - private final HashMap tileIDsPerTilesetAndLocalID = new HashMap(); - private final LruCache cache = new LruCache(1000); - - public int getMaxTileID() { return resourceTiles.length-1; } - public void allocateMaxTileID(int maxTileID) { - if (maxTileID <= 0) return; - - ResourceFileTile[] oldArray = resourceTiles; - resourceTiles = new ResourceFileTile[maxTileID+1]; - System.arraycopy(oldArray, 0, resourceTiles, 0, oldArray.length); - } - public void setTile(int tileID, ResourceFileTileset tileset, int localID) { - if (resourceTiles[tileID] == null) resourceTiles[tileID] = new ResourceFileTile(tileset, localID); - SparseIntArray tileIDsPerLocalID = tileIDsPerTilesetAndLocalID.get(tileset.tilesetName); - if (tileIDsPerLocalID == null) { - tileIDsPerLocalID = new SparseIntArray(); - tileIDsPerTilesetAndLocalID.put(tileset.tilesetName, tileIDsPerLocalID); - } - tileIDsPerLocalID.put(localID, tileID); - } - public int getTileID(String tileSetName, int localID) { - return tileIDsPerTilesetAndLocalID.get(tileSetName).get(localID); - } - - private static final class ResourceFileTile { - public final ResourceFileTileset tileset; - public final int localID; - //public WeakReference bitmap; - public ResourceFileTile(ResourceFileTileset tileset, int localID) { - this.tileset = tileset; - this.localID = localID; - } - } - - private void cleanQueue() { - System.gc(); - Reference ref; - while ((ref = gcQueue.poll()) != null) { - Bitmap b = ref.get(); - if (b != null) b.recycle(); - } - } - - public TileCollection loadTilesFor(Collection iconIDs, Resources r) { return loadTilesFor(iconIDs, r, null); } - public TileCollection loadTilesFor(Collection iconIDs, Resources r, TileCollection result) { - int maxTileID = 0; - HashMap> tilesToLoadPerSourceFile = new HashMap>(); - for(int tileID : iconIDs) { - ResourceFileTile tile = resourceTiles[tileID]; - SparseArray tiles = tilesToLoadPerSourceFile.get(tile.tileset); - if (tiles == null) { - tiles = new SparseArray(); - tilesToLoadPerSourceFile.put(tile.tileset, tiles); - } - tiles.put(tileID, tile); - maxTileID = Math.max(maxTileID, tileID); - } - - boolean hasLoadedTiles = false; - if (result == null) result = new TileCollection(maxTileID); - for(Entry> e : tilesToLoadPerSourceFile.entrySet()) { - TileCutter cutter = null; - - SparseArray tilesToLoad = e.getValue(); - for (int i = 0; i < tilesToLoad.size(); ++i) { - int tileID = tilesToLoad.keyAt(i); - ResourceFileTile tile = tilesToLoad.valueAt(i); - - Bitmap bitmap = cache.get(tileID); - - if (bitmap == null) { - if (cutter == null) { - if (!hasLoadedTiles) cleanQueue(); - cutter = new TileCutter(e.getKey(), r); - hasLoadedTiles = true; - } - - bitmap = cutter.createTile(tile.localID); - cache.put(tileID, bitmap); - new WeakReference(bitmap, gcQueue); - } - result.setBitmap(tileID, bitmap); - } - - if (cutter != null) cutter.recycle(); - } - if (hasLoadedTiles) cleanQueue(); - return result; - } - - public Bitmap loadSingleTile(int tileID, Resources r) { - cleanQueue(); - ResourceFileTile tile = resourceTiles[tileID]; - Bitmap bitmap = cache.get(tileID); - if (bitmap != null) return bitmap; - - TileCutter cutter = new TileCutter(tile.tileset, r); - Bitmap result = cutter.createTile(tile.localID); - cutter.recycle(); - cache.put(tileID, result); - return result; - } -} +package com.gpl.rpg.AndorsTrail.resource.tiles; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map.Entry; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.util.SparseArray; +import android.util.SparseIntArray; + +import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; +import com.gpl.rpg.AndorsTrail.util.L; +import com.gpl.rpg.AndorsTrail.util.LruCache; + +public final class TileCache { + + private final ReferenceQueue gcQueue = new ReferenceQueue(); + private ResourceFileTile[] resourceTiles = new ResourceFileTile[1]; + private final HashMap tileIDsPerTilesetAndLocalID = new HashMap(); + private final LruCache cache = new LruCache(1000); + + public int getMaxTileID() { return resourceTiles.length-1; } + public void allocateMaxTileID(int maxTileID) { + if (maxTileID <= 0) return; + + ResourceFileTile[] oldArray = resourceTiles; + resourceTiles = new ResourceFileTile[maxTileID+1]; + System.arraycopy(oldArray, 0, resourceTiles, 0, oldArray.length); + } + public void setTile(int tileID, ResourceFileTileset tileset, int localID) { + if (resourceTiles[tileID] == null) resourceTiles[tileID] = new ResourceFileTile(tileset, localID); + SparseIntArray tileIDsPerLocalID = tileIDsPerTilesetAndLocalID.get(tileset.tilesetName); + if (tileIDsPerLocalID == null) { + tileIDsPerLocalID = new SparseIntArray(); + tileIDsPerTilesetAndLocalID.put(tileset.tilesetName, tileIDsPerLocalID); + } + tileIDsPerLocalID.put(localID, tileID); + } + public int getTileID(String tileSetName, int localID) { + return tileIDsPerTilesetAndLocalID.get(tileSetName).get(localID); + } + + private static final class ResourceFileTile { + public final ResourceFileTileset tileset; + public final int localID; + //public WeakReference bitmap; + public ResourceFileTile(ResourceFileTileset tileset, int localID) { + this.tileset = tileset; + this.localID = localID; + } + } + + private void cleanQueue() { + System.gc(); + Reference ref; + while ((ref = gcQueue.poll()) != null) { + Bitmap b = ref.get(); + if (b != null) b.recycle(); + } + } + + public TileCollection loadTilesFor(Collection iconIDs, Resources r) { return loadTilesFor(iconIDs, r, null); } + public TileCollection loadTilesFor(Collection iconIDs, Resources r, TileCollection result) { + int maxTileID = 0; + HashMap> tilesToLoadPerSourceFile = new HashMap>(); + for(int tileID : iconIDs) { + ResourceFileTile tile = resourceTiles[tileID]; + SparseArray tiles = tilesToLoadPerSourceFile.get(tile.tileset); + if (tiles == null) { + tiles = new SparseArray(); + tilesToLoadPerSourceFile.put(tile.tileset, tiles); + } + tiles.put(tileID, tile); + maxTileID = Math.max(maxTileID, tileID); + } + + boolean hasLoadedTiles = false; + if (result == null) result = new TileCollection(maxTileID); + for(Entry> e : tilesToLoadPerSourceFile.entrySet()) { + TileCutter cutter = null; + + SparseArray tilesToLoad = e.getValue(); + for (int i = 0; i < tilesToLoad.size(); ++i) { + int tileID = tilesToLoad.keyAt(i); + ResourceFileTile tile = tilesToLoad.valueAt(i); + + Bitmap bitmap = cache.get(tileID); + + if (bitmap == null) { + if (cutter == null) { + if (!hasLoadedTiles) cleanQueue(); + cutter = new TileCutter(e.getKey(), r); + hasLoadedTiles = true; + } + + bitmap = cutter.createTile(tile.localID); + cache.put(tileID, bitmap); + new WeakReference(bitmap, gcQueue); + } + result.setBitmap(tileID, bitmap); + } + + if (cutter != null) cutter.recycle(); + } + if (hasLoadedTiles) cleanQueue(); + return result; + } + + public Bitmap loadSingleTile(int tileID, Resources r) { + cleanQueue(); + ResourceFileTile tile = resourceTiles[tileID]; + Bitmap bitmap = cache.get(tileID); + if (bitmap != null) return bitmap; + + TileCutter cutter = new TileCutter(tile.tileset, r); + Bitmap result = cutter.createTile(tile.localID); + cutter.recycle(); + cache.put(tileID, result); + return result; + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/L.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/L.java index 71ee062f7..854e82478 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/L.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/L.java @@ -1,15 +1,15 @@ -package com.gpl.rpg.AndorsTrail.util; - -import android.util.Log; - -import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; - -public final class L { - private static final String TAG = "AndorsTrail"; - - public static void log(String s) { - if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) { - Log.d(TAG, s); - } - } -} +package com.gpl.rpg.AndorsTrail.util; + +import android.util.Log; + +import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; + +public final class L { + private static final String TAG = "AndorsTrail"; + + public static void log(String s) { + if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) { + Log.w(TAG, s); + } + } +}