Partially implemented specific unlock databases

This commit is contained in:
Anuken
2018-09-28 14:17:44 -04:00
parent 24decf8abc
commit 967998273f
4 changed files with 115 additions and 43 deletions

View File

@@ -14,8 +14,9 @@ android:
- addon-google_apis-google-27 - addon-google_apis-google-27
- build-tools-27.0.3 - build-tools-27.0.3
script: script:
- ./gradlew desktop:dist - ./gradlew desktop:dist
- ./gradlew server:dist
after_success: after_success:
- chmod +x upload-build.sh - chmod +x upload-build.sh

View File

@@ -4,16 +4,14 @@ import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.ObjectMap.Entry; import com.badlogic.gdx.utils.ObjectMap.Entry;
import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.ObjectSet;
import io.anuke.mindustry.game.EventType.UnlockEvent; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.ContentType;
import io.anuke.ucore.core.Events;
import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Settings;
import static io.anuke.mindustry.Vars.*;
public class ContentDatabase{ public class ContentDatabase{
/** Maps unlockable type names to a set of unlocked content.*/ private ObjectMap<String, ContentUnlockSet> sets = new ObjectMap<>();
private ObjectMap<ContentType, ObjectSet<String>> unlocked = new ObjectMap<>();
/** Whether unlockables have changed since the last save.*/
private boolean dirty;
static{ static{
Settings.setSerializer(ContentType.class, (stream, t) -> stream.writeInt(t.ordinal()), stream -> ContentType.values()[stream.readInt()]); Settings.setSerializer(ContentType.class, (stream, t) -> stream.writeInt(t.ordinal()), stream -> ContentType.values()[stream.readInt()]);
@@ -21,15 +19,7 @@ public class ContentDatabase{
/** Returns whether or not this piece of content is unlocked yet.*/ /** Returns whether or not this piece of content is unlocked yet.*/
public boolean isUnlocked(UnlockableContent content){ public boolean isUnlocked(UnlockableContent content){
if(content.alwaysUnlocked()) return true; return rootSet().isUnlocked(content) || currentSet().isUnlocked(content);
if(!unlocked.containsKey(content.getContentType())){
unlocked.put(content.getContentType(), new ObjectSet<>());
}
ObjectSet<String> set = unlocked.get(content.getContentType());
return set.contains(content.getContentName());
} }
/** /**
@@ -40,58 +30,81 @@ public class ContentDatabase{
* @return whether or not this content was newly unlocked. * @return whether or not this content was newly unlocked.
*/ */
public boolean unlockContent(UnlockableContent content){ public boolean unlockContent(UnlockableContent content){
if(!content.canBeUnlocked() || content.alwaysUnlocked()) return false; if(rootSet().isUnlocked(content)) return false;
return currentSet().unlockContent(content);
}
if(!unlocked.containsKey(content.getContentType())){ private ContentUnlockSet currentSet(){
unlocked.put(content.getContentType(), new ObjectSet<>()); //client connected to server: always return the IP-specific set
if(Net.client()){
return getSet(Net.getLastIP());
}else if(world.getSector() != null || state.mode.infiniteResources){ //sector-sandbox have shared set
return rootSet();
}else if(control != null && control.getSaves().getCurrent() != null){ //per-save set
return getSet(String.valueOf(control.getSaves().getCurrent().index));
}else{ //dedicated server set
return rootSet();
} }
}
boolean ret = unlocked.get(content.getContentType()).add(content.getContentName()); private ContentUnlockSet rootSet(){
return getSet("root");
}
//fire unlock event so other classes can use it private ContentUnlockSet getSet(String name){
if(ret){ if(!sets.containsKey(name)){
content.onUnlock(); sets.put(name, new ContentUnlockSet());
Events.fire(new UnlockEvent(content));
dirty = true;
} }
return sets.get(name);
return ret;
} }
/** Returns whether unlockables have changed since the last save.*/ /** Returns whether unlockables have changed since the last save.*/
public boolean isDirty(){ public boolean isDirty(){
return dirty; for(ContentUnlockSet set : sets.values()){
if(set.isDirty()){
return true;
}
}
return false;
} }
/** Clears all unlocked content.*/ /** Clears all unlocked content. Automatically saves.*/
public void reset(){ public void reset(){
unlocked.clear(); sets.clear();
dirty = true; save();
} }
public void load(){ public void load(){
ObjectMap<ContentType, Array<String>> result = Settings.getBinary("content-database", ObjectMap.class, () -> new ObjectMap<>()); sets.clear();
for(Entry<ContentType, Array<String>> entry : result.entries()){ ObjectMap<String, ObjectMap<ContentType, Array<String>>> result = Settings.getBinary("content-database", ObjectMap.class, () -> new ObjectMap<>());
ObjectSet<String> set = new ObjectSet<>();
set.addAll(entry.value); for(Entry<String, ObjectMap<ContentType, Array<String>>> outer : result.entries()){
unlocked.put(entry.key, set); ContentUnlockSet cset = new ContentUnlockSet();
for (Entry<ContentType, Array<String>> entry : outer.value.entries()){
ObjectSet<String> set = new ObjectSet<>();
set.addAll(entry.value);
cset.getUnlocked().put(entry.key, set);
}
sets.put(outer.key, cset);
} }
dirty = false;
} }
public void save(){ public void save(){
ObjectMap<String, ObjectMap<ContentType, Array<String>>> output = new ObjectMap<>();
ObjectMap<ContentType, Array<String>> write = new ObjectMap<>(); for(Entry<String, ContentUnlockSet> centry : sets.entries()){
ObjectMap<ContentType, Array<String>> write = new ObjectMap<>();
for(Entry<ContentType, ObjectSet<String>> entry : unlocked.entries()){ for(Entry<ContentType, ObjectSet<String>> entry : centry.value.getUnlocked().entries()){
write.put(entry.key, entry.value.iterator().toArray()); write.put(entry.key, entry.value.iterator().toArray());
}
output.put(centry.key, write);
} }
Settings.putBinary("content-database", write); Settings.putBinary("content-database", output);
Settings.save(); Settings.save();
dirty = false;
} }
} }

View File

@@ -0,0 +1,51 @@
package io.anuke.mindustry.game;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.ObjectSet;
import io.anuke.mindustry.game.EventType.UnlockEvent;
import io.anuke.mindustry.type.ContentType;
import io.anuke.ucore.core.Events;
public class ContentUnlockSet {
private ObjectMap<ContentType, ObjectSet<String>> unlocked = new ObjectMap<>();
private boolean dirty;
public boolean isUnlocked(UnlockableContent content){
if(content.alwaysUnlocked()) return true;
if(!unlocked.containsKey(content.getContentType())){
unlocked.put(content.getContentType(), new ObjectSet<>());
}
ObjectSet<String> set = unlocked.get(content.getContentType());
return set.contains(content.getContentName());
}
public boolean unlockContent(UnlockableContent content){
if(!content.canBeUnlocked() || content.alwaysUnlocked()) return false;
if(!unlocked.containsKey(content.getContentType())){
unlocked.put(content.getContentType(), new ObjectSet<>());
}
boolean ret = unlocked.get(content.getContentType()).add(content.getContentName());
//fire unlock event so other classes can use it
if(ret){
content.onUnlock();
Events.fire(new UnlockEvent(content));
dirty = true;
}
return ret;
}
public boolean isDirty() {
return dirty;
}
public ObjectMap<ContentType, ObjectSet<String>> getUnlocked() {
return unlocked;
}
}

View File

@@ -31,6 +31,7 @@ public class Net{
private static boolean server; private static boolean server;
private static boolean active; private static boolean active;
private static boolean clientLoaded; private static boolean clientLoaded;
private static String lastIP;
private static Array<Object> packetQueue = new Array<>(); private static Array<Object> packetQueue = new Array<>();
private static ObjectMap<Class<?>, Consumer> clientListeners = new ObjectMap<>(); private static ObjectMap<Class<?>, Consumer> clientListeners = new ObjectMap<>();
private static ObjectMap<Class<?>, BiConsumer<Integer, Object>> serverListeners = new ObjectMap<>(); private static ObjectMap<Class<?>, BiConsumer<Integer, Object>> serverListeners = new ObjectMap<>();
@@ -79,6 +80,7 @@ public class Net{
* Connect to an address. * Connect to an address.
*/ */
public static void connect(String ip, int port) throws IOException{ public static void connect(String ip, int port) throws IOException{
lastIP = ip + ":" + port;
if(!active){ if(!active){
clientProvider.connect(ip, port); clientProvider.connect(ip, port);
active = true; active = true;
@@ -88,6 +90,11 @@ public class Net{
} }
} }
/**Returns the last IP connected to.*/
public static String getLastIP() {
return lastIP;
}
/** /**
* Host a server at an address. * Host a server at an address.
*/ */