package com.hypixel.hytale.builtin.deployables.config;
import com.hypixel.hytale.builtin.deployables.DeployablesUtils;
import com.hypixel.hytale.builtin.deployables.component.DeployableComponent;
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.map.MapCodec;
import com.hypixel.hytale.codec.lookup.CodecMapCodec;
import com.hypixel.hytale.codec.validation.Validators;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.protocol.AnimationSlot;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelParticle;
import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent;
import com.hypixel.hytale.server.core.asset.type.soundevent.validator.SoundEventValidators;
import com.hypixel.hytale.server.core.io.NetworkSerializable;
import com.hypixel.hytale.server.core.modules.entity.hitboxcollision.HitboxCollisionConfig;
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.Map;
import javax.annotation.Nonnull;
public abstract class DeployableConfig implements NetworkSerializable<com.hypixel.hytale.protocol.DeployableConfig> {
public static final CodecMapCodec<DeployableConfig> CODEC = new CodecMapCodec<DeployableConfig>("Type");
public static final BuilderCodec<DeployableConfig> BASE_CODEC;
protected Map<String, StatConfig> statValues;
protected String deploySoundEventId;
protected String despawnSoundEventId;
protected String dieSoundEventId;
protected String ambientSoundEventId;
protected ModelParticle[] spawnParticles;
protected ModelParticle[] despawnParticles;
protected transient int deploySoundEventIndex = 0;
protected transient int despawnSoundEventIndex = 0;
protected transient int dieSoundEventIndex = 0;
protected transient int ambientSoundEventIndex = 0;
protected Model generatedModel;
protected Model generatedModelPreview;
protected String hitboxCollisionConfigId;
protected int hitboxCollisionConfigIndex = -1;
private String id;
private int maxLiveCount = 2147483647;
private String model;
private String modelPreview;
private float modelScale = 1.0F;
private float liveDuration = 1.0F;
private boolean invulnerable;
private boolean debugVisuals;
private boolean allowPlaceOnWalls;
private boolean wireframeDebugVisuals;
private boolean countTowardsGlobalLimit = true;
protected DeployableConfig() {
}
private static void processConfig(DeployableConfig config) {
if (config.deploySoundEventId != null) {
config.deploySoundEventIndex = SoundEvent.getAssetMap().getIndex(config.deploySoundEventId);
}
if (config.despawnSoundEventId != null) {
config.despawnSoundEventIndex = SoundEvent.getAssetMap().getIndex(config.despawnSoundEventId);
}
if (config.dieSoundEventId != null) {
config.dieSoundEventIndex = SoundEvent.getAssetMap().getIndex(config.dieSoundEventId);
}
if (config.ambientSoundEventId != null) {
config.ambientSoundEventIndex = SoundEvent.getAssetMap().getIndex(config.ambientSoundEventId);
}
if (config.generatedModel != null) {
config.generatedModel = Model.createScaledModel((ModelAsset)ModelAsset.getAssetMap().getAsset(config.model), config.modelScale);
}
if (config.generatedModelPreview != null) {
config.generatedModelPreview = Model.createScaledModel((ModelAsset)ModelAsset.getAssetMap().getAsset(config.modelPreview), config.modelScale);
}
if (config.hitboxCollisionConfigId != null) {
config.hitboxCollisionConfigIndex = HitboxCollisionConfig.getAssetMap().getIndexOrDefault(config.hitboxCollisionConfigId, -1);
}
}
protected static void playAnimation(@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull DeployableConfig config, @Nonnull String animationSetKey) {
EntityStore externalData = store.getExternalData();
NetworkId networkIdComponent = (NetworkId)store.getComponent(ref, NetworkId.getComponentType());
DeployablesUtils.playAnimation(store, networkIdComponent.getId(), ref, config, AnimationSlot.Action, (String)null, animationSetKey);
}
protected static void stopAnimation(@Nonnull Store<EntityStore> store, @Nonnull ArchetypeChunk<EntityStore> archetypeChunk, int index) {
EntityStore externalData = store.getExternalData();
Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
if (ref != null && ref.isValid()) {
NetworkId networkIdComponent = (NetworkId)archetypeChunk.getComponent(index, NetworkId.getComponentType());
DeployablesUtils.stopAnimation(store, networkIdComponent.getId(), ref, AnimationSlot.Action);
}
}
public Model getModel() {
if (this.generatedModel != null) {
return this.generatedModel;
} else {
this.generatedModel = Model.createScaledModel((ModelAsset)ModelAsset.getAssetMap().getAsset(this.model), this.modelScale);
return this.generatedModel;
}
}
public Model getModelPreview() {
if (this.modelPreview == null) {
return null;
} else if (this.generatedModelPreview != null) {
return this.generatedModelPreview;
} else {
this.generatedModelPreview = Model.createScaledModel((ModelAsset)ModelAsset.getAssetMap().getAsset(this.modelPreview), this.modelScale);
return this.generatedModelPreview;
}
}
public int getHitboxCollisionConfigIndex() {
return this.hitboxCollisionConfigIndex;
}
public long getLiveDurationInMillis() {
return (long)(this.liveDuration * 1000.0F);
}
public float getLiveDuration() {
return this.liveDuration;
}
public String getId() {
return this.id;
}
public int getMaxLiveCount() {
return this.maxLiveCount;
}
public boolean getInvulnerable() {
return this.invulnerable;
}
public Map<String, StatConfig> getStatValues() {
return this.statValues;
}
public int getDespawnSoundEventIndex() {
return this.despawnSoundEventIndex;
}
public int getDeploySoundEventIndex() {
return this.deploySoundEventIndex;
}
public int getDieSoundEventIndex() {
return this.dieSoundEventIndex;
}
public int getAmbientSoundEventIndex() {
return this.ambientSoundEventIndex;
}
public ModelParticle[] getSpawnParticles() {
return this.spawnParticles;
}
public ModelParticle[] getDespawnParticles() {
return this.despawnParticles;
}
public boolean getDebugVisuals() {
return this.debugVisuals;
}
public boolean getAllowPlaceOnWalls() {
return this.allowPlaceOnWalls;
}
public boolean getWireframeDebugVisuals() {
return this.wireframeDebugVisuals;
}
public boolean getCountTowardsGlobalLimit() {
return this.countTowardsGlobalLimit;
}
public void tick(@Nonnull DeployableComponent deployableComponent, float dt, int index, @Nonnull ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
}
public void firstTick(@Nonnull DeployableComponent deployableComponent, float dt, int index, @Nonnull ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
}
public com.hypixel.hytale.protocol.DeployableConfig toPacket() {
com.hypixel.hytale.protocol.DeployableConfig config = new com.hypixel.hytale.protocol.DeployableConfig();
config.model = this.getModel().toPacket();
if (this.modelPreview != null) {
config.modelPreview = this.getModelPreview().toPacket();
}
config.allowPlaceOnWalls = this.allowPlaceOnWalls;
return config;
}
public String toString() {
return "DeployableConfig{}";
}
static {
BASE_CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.abstractBuilder(DeployableConfig.class).appendInherited(new KeyedCodec("Id", Codec.STRING), (o, i) -> o.id = i, (o) -> o.id, (o, p) -> o.id = p.id).documentation("Used to identify this deployable for uses such as MaxLiveCount").add()).appendInherited(new KeyedCodec("MaxLiveCount", Codec.INTEGER), (o, i) -> o.maxLiveCount = i, (o) -> o.maxLiveCount, (o, p) -> o.maxLiveCount = p.maxLiveCount).documentation("The maximum amount of this deployable that can be live at once").add()).appendInherited(new KeyedCodec("Model", Codec.STRING), (o, i) -> o.model = i, (o) -> o.model, (o, p) -> o.model = p.model).addValidator(Validators.nonNull()).addValidator(ModelAsset.VALIDATOR_CACHE.getValidator()).add()).appendInherited(new KeyedCodec("ModelPreview", Codec.STRING), (o, i) -> o.modelPreview = i, (o) -> o.modelPreview, (o, p) -> o.modelPreview = p.modelPreview).addValidator(ModelAsset.VALIDATOR_CACHE.getValidator()).add()).appendInherited(new KeyedCodec("ModelScale", Codec.FLOAT), (o, i) -> o.modelScale = i, (o) -> o.modelScale, (o, p) -> o.modelScale = p.modelScale).add()).appendInherited(new KeyedCodec("LiveDuration", Codec.FLOAT), (o, i) -> o.liveDuration = i, (o) -> o.liveDuration, (o, p) -> o.liveDuration = p.liveDuration).documentation("The duration of the lifetime of the deployable in seconds").add()).appendInherited(new KeyedCodec("Invulnerable", Codec.BOOLEAN), (o, i) -> o.invulnerable = i, (o) -> o.invulnerable, (o, p) -> o.invulnerable = p.invulnerable).documentation("Whether this deployable is invulnerable to damage or not").add()).appendInherited(new KeyedCodec("Stats", new MapCodec(DeployableConfig.StatConfig.CODEC, Object2ObjectOpenHashMap::new)), (o, i) -> o.statValues = i, (o) -> o.statValues, (i, o) -> i.statValues = o.statValues).documentation("The default stat configuration for the deployable").add()).appendInherited(new KeyedCodec("DeploySoundEventId", Codec.STRING), (o, i) -> o.deploySoundEventId = i, (o) -> o.deploySoundEventId, (i, o) -> i.deploySoundEventId = o.deploySoundEventId).documentation("The ID of the sound to play upon deployment (at deployment location)").addValidator(SoundEventValidators.ONESHOT).addValidator(SoundEventValidators.MONO).add()).appendInherited(new KeyedCodec("DespawnSoundEventId", Codec.STRING), (o, i) -> o.despawnSoundEventId = i, (o) -> o.despawnSoundEventId, (i, o) -> i.despawnSoundEventId = o.despawnSoundEventId).documentation("The ID of the sound to play when despawning").addValidator(SoundEventValidators.ONESHOT).addValidator(SoundEventValidators.MONO).add()).appendInherited(new KeyedCodec("DieSoundEventId", Codec.STRING), (o, i) -> o.dieSoundEventId = i, (o) -> o.dieSoundEventId, (i, o) -> i.dieSoundEventId = o.dieSoundEventId).documentation("The ID of the sound to play when despawning due to death").addValidator(SoundEventValidators.ONESHOT).addValidator(SoundEventValidators.MONO).add()).appendInherited(new KeyedCodec("AmbientSoundEventId", Codec.STRING), (o, i) -> o.ambientSoundEventId = i, (o) -> o.ambientSoundEventId, (i, o) -> i.ambientSoundEventId = o.ambientSoundEventId).documentation("The ID of the sound to play ambiently from the deployable while it's in the world").addValidator(SoundEventValidators.LOOPING).addValidator(SoundEventValidators.MONO).add()).appendInherited(new KeyedCodec("SpawnParticles", ModelParticle.ARRAY_CODEC), (o, i) -> o.spawnParticles = i, (o) -> o.spawnParticles, (i, o) -> i.spawnParticles = o.spawnParticles).documentation("A collection of model particles to play when this deployable is spawned.").add()).appendInherited(new KeyedCodec("DespawnParticles", ModelParticle.ARRAY_CODEC), (o, i) -> o.despawnParticles = i, (o) -> o.despawnParticles, (i, o) -> i.despawnParticles = o.despawnParticles).documentation("A collection of model particles to play when this deployable is despawned.").add()).appendInherited(new KeyedCodec("DebugVisuals", Codec.BOOLEAN), (o, i) -> o.debugVisuals = i, (o) -> o.debugVisuals, (i, o) -> i.debugVisuals = o.debugVisuals).documentation("Whether or not to display debug visuals.").add()).appendInherited(new KeyedCodec("AllowPlaceOnWalls", Codec.BOOLEAN), (o, i) -> o.allowPlaceOnWalls = i, (o) -> o.allowPlaceOnWalls, (i, o) -> i.allowPlaceOnWalls = o.allowPlaceOnWalls).documentation("Whether or not this deployable can be placed on walls.").add()).appendInherited(new KeyedCodec("WireframeDebugVisuals", Codec.BOOLEAN), (o, i) -> o.wireframeDebugVisuals = i, (o) -> o.wireframeDebugVisuals, (i, o) -> i.wireframeDebugVisuals = o.wireframeDebugVisuals).documentation("Whether debug visuals will be wireframe or have color.").add()).appendInherited(new KeyedCodec("HitboxCollisionConfig", Codec.STRING), (playerConfig, s) -> playerConfig.hitboxCollisionConfigId = s, (playerConfig) -> playerConfig.hitboxCollisionConfigId, (playerConfig, parent) -> playerConfig.hitboxCollisionConfigId = parent.hitboxCollisionConfigId).documentation("The HitboxCollision config to apply to the deployable.").addValidator(HitboxCollisionConfig.VALIDATOR_CACHE.getValidator()).add()).appendInherited(new KeyedCodec("CountTowardsGlobalLimit", Codec.BOOLEAN), (o, i) -> o.countTowardsGlobalLimit = i, (o) -> o.countTowardsGlobalLimit, (i, o) -> i.countTowardsGlobalLimit = o.countTowardsGlobalLimit).documentation("Whether or not this deployable counts towards global deployable limit").add()).afterDecode(DeployableConfig::processConfig)).build();
}
public static class StatConfig {
private static final BuilderCodec<StatConfig> CODEC;
private float max;
private float initial = 3.4028235E38F;
private StatConfig() {
}
public float getMax() {
return this.max;
}
public float getInitial() {
return this.initial;
}
static {
CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.builder(StatConfig.class, StatConfig::new).documentation("Initial and maximum values for a stat.")).append(new KeyedCodec("Max", Codec.FLOAT), (config, f) -> config.max = f, (config) -> config.max).addValidator(Validators.nonNull()).addValidator(Validators.greaterThan(0.0F)).documentation("The maximum value for the stat.").add()).append(new KeyedCodec("Initial", Codec.FLOAT), (config, f) -> config.initial = f, (config) -> config.initial).documentation("The initial value for the stat. If omitted, will be set to max.").add()).build();
}
}
}