package com.hypixel.hytale.server.core.entity.entities.player.data;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.codec.codecs.array.ArrayCodec;
import com.hypixel.hytale.codec.codecs.map.MapCodec;
import com.hypixel.hytale.codec.codecs.map.Object2IntMapCodec;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockMigration;
import com.hypixel.hytale.server.core.universe.Universe;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import javax.annotation.Nonnull;
public final class PlayerConfigData {
@Nonnull
public static final BuilderCodec<PlayerConfigData> CODEC;
@Nonnull
private final transient AtomicBoolean hasChanged = new AtomicBoolean();
private int blockIdVersion = 1;
private String world;
private String preset;
@Nonnull
private Set<String> knownRecipes = new HashSet();
@Nonnull
private Set<String> unmodifiableKnownRecipes;
private Map<String, PlayerWorldData> perWorldData;
@Nonnull
private Map<String, PlayerWorldData> unmodifiablePerWorldData;
@Nonnull
private Set<String> discoveredZones;
@Nonnull
private Set<String> unmodifiableDiscoveredZones;
@Nonnull
private Set<UUID> discoveredInstances;
@Nonnull
private Set<UUID> unmodifiableDiscoveredInstances;
private Object2IntMap<String> reputationData;
@Nonnull
private Object2IntMap<String> unmodifiableReputationData;
@Nonnull
private Set<UUID> activeObjectiveUUIDs;
@Nonnull
private Set<UUID> unmodifiableActiveObjectiveUUIDs;
public final Vector3d lastSavedPosition;
public final Vector3f lastSavedRotation;
public PlayerConfigData() {
this.unmodifiableKnownRecipes = Collections.unmodifiableSet(this.knownRecipes);
this.perWorldData = new ConcurrentHashMap();
this.unmodifiablePerWorldData = Collections.unmodifiableMap(this.perWorldData);
this.discoveredZones = new HashSet();
this.unmodifiableDiscoveredZones = Collections.unmodifiableSet(this.discoveredZones);
this.discoveredInstances = new HashSet();
this.unmodifiableDiscoveredInstances = Collections.unmodifiableSet(this.discoveredInstances);
this.reputationData = new Object2IntOpenHashMap<String>();
this.unmodifiableReputationData = Object2IntMaps.<String>unmodifiable(this.reputationData);
this.activeObjectiveUUIDs = ConcurrentHashMap.newKeySet();
this.unmodifiableActiveObjectiveUUIDs = Collections.unmodifiableSet(this.activeObjectiveUUIDs);
this.lastSavedPosition = new Vector3d();
this.lastSavedRotation = new Vector3f();
}
public int getBlockIdVersion() {
return this.blockIdVersion;
}
public void setBlockIdVersion(int blockIdVersion) {
this.blockIdVersion = blockIdVersion;
}
public String getWorld() {
return this.world;
}
public void setWorld(@Nonnull String world) {
this.world = world;
this.markChanged();
}
public String getPreset() {
return this.preset;
}
public void setPreset(@Nonnull String preset) {
this.preset = preset;
this.markChanged();
}
@Nonnull
public Set<String> getKnownRecipes() {
return this.unmodifiableKnownRecipes;
}
public void setKnownRecipes(@Nonnull Set<String> knownRecipes) {
this.knownRecipes = knownRecipes;
this.unmodifiableKnownRecipes = Collections.unmodifiableSet(knownRecipes);
this.markChanged();
}
@Nonnull
public Map<String, PlayerWorldData> getPerWorldData() {
return this.unmodifiablePerWorldData;
}
@Nonnull
public PlayerWorldData getPerWorldData(@Nonnull String worldName) {
return (PlayerWorldData)this.perWorldData.computeIfAbsent(worldName, (s) -> new PlayerWorldData(this));
}
public void setPerWorldData(@Nonnull Map<String, PlayerWorldData> perWorldData) {
this.perWorldData = perWorldData;
this.unmodifiablePerWorldData = Collections.unmodifiableMap(perWorldData);
this.markChanged();
}
@Nonnull
public Set<String> getDiscoveredZones() {
return this.unmodifiableDiscoveredZones;
}
public void setDiscoveredZones(@Nonnull Set<String> discoveredZones) {
this.discoveredZones = discoveredZones;
this.unmodifiableDiscoveredZones = Collections.unmodifiableSet(discoveredZones);
this.markChanged();
}
@Nonnull
public Set<UUID> getDiscoveredInstances() {
return this.unmodifiableDiscoveredInstances;
}
public void setDiscoveredInstances(@Nonnull Set<UUID> discoveredInstances) {
this.discoveredInstances = discoveredInstances;
this.unmodifiableDiscoveredInstances = Collections.unmodifiableSet(discoveredInstances);
this.markChanged();
}
@Nonnull
public Object2IntMap<String> getReputationData() {
return this.unmodifiableReputationData;
}
public void setReputationData(@Nonnull Object2IntMap<String> reputationData) {
this.reputationData = reputationData;
this.unmodifiableReputationData = Object2IntMaps.<String>unmodifiable(reputationData);
this.markChanged();
}
@Nonnull
public Set<UUID> getActiveObjectiveUUIDs() {
return this.unmodifiableActiveObjectiveUUIDs;
}
public void setActiveObjectiveUUIDs(@Nonnull Set<UUID> activeObjectiveUUIDs) {
this.activeObjectiveUUIDs.clear();
this.activeObjectiveUUIDs.addAll(activeObjectiveUUIDs);
this.markChanged();
}
public void markChanged() {
this.hasChanged.set(true);
}
public boolean consumeHasChanged() {
return this.hasChanged.getAndSet(false);
}
public void cleanup(@Nonnull Universe universe) {
Set<String> keySet = this.perWorldData.keySet();
Iterator<String> iterator = keySet.iterator();
while(iterator.hasNext()) {
String worldName = (String)iterator.next();
if (worldName.startsWith("instance-") && universe.getWorld(worldName) == null) {
iterator.remove();
}
}
}
static {
CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.builder(PlayerConfigData.class, PlayerConfigData::new).addField(new KeyedCodec("BlockIdVersion", Codec.INTEGER), (playerConfigData, s) -> playerConfigData.blockIdVersion = s, (playerConfigData) -> playerConfigData.blockIdVersion)).addField(new KeyedCodec("World", Codec.STRING), (playerConfigData, s) -> playerConfigData.world = s, (playerConfigData) -> playerConfigData.world)).addField(new KeyedCodec("Preset", Codec.STRING), (playerConfigData, s) -> playerConfigData.preset = s, (playerConfigData) -> playerConfigData.preset)).addField(new KeyedCodec("KnownRecipes", new ArrayCodec(Codec.STRING, (x$0) -> new String[x$0])), (playerConfigData, knownRecipes) -> {
playerConfigData.knownRecipes = Set.of(knownRecipes);
playerConfigData.unmodifiableKnownRecipes = Collections.unmodifiableSet(playerConfigData.knownRecipes);
}, (playerConfigData) -> (String[])playerConfigData.knownRecipes.toArray((x$0) -> new String[x$0]))).addField(new KeyedCodec("PerWorldData", new MapCodec(PlayerWorldData.CODEC, ConcurrentHashMap::new, false)), (playerConfigData, perWorldData) -> {
playerConfigData.perWorldData = perWorldData;
playerConfigData.unmodifiablePerWorldData = Collections.unmodifiableMap(perWorldData);
}, (playerConfigData) -> playerConfigData.perWorldData)).addField(new KeyedCodec("DiscoveredZones", Codec.STRING_ARRAY), (playerConfigData, discoveredZones) -> {
playerConfigData.discoveredZones = Set.of(discoveredZones);
playerConfigData.unmodifiableDiscoveredZones = Collections.unmodifiableSet(playerConfigData.discoveredZones);
}, (playerConfigData) -> (String[])playerConfigData.discoveredZones.toArray((x$0) -> new String[x$0]))).addField(new KeyedCodec("DiscoveredInstances", new ArrayCodec(Codec.UUID_BINARY, (x$0) -> new UUID[x$0])), (playerConfigData, discoveredInstances) -> {
playerConfigData.discoveredInstances = Set.of(discoveredInstances);
playerConfigData.unmodifiableDiscoveredInstances = Collections.unmodifiableSet(playerConfigData.discoveredInstances);
}, (playerConfigData) -> (UUID[])playerConfigData.discoveredInstances.toArray((x$0) -> new UUID[x$0]))).addField(new KeyedCodec("ReputationData", new Object2IntMapCodec(Codec.STRING, Object2IntOpenHashMap::new, false)), (playerConfigData, reputationData) -> {
playerConfigData.reputationData = reputationData;
playerConfigData.unmodifiableReputationData = Object2IntMaps.<String>unmodifiable(reputationData);
}, (playerConfigData) -> playerConfigData.reputationData)).addField(new KeyedCodec("ActiveObjectiveUUIDs", new ArrayCodec(Codec.UUID_BINARY, (x$0) -> new UUID[x$0])), (playerConfigData, objectives) -> Collections.addAll(playerConfigData.activeObjectiveUUIDs, objectives), (playerConfigData) -> (UUID[])playerConfigData.activeObjectiveUUIDs.toArray((x$0) -> new UUID[x$0]))).afterDecode((data) -> {
for(PlayerWorldData worldData : data.perWorldData.values()) {
worldData.setPlayerConfigData(data);
}
int v = data.getBlockIdVersion();
Map<Integer, BlockMigration> blockMigrationMap = BlockMigration.getAssetMap().getAssetMap();
BlockMigration migration = (BlockMigration)blockMigrationMap.get(v);
Function<String, String> blockMigration;
for(blockMigration = null; migration != null; migration = (BlockMigration)blockMigrationMap.get(v)) {
if (blockMigration == null) {
Objects.requireNonNull(migration);
blockMigration = migration::getMigration;
} else {
Objects.requireNonNull(migration);
blockMigration = blockMigration.andThen(migration::getMigration);
}
++v;
}
data.setBlockIdVersion(v);
if (blockMigration != null) {
Set<String> oldKnownRecipes = data.getKnownRecipes();
if (!oldKnownRecipes.isEmpty()) {
Set<String> knownRecipes = new HashSet();
for(String blockTypeKey : oldKnownRecipes) {
knownRecipes.add((String)blockMigration.apply(blockTypeKey));
}
data.setKnownRecipes(knownRecipes);
}
}
})).build();
}
}