package com.hypixel.hytale.builtin.hytalegenerator.assets.props.prefabprop;
import com.hypixel.hytale.assetstore.AssetExtraInfo;
import com.hypixel.hytale.assetstore.AssetPack;
import com.hypixel.hytale.assetstore.codec.AssetBuilderCodec;
import com.hypixel.hytale.assetstore.map.DefaultAssetMap;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
import com.hypixel.hytale.builtin.hytalegenerator.BlockMask;
import com.hypixel.hytale.builtin.hytalegenerator.LoggerUtil;
import com.hypixel.hytale.builtin.hytalegenerator.assets.blockmask.BlockMaskAsset;
import com.hypixel.hytale.builtin.hytalegenerator.assets.patterns.ConstantPatternAsset;
import com.hypixel.hytale.builtin.hytalegenerator.assets.patterns.PatternAsset;
import com.hypixel.hytale.builtin.hytalegenerator.assets.props.PropAsset;
import com.hypixel.hytale.builtin.hytalegenerator.assets.props.prefabprop.directionality.DirectionalityAsset;
import com.hypixel.hytale.builtin.hytalegenerator.assets.props.prefabprop.directionality.StaticDirectionalityAsset;
import com.hypixel.hytale.builtin.hytalegenerator.assets.scanners.OriginScannerAsset;
import com.hypixel.hytale.builtin.hytalegenerator.assets.scanners.ScannerAsset;
import com.hypixel.hytale.builtin.hytalegenerator.datastructures.WeightedMap;
import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache;
import com.hypixel.hytale.builtin.hytalegenerator.patterns.Pattern;
import com.hypixel.hytale.builtin.hytalegenerator.props.Prop;
import com.hypixel.hytale.builtin.hytalegenerator.props.directionality.Directionality;
import com.hypixel.hytale.builtin.hytalegenerator.props.prefab.MoldingDirection;
import com.hypixel.hytale.builtin.hytalegenerator.props.prefab.PrefabMoldingConfiguration;
import com.hypixel.hytale.builtin.hytalegenerator.props.prefab.PrefabProp;
import com.hypixel.hytale.builtin.hytalegenerator.scanners.Scanner;
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.validation.Validators;
import com.hypixel.hytale.common.util.ExceptionUtil;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.server.core.asset.AssetModule;
import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.PrefabBuffer;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class PrefabPropAsset extends PropAsset {
public static final BuilderCodec<PrefabPropAsset> CODEC;
private WeightedPathAsset[] weightedPrefabPathAssets = new WeightedPathAsset[0];
private boolean legacyPath = false;
private boolean loadEntities = true;
private DirectionalityAsset directionalityAsset = new StaticDirectionalityAsset();
private ScannerAsset scannerAsset = new OriginScannerAsset();
private BlockMaskAsset blockMaskAsset = new BlockMaskAsset();
private MoldingDirection moldingDirectionName;
private ScannerAsset moldingScannerAsset;
private PatternAsset moldingPatternAsset;
private boolean moldChildren;
public PrefabPropAsset() {
this.moldingDirectionName = MoldingDirection.NONE;
this.moldingScannerAsset = new OriginScannerAsset();
this.moldingPatternAsset = new ConstantPatternAsset();
this.moldChildren = false;
}
public void cleanUp() {
this.directionalityAsset.cleanUp();
this.scannerAsset.cleanUp();
this.blockMaskAsset.cleanUp();
this.moldingScannerAsset.cleanUp();
this.moldingPatternAsset.cleanUp();
}
@Nonnull
public Prop build(@Nonnull PropAsset.Argument argument) {
if (!super.skip() && this.weightedPrefabPathAssets.length != 0) {
WeightedMap<List<PrefabBuffer>> prefabWeightedMap = new WeightedMap<List<PrefabBuffer>>();
for(WeightedPathAsset pathAsset : this.weightedPrefabPathAssets) {
List<PrefabBuffer> pathPrefabs = this.loadPrefabBuffersFrom(pathAsset.path);
if (pathPrefabs != null) {
prefabWeightedMap.add(pathPrefabs, pathAsset.weight);
}
}
if (prefabWeightedMap.size() == 0) {
return Prop.noProp();
} else {
MaterialCache voxelCache = argument.materialCache;
BlockMask blockMask;
if (this.blockMaskAsset == null) {
blockMask = new BlockMask();
} else {
blockMask = this.blockMaskAsset.build(voxelCache);
}
Scanner scanner = this.scannerAsset.build(ScannerAsset.argumentFrom(argument));
Directionality directionality = this.directionalityAsset.build(DirectionalityAsset.argumentFrom(argument));
MoldingDirection moldingDirection = this.moldingDirectionName;
PrefabMoldingConfiguration moldingConfiguration = null;
if (moldingDirection != MoldingDirection.DOWN && moldingDirection != MoldingDirection.UP) {
moldingConfiguration = PrefabMoldingConfiguration.none();
} else {
Scanner moldingScanner = this.moldingScannerAsset == null ? Scanner.noScanner() : this.moldingScannerAsset.build(ScannerAsset.argumentFrom(argument));
Pattern moldingPattern = this.moldingPatternAsset == null ? Pattern.noPattern() : this.moldingPatternAsset.build(PatternAsset.argumentFrom(argument));
moldingConfiguration = new PrefabMoldingConfiguration(moldingScanner, moldingPattern, moldingDirection, this.moldChildren);
}
return new PrefabProp(prefabWeightedMap, scanner, directionality, voxelCache, blockMask, moldingConfiguration, this::loadPrefabBuffersFrom, argument.parentSeed, this.loadEntities);
}
} else {
return Prop.noProp();
}
}
@Nullable
private List<PrefabBuffer> loadPrefabBuffersFrom(@Nonnull String path) {
List<PrefabBuffer> pathPrefabs = new ArrayList();
for(AssetPack pack : AssetModule.get().getAssetPacks()) {
Path fullPath = pack.getRoot().resolve("Server");
if (this.legacyPath) {
fullPath = fullPath.resolve("World").resolve("Default").resolve("Prefabs");
} else {
fullPath = fullPath.resolve("Prefabs");
}
fullPath = fullPath.resolve(path);
try {
PrefabLoader.loadAllPrefabBuffersUnder(fullPath, pathPrefabs);
} catch (Exception e) {
String msg = "Couldn't load prefab with path: " + path;
msg = msg + "\n";
msg = msg + ExceptionUtil.toStringWithStack(e);
LoggerUtil.getLogger().severe(msg);
return null;
}
}
if (pathPrefabs.isEmpty()) {
((HytaleLogger.Api)HytaleLogger.getLogger().atWarning()).log("This prefab path contains no prefabs: " + path);
return null;
} else {
return pathPrefabs;
}
}
static {
CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.builder(PrefabPropAsset.class, PrefabPropAsset::new, PropAsset.ABSTRACT_CODEC).append(new KeyedCodec("WeightedPrefabPaths", new ArrayCodec(PrefabPropAsset.WeightedPathAsset.CODEC, (x$0) -> new WeightedPathAsset[x$0]), true), (asset, v) -> asset.weightedPrefabPathAssets = v, (asset) -> asset.weightedPrefabPathAssets).add()).append(new KeyedCodec("LegacyPath", Codec.BOOLEAN, false), (asset, v) -> asset.legacyPath = v, (asset) -> asset.legacyPath).add()).append(new KeyedCodec("Directionality", DirectionalityAsset.CODEC, true), (asset, v) -> asset.directionalityAsset = v, (asset) -> asset.directionalityAsset).add()).append(new KeyedCodec("Scanner", ScannerAsset.CODEC, true), (asset, v) -> asset.scannerAsset = v, (asset) -> asset.scannerAsset).add()).append(new KeyedCodec("BlockMask", BlockMaskAsset.CODEC, false), (asset, v) -> asset.blockMaskAsset = v, (asset) -> asset.blockMaskAsset).add()).append(new KeyedCodec("MoldingDirection", MoldingDirection.CODEC, false), (t, k) -> t.moldingDirectionName = k, (k) -> k.moldingDirectionName).add()).append(new KeyedCodec("MoldingPattern", PatternAsset.CODEC, false), (asset, v) -> asset.moldingPatternAsset = v, (asset) -> asset.moldingPatternAsset).add()).append(new KeyedCodec("MoldingScanner", ScannerAsset.CODEC, false), (asset, v) -> asset.moldingScannerAsset = v, (asset) -> asset.moldingScannerAsset).add()).append(new KeyedCodec("MoldingChildren", Codec.BOOLEAN, false), (asset, v) -> asset.moldChildren = v, (asset) -> asset.moldChildren).add()).append(new KeyedCodec("LoadEntities", Codec.BOOLEAN, false), (asset, v) -> asset.loadEntities = v, (asset) -> asset.loadEntities).add()).build();
}
public static class WeightedPathAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, WeightedPathAsset>> {
public static final AssetBuilderCodec<String, WeightedPathAsset> CODEC;
private String id;
private AssetExtraInfo.Data data;
private double weight = 1.0;
private String path;
public WeightedPathAsset() {
}
public String getId() {
return this.id;
}
static {
CODEC = ((AssetBuilderCodec.Builder)((AssetBuilderCodec.Builder)AssetBuilderCodec.builder(WeightedPathAsset.class, WeightedPathAsset::new, Codec.STRING, (asset, id) -> asset.id = id, (config) -> config.id, (config, data) -> config.data = data, (config) -> config.data).append(new KeyedCodec("Weight", Codec.DOUBLE, true), (t, y) -> t.weight = y, (t) -> t.weight).addValidator(Validators.greaterThanOrEqual(0.0)).add()).append(new KeyedCodec("Path", Codec.STRING, true), (t, out) -> t.path = out, (t) -> t.path).add()).build();
}
}
}