Fixed "restart for locale" bugs.

Fixed missing parsing of the colorfilter map properties.
This commit is contained in:
Zukero
2018-09-21 19:38:24 +02:00
parent 52f74066d0
commit b26fada91d
6 changed files with 568 additions and 544 deletions

View File

@@ -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());
}
}

View File

@@ -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 {

View File

@@ -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<String> initiallyActiveMapObjectGroups;
public final List<String> activeMapObjectGroups;
public final ArrayList<Loot> groundBags = new ArrayList<Loot>();
public boolean visited = false;
public long lastVisitTime = VISIT_RESET;
public String lastSeenLayoutHash = "";
public final boolean isOutdoors;
public String currentColorFilter = null;
public final ArrayList<BloodSplatter> splatters = new ArrayList<BloodSplatter>();
public PredefinedMap(
int xmlResourceId
, String name
, Size size
, MapObject[] eventObjects
, MonsterSpawnArea[] spawnAreas
, List<String> 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<String>();
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<MapObject> getActiveEventObjectsAt(final Coord p) {
List<MapObject> 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<MapObject>();
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<String> initiallyActiveMapObjectGroups;
public final List<String> activeMapObjectGroups;
public final ArrayList<Loot> groundBags = new ArrayList<Loot>();
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<BloodSplatter> splatters = new ArrayList<BloodSplatter>();
public PredefinedMap(
int xmlResourceId
, String name
, Size size
, MapObject[] eventObjects
, MonsterSpawnArea[] spawnAreas
, List<String> 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<String>();
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<MapObject> getActiveEventObjectsAt(final Coord p) {
List<MapObject> 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<MapObject>();
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);
}
}

View File

@@ -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<Integer> 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);

View File

@@ -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<Bitmap> gcQueue = new ReferenceQueue<Bitmap>();
private ResourceFileTile[] resourceTiles = new ResourceFileTile[1];
private final HashMap<String, SparseIntArray> tileIDsPerTilesetAndLocalID = new HashMap<String, SparseIntArray>();
private final LruCache<Integer, Bitmap> cache = new LruCache<Integer, Bitmap>(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> bitmap;
public ResourceFileTile(ResourceFileTileset tileset, int localID) {
this.tileset = tileset;
this.localID = localID;
}
}
private void cleanQueue() {
System.gc();
Reference<? extends Bitmap> ref;
while ((ref = gcQueue.poll()) != null) {
Bitmap b = ref.get();
if (b != null) b.recycle();
}
}
public TileCollection loadTilesFor(Collection<Integer> iconIDs, Resources r) { return loadTilesFor(iconIDs, r, null); }
public TileCollection loadTilesFor(Collection<Integer> iconIDs, Resources r, TileCollection result) {
int maxTileID = 0;
HashMap<ResourceFileTileset, SparseArray<ResourceFileTile>> tilesToLoadPerSourceFile = new HashMap<ResourceFileTileset, SparseArray<ResourceFileTile>>();
for(int tileID : iconIDs) {
ResourceFileTile tile = resourceTiles[tileID];
SparseArray<ResourceFileTile> tiles = tilesToLoadPerSourceFile.get(tile.tileset);
if (tiles == null) {
tiles = new SparseArray<TileCache.ResourceFileTile>();
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<ResourceFileTileset, SparseArray<ResourceFileTile>> e : tilesToLoadPerSourceFile.entrySet()) {
TileCutter cutter = null;
SparseArray<ResourceFileTile> 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>(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<Bitmap> gcQueue = new ReferenceQueue<Bitmap>();
private ResourceFileTile[] resourceTiles = new ResourceFileTile[1];
private final HashMap<String, SparseIntArray> tileIDsPerTilesetAndLocalID = new HashMap<String, SparseIntArray>();
private final LruCache<Integer, Bitmap> cache = new LruCache<Integer, Bitmap>(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> bitmap;
public ResourceFileTile(ResourceFileTileset tileset, int localID) {
this.tileset = tileset;
this.localID = localID;
}
}
private void cleanQueue() {
System.gc();
Reference<? extends Bitmap> ref;
while ((ref = gcQueue.poll()) != null) {
Bitmap b = ref.get();
if (b != null) b.recycle();
}
}
public TileCollection loadTilesFor(Collection<Integer> iconIDs, Resources r) { return loadTilesFor(iconIDs, r, null); }
public TileCollection loadTilesFor(Collection<Integer> iconIDs, Resources r, TileCollection result) {
int maxTileID = 0;
HashMap<ResourceFileTileset, SparseArray<ResourceFileTile>> tilesToLoadPerSourceFile = new HashMap<ResourceFileTileset, SparseArray<ResourceFileTile>>();
for(int tileID : iconIDs) {
ResourceFileTile tile = resourceTiles[tileID];
SparseArray<ResourceFileTile> tiles = tilesToLoadPerSourceFile.get(tile.tileset);
if (tiles == null) {
tiles = new SparseArray<TileCache.ResourceFileTile>();
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<ResourceFileTileset, SparseArray<ResourceFileTile>> e : tilesToLoadPerSourceFile.entrySet()) {
TileCutter cutter = null;
SparseArray<ResourceFileTile> 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>(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;
}
}

View File

@@ -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);
}
}
}