hytale-server/com/hypixel/hytale/assetstore/AssetExtraInfo.java

280 lines
9.9 KiB
Java

package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
import com.hypixel.hytale.codec.ExtraInfo;
import com.hypixel.hytale.common.util.ArrayUtil;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.ints.IntSets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class AssetExtraInfo<K> extends ExtraInfo {
@Nullable
private final Path assetPath;
private final AssetExtraInfo.Data data;
public AssetExtraInfo(AssetExtraInfo.Data data) {
super(Integer.MAX_VALUE, AssetValidationResults::new);
this.assetPath = null;
this.data = data;
}
public AssetExtraInfo(Path assetPath, AssetExtraInfo.Data data) {
super(Integer.MAX_VALUE, AssetValidationResults::new);
this.assetPath = assetPath;
this.data = data;
}
@Nonnull
public String generateKey() {
return "*" + this.getKey() + "_" + this.peekKey('_');
}
public K getKey() {
return (K)this.getData().getKey();
}
@Nullable
public Path getAssetPath() {
return this.assetPath;
}
public AssetExtraInfo.Data getData() {
return this.data;
}
@Override
public void appendDetailsTo(@Nonnull StringBuilder sb) {
sb.append("Id: ").append(this.getKey()).append("\n");
if (this.assetPath != null) {
sb.append("Path: ").append(this.assetPath).append("\n");
}
}
public AssetValidationResults getValidationResults() {
return (AssetValidationResults)super.getValidationResults();
}
@Nonnull
@Override
public String toString() {
return "AssetExtraInfo{assetPath=" + this.assetPath + ", data=" + this.data + "} " + super.toString();
}
public static class Data {
public static final char TAG_VALUE_SEPARATOR = '=';
private Map<Class<? extends JsonAssetWithMap>, List<Object>> containedAssets;
private Map<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> containedRawAssets;
@Nullable
private AssetExtraInfo.Data containerData;
private Class<? extends JsonAsset<?>> assetClass;
private Object key;
private Object parentKey;
private final Map<String, String[]> rawTags = new HashMap<>(0);
private final Int2ObjectMap<IntSet> tagStorage = new Int2ObjectOpenHashMap(0);
private final Int2ObjectMap<IntSet> unmodifiableTagStorage = new Int2ObjectOpenHashMap(0);
private final IntSet expandedTagStorage = new IntOpenHashSet(0);
private final IntSet unmodifiableExpandedTagStorage = IntSets.unmodifiable(this.expandedTagStorage);
public <K> Data(Class<? extends JsonAsset<K>> assetClass, K key, K parentKey) {
this.assetClass = assetClass;
this.key = key;
this.parentKey = parentKey;
}
public <K> Data(@Nullable AssetExtraInfo.Data containerData, Class<? extends JsonAsset<K>> aClass, K key, K parentKey, boolean inheritContainerTags) {
this(aClass, key, parentKey);
this.containerData = containerData;
if (containerData != null && inheritContainerTags) {
this.putTags(containerData.rawTags);
}
}
public Class<? extends JsonAsset<?>> getAssetClass() {
return this.assetClass;
}
public Object getKey() {
return this.key;
}
public Object getParentKey() {
return this.parentKey;
}
@Nonnull
public AssetExtraInfo.Data getRootContainerData() {
AssetExtraInfo.Data temp = this;
while (temp.containerData != null) {
temp = temp.containerData;
}
return temp;
}
@Nullable
public AssetExtraInfo.Data getContainerData() {
return this.containerData;
}
@Nullable
public <K> K getContainerKey(Class<? extends JsonAsset<K>> aClass) {
if (this.containerData == null) {
return null;
} else {
return (K)(this.containerData.assetClass.equals(aClass) ? this.containerData.key : this.containerData.getContainerKey(aClass));
}
}
public void putTags(@Nonnull Map<String, String[]> tags) {
for (Entry<String, String[]> entry : tags.entrySet()) {
String tag = entry.getKey().intern();
this.rawTags.merge(tag, entry.getValue(), ArrayUtil::combine);
IntSet tagIndexes = this.ensureTag(tag);
for (String value : entry.getValue()) {
tagIndexes.add(AssetRegistry.getOrCreateTagIndex(value));
this.ensureTag(value);
this.rawTags.putIfAbsent(value, ArrayUtil.EMPTY_STRING_ARRAY);
String valueTag = (tag + "=" + value).intern();
this.rawTags.putIfAbsent(valueTag, ArrayUtil.EMPTY_STRING_ARRAY);
this.ensureTag(valueTag);
}
}
}
@Nonnull
public Map<String, String[]> getRawTags() {
return Collections.unmodifiableMap(this.rawTags);
}
@Nonnull
public Int2ObjectMap<IntSet> getTags() {
return Int2ObjectMaps.unmodifiable(this.unmodifiableTagStorage);
}
@Nonnull
public IntSet getExpandedTagIndexes() {
return this.unmodifiableExpandedTagStorage;
}
public IntSet getTag(int tagIndex) {
return (IntSet)this.unmodifiableTagStorage.getOrDefault(tagIndex, IntSets.EMPTY_SET);
}
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> void addContainedAsset(Class<T> assetClass, T asset) {
if (this.containedAssets == null) {
this.containedAssets = new HashMap<>();
}
this.containedAssets.computeIfAbsent(assetClass, k -> new ArrayList<>()).add(asset);
}
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> void addContainedAsset(Class<T> assetClass, RawAsset<K> rawAsset) {
if (this.containedRawAssets == null) {
this.containedRawAssets = new HashMap<>();
}
this.containedRawAssets.computeIfAbsent(assetClass, k -> new ArrayList<>()).add(rawAsset);
}
public <K> void fetchContainedAssets(K key, @Nonnull Map<Class<? extends JsonAssetWithMap>, Map<K, List<Object>>> containedAssets) {
if (this.containedAssets != null) {
for (Entry<Class<? extends JsonAssetWithMap>, List<Object>> entry : this.containedAssets.entrySet()) {
containedAssets.computeIfAbsent(entry.getKey(), k -> new HashMap<>()).computeIfAbsent(key, k -> new ArrayList<>(3)).addAll(entry.getValue());
}
}
}
public <K> void fetchContainedRawAssets(K key, @Nonnull Map<Class<? extends JsonAssetWithMap>, Map<K, List<RawAsset<Object>>>> containedAssets) {
if (this.containedRawAssets != null) {
for (Entry<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> entry : this.containedRawAssets.entrySet()) {
containedAssets.computeIfAbsent(entry.getKey(), k -> new HashMap<>()).computeIfAbsent(key, k -> new ArrayList<>(3)).addAll(entry.getValue());
}
}
}
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> boolean containsAsset(Class<T> tClass, K key) {
if (this.containedAssets != null) {
List<T> assets = (List<T>)this.containedAssets.get(tClass);
if (assets != null) {
Function<T, K> keyFunction = AssetRegistry.<K, T, M>getAssetStore(tClass).getKeyFunction();
for (T asset : assets) {
if (key.equals(keyFunction.apply(asset))) {
return true;
}
}
}
}
if (this.containedRawAssets != null) {
List<RawAsset<T>> rawAssets = (List<RawAsset<T>>)this.containedRawAssets.get(tClass);
if (rawAssets != null) {
for (RawAsset<T> rawAsset : rawAssets) {
if (key.equals(rawAsset.getKey())) {
return true;
}
}
}
}
return false;
}
public void loadContainedAssets(boolean reloading) {
if (this.containedAssets != null) {
for (Entry<Class<? extends JsonAssetWithMap>, List<Object>> entry : this.containedAssets.entrySet()) {
AssetRegistry.getAssetStore(entry.getKey()).loadAssets("Hytale:Hytale", entry.getValue(), AssetUpdateQuery.DEFAULT, reloading);
}
}
if (this.containedRawAssets != null) {
for (Entry<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> entry : this.containedRawAssets.entrySet()) {
AssetRegistry.getAssetStore(entry.getKey()).loadBuffersWithKeys("Hytale:Hytale", entry.getValue(), AssetUpdateQuery.DEFAULT, reloading);
}
}
}
@Nonnull
private IntSet ensureTag(@Nonnull String tag) {
int idx = AssetRegistry.getOrCreateTagIndex(tag);
this.expandedTagStorage.add(idx);
return (IntSet)this.tagStorage.computeIfAbsent(idx, k -> {
IntSet set = new IntOpenHashSet(3);
this.unmodifiableTagStorage.put(k, IntSets.unmodifiable(set));
return set;
});
}
@Nonnull
@Override
public String toString() {
return "Data{containedAssets="
+ this.containedRawAssets
+ ", rawTags="
+ this.rawTags
+ ", parent="
+ this.containerData
+ ", assetClass="
+ this.assetClass
+ ", key="
+ this.key
+ "}";
}
}
}