package com.hypixel.hytale.server.core.modules.entity.system;
import com.hypixel.hytale.assetstore.map.DefaultAssetMap;
import com.hypixel.hytale.common.util.RandomUtil;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.SystemGroup;
import com.hypixel.hytale.component.dependency.Dependency;
import com.hypixel.hytale.component.dependency.Order;
import com.hypixel.hytale.component.dependency.SystemDependency;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.system.HolderSystem;
import com.hypixel.hytale.component.system.RefChangeSystem;
import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
import com.hypixel.hytale.math.shape.Box;
import com.hypixel.hytale.protocol.ComponentUpdate;
import com.hypixel.hytale.protocol.ComponentUpdateType;
import com.hypixel.hytale.protocol.MovementStates;
import com.hypixel.hytale.protocol.PlayerSkin;
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.cosmetics.CosmeticsModule;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.entity.entities.player.movement.MovementManager;
import com.hypixel.hytale.server.core.entity.movement.MovementStatesComponent;
import com.hypixel.hytale.server.core.entity.movement.MovementStatesSystems;
import com.hypixel.hytale.server.core.modules.entity.component.ActiveAnimationComponent;
import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.entity.component.PropComponent;
import com.hypixel.hytale.server.core.modules.entity.player.ApplyRandomSkinPersistedComponent;
import com.hypixel.hytale.server.core.modules.entity.player.PlayerSkinComponent;
import com.hypixel.hytale.server.core.modules.entity.tracker.EntityTrackerSystems;
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
import com.hypixel.hytale.server.core.prefab.PrefabCopyableComponent;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class ModelSystems {
public ModelSystems() {
}
public static class ModelChange extends RefChangeSystem<EntityStore, ModelComponent> {
private final ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
private final ComponentType<EntityStore, PersistentModel> persistentModelComponentType = PersistentModel.getComponentType();
public ModelChange() {
}
public Query<EntityStore> getQuery() {
return this.persistentModelComponentType;
}
@Nonnull
public ComponentType<EntityStore, ModelComponent> componentType() {
return this.modelComponentType;
}
public void onComponentAdded(@Nonnull Ref<EntityStore> ref, @Nonnull ModelComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
}
public void onComponentSet(@Nonnull Ref<EntityStore> ref, ModelComponent oldComponent, @Nonnull ModelComponent newComponent, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
PersistentModel persistentModel = (PersistentModel)store.getComponent(ref, this.persistentModelComponentType);
persistentModel.setModelReference(newComponent.getModel().toReference());
}
public void onComponentRemoved(@Nonnull Ref<EntityStore> ref, @Nonnull ModelComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
commandBuffer.removeComponent(ref, this.persistentModelComponentType);
}
}
public static class ModelSpawned extends HolderSystem<EntityStore> {
private final ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
private final ComponentType<EntityStore, BoundingBox> boundingBoxComponentType = BoundingBox.getComponentType();
private final Set<Dependency<EntityStore>> dependencies;
public ModelSpawned() {
this.dependencies = Set.of(new SystemDependency(Order.AFTER, SetRenderedModel.class));
}
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
Model model = ((ModelComponent)holder.getComponent(this.modelComponentType)).getModel();
Box modelBoundingBox = model.getBoundingBox();
if (modelBoundingBox != null) {
BoundingBox boundingBox = (BoundingBox)holder.getComponent(this.boundingBoxComponentType);
if (boundingBox == null) {
boundingBox = new BoundingBox();
holder.addComponent(this.boundingBoxComponentType, boundingBox);
}
boundingBox.setBoundingBox(modelBoundingBox);
boundingBox.setDetailBoxes(model.getDetailBoxes());
}
}
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) {
}
public Query<EntityStore> getQuery() {
return this.modelComponentType;
}
@Nonnull
public Set<Dependency<EntityStore>> getDependencies() {
return this.dependencies;
}
}
public static class SetRenderedModel extends HolderSystem<EntityStore> {
private final ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
private final ComponentType<EntityStore, PersistentModel> persistentModelComponentType = PersistentModel.getComponentType();
private final Query<EntityStore> query;
public SetRenderedModel() {
this.query = Query.<EntityStore>and(this.persistentModelComponentType, Query.not(this.modelComponentType));
}
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
PersistentModel persistentModel = (PersistentModel)holder.getComponent(this.persistentModelComponentType);
holder.putComponent(this.modelComponentType, new ModelComponent(persistentModel.getModelReference().toModel()));
}
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) {
}
@Nonnull
public Query<EntityStore> getQuery() {
return this.query;
}
}
public static class AssignNetworkIdToProps extends HolderSystem<EntityStore> {
private final ComponentType<EntityStore, PropComponent> propComponentType = PropComponent.getComponentType();
private final ComponentType<EntityStore, NetworkId> networkIdComponentType = NetworkId.getComponentType();
private final Query<EntityStore> query;
public AssignNetworkIdToProps() {
this.query = Query.<EntityStore>and(this.propComponentType, Query.not(this.networkIdComponentType));
}
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
holder.addComponent(this.networkIdComponentType, new NetworkId(((EntityStore)store.getExternalData()).takeNextNetworkId()));
}
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) {
}
@Nonnull
public Query<EntityStore> getQuery() {
return this.query;
}
}
public static class EnsurePropsPrefabCopyable extends HolderSystem<EntityStore> {
private final ComponentType<EntityStore, PropComponent> propComponentType = PropComponent.getComponentType();
public EnsurePropsPrefabCopyable() {
}
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
holder.ensureComponent(PrefabCopyableComponent.getComponentType());
}
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) {
}
@Nonnull
public Query<EntityStore> getQuery() {
return this.propComponentType;
}
}
public static class ApplyRandomSkin extends HolderSystem<EntityStore> {
private final ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
private final ComponentType<EntityStore, ApplyRandomSkinPersistedComponent> randomSkinComponent = ApplyRandomSkinPersistedComponent.getComponentType();
private final Query<EntityStore> query;
public ApplyRandomSkin() {
this.query = Query.<EntityStore>and(this.randomSkinComponent, this.modelComponentType);
}
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
PlayerSkin playerSkin = CosmeticsModule.get().generateRandomSkin(RandomUtil.getSecureRandom());
holder.putComponent(PlayerSkinComponent.getComponentType(), new PlayerSkinComponent(playerSkin));
}
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) {
}
@Nonnull
public Query<EntityStore> getQuery() {
return this.query;
}
}
public static class PlayerConnect extends HolderSystem<EntityStore> {
private final ComponentType<EntityStore, Player> playerComponentType = Player.getComponentType();
private final ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
private final Query<EntityStore> query;
private final Set<Dependency<EntityStore>> dependencies;
public PlayerConnect() {
this.query = Query.<EntityStore>and(this.playerComponentType, Query.not(this.modelComponentType));
this.dependencies = Set.of(new SystemDependency(Order.BEFORE, ModelSpawned.class));
}
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
Player player = (Player)holder.getComponent(this.playerComponentType);
DefaultAssetMap<String, ModelAsset> assetMap = ModelAsset.getAssetMap();
String preset = player.getPlayerConfigData().getPreset();
ModelAsset modelAsset = preset != null ? (ModelAsset)assetMap.getAsset(preset) : null;
if (modelAsset != null) {
Model model = Model.createUnitScaleModel(modelAsset);
holder.addComponent(this.modelComponentType, new ModelComponent(model));
} else {
ModelAsset defaultModelAsset = assetMap.getAsset("Player");
if (defaultModelAsset != null) {
Model defaultModel = Model.createUnitScaleModel(defaultModelAsset);
holder.addComponent(this.modelComponentType, new ModelComponent(defaultModel));
}
}
}
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) {
}
@Nonnull
public Query<EntityStore> getQuery() {
return this.query;
}
@Nonnull
public Set<Dependency<EntityStore>> getDependencies() {
return this.dependencies;
}
}
public static class UpdateBoundingBox extends RefChangeSystem<EntityStore, ModelComponent> {
private final ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
private final ComponentType<EntityStore, BoundingBox> boundingBoxComponentType = BoundingBox.getComponentType();
private final ComponentType<EntityStore, MovementStatesComponent> movementStatesComponentType = MovementStatesComponent.getComponentType();
public UpdateBoundingBox() {
}
public Query<EntityStore> getQuery() {
return this.boundingBoxComponentType;
}
@Nonnull
public ComponentType<EntityStore, ModelComponent> componentType() {
return this.modelComponentType;
}
public void onComponentAdded(@Nonnull Ref<EntityStore> ref, @Nonnull ModelComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
BoundingBox boundingBox = (BoundingBox)commandBuffer.getComponent(ref, this.boundingBoxComponentType);
MovementStatesComponent movementStates = (MovementStatesComponent)commandBuffer.getComponent(ref, this.movementStatesComponentType);
updateBoundingBox(component.getModel(), boundingBox, movementStates);
}
public void onComponentSet(@Nonnull Ref<EntityStore> ref, ModelComponent oldComponent, @Nonnull ModelComponent newComponent, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
BoundingBox boundingBox = (BoundingBox)commandBuffer.getComponent(ref, this.boundingBoxComponentType);
MovementStatesComponent movementStates = (MovementStatesComponent)commandBuffer.getComponent(ref, this.movementStatesComponentType);
updateBoundingBox(newComponent.getModel(), boundingBox, movementStates);
}
public void onComponentRemoved(@Nonnull Ref<EntityStore> ref, @Nonnull ModelComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
((BoundingBox)commandBuffer.getComponent(ref, this.boundingBoxComponentType)).setBoundingBox(new Box());
}
protected static void updateBoundingBox(@Nonnull Model model, @Nonnull BoundingBox boundingBox, @Nullable MovementStatesComponent movementStatesComponent) {
updateBoundingBox(model, boundingBox, movementStatesComponent != null ? movementStatesComponent.getMovementStates() : null);
}
protected static void updateBoundingBox(@Nonnull Model model, @Nonnull BoundingBox boundingBox, @Nullable MovementStates movementStates) {
Box modelBoundingBox = model.getBoundingBox(movementStates);
if (modelBoundingBox == null) {
modelBoundingBox = new Box();
}
boundingBox.setBoundingBox(modelBoundingBox);
}
}
public static class UpdateCrouchingBoundingBox extends EntityTickingSystem<EntityStore> {
public static final Set<Dependency<EntityStore>> DEPENDENCIES;
private final ComponentType<EntityStore, MovementStatesComponent> movementStatesComponentType = MovementStatesComponent.getComponentType();
private final ComponentType<EntityStore, BoundingBox> boundingBoxComponentType = BoundingBox.getComponentType();
private final ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
private final Query<EntityStore> query;
public UpdateCrouchingBoundingBox() {
this.query = Query.<EntityStore>and(this.movementStatesComponentType, this.boundingBoxComponentType, this.modelComponentType);
}
public boolean isParallel(int archetypeChunkSize, int taskCount) {
return EntityTickingSystem.maybeUseParallel(archetypeChunkSize, taskCount);
}
@Nonnull
public Set<Dependency<EntityStore>> getDependencies() {
return DEPENDENCIES;
}
@Nonnull
public Query<EntityStore> getQuery() {
return this.query;
}
public void tick(float dt, int index, @Nonnull ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
MovementStatesComponent movementStates = (MovementStatesComponent)archetypeChunk.getComponent(index, this.movementStatesComponentType);
MovementStates newMovementStates = movementStates.getMovementStates();
MovementStates sentMovementStates = movementStates.getSentMovementStates();
if (newMovementStates.crouching != sentMovementStates.crouching || newMovementStates.forcedCrouching != sentMovementStates.forcedCrouching) {
Model model = ((ModelComponent)archetypeChunk.getComponent(index, this.modelComponentType)).getModel();
BoundingBox boundingBox = (BoundingBox)archetypeChunk.getComponent(index, this.boundingBoxComponentType);
ModelSystems.UpdateBoundingBox.updateBoundingBox(model, boundingBox, newMovementStates);
}
}
static {
DEPENDENCIES = Collections.singleton(new SystemDependency(Order.BEFORE, MovementStatesSystems.TickingSystem.class));
}
}
public static class PlayerUpdateMovementManager extends RefChangeSystem<EntityStore, ModelComponent> {
private final ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
private final ComponentType<EntityStore, Player> playerComponentType = Player.getComponentType();
private final Set<Dependency<EntityStore>> dependencies;
public PlayerUpdateMovementManager() {
this.dependencies = Set.of(new SystemDependency(Order.AFTER, UpdateBoundingBox.class));
}
@Nonnull
public Query<EntityStore> getQuery() {
return this.playerComponentType;
}
@Nonnull
public Set<Dependency<EntityStore>> getDependencies() {
return this.dependencies;
}
@Nonnull
public ComponentType<EntityStore, ModelComponent> componentType() {
return this.modelComponentType;
}
public void onComponentAdded(@Nonnull Ref<EntityStore> ref, @Nonnull ModelComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
this.updateMovementController(ref, commandBuffer);
}
public void onComponentSet(@Nonnull Ref<EntityStore> ref, ModelComponent oldComponent, @Nonnull ModelComponent newComponent, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
this.updateMovementController(ref, commandBuffer);
}
public void onComponentRemoved(@Nonnull Ref<EntityStore> ref, @Nonnull ModelComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
this.updateMovementController(ref, commandBuffer);
}
private void updateMovementController(@Nonnull Ref<EntityStore> ref, @Nonnull ComponentAccessor<EntityStore> componentAccessor) {
MovementManager movementManagerComponent = (MovementManager)componentAccessor.getComponent(ref, MovementManager.getComponentType());
assert movementManagerComponent != null;
movementManagerComponent.resetDefaultsAndUpdate(ref, componentAccessor);
}
}
public static class AnimationEntityTrackerUpdate extends EntityTickingSystem<EntityStore> {
private final ComponentType<EntityStore, EntityTrackerSystems.Visible> visibleComponentType = EntityTrackerSystems.Visible.getComponentType();
private final ComponentType<EntityStore, ActiveAnimationComponent> activeAnimationComponentType = ActiveAnimationComponent.getComponentType();
private final Query<EntityStore> query;
public AnimationEntityTrackerUpdate() {
this.query = Query.<EntityStore>and(this.visibleComponentType, this.activeAnimationComponentType);
}
@Nullable
public SystemGroup<EntityStore> getGroup() {
return EntityTrackerSystems.QUEUE_UPDATE_GROUP;
}
@Nonnull
public Query<EntityStore> getQuery() {
return this.query;
}
public boolean isParallel(int archetypeChunkSize, int taskCount) {
return EntityTickingSystem.maybeUseParallel(archetypeChunkSize, taskCount);
}
public void tick(float dt, int index, @Nonnull ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
EntityTrackerSystems.Visible visibleComponent = (EntityTrackerSystems.Visible)archetypeChunk.getComponent(index, this.visibleComponentType);
assert visibleComponent != null;
ActiveAnimationComponent activeAnimationComponent = (ActiveAnimationComponent)archetypeChunk.getComponent(index, this.activeAnimationComponentType);
assert activeAnimationComponent != null;
Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
if (activeAnimationComponent.consumeNetworkOutdated()) {
queueUpdatesFor(ref, activeAnimationComponent, visibleComponent.visibleTo);
} else if (!visibleComponent.newlyVisibleTo.isEmpty()) {
queueUpdatesFor(ref, activeAnimationComponent, visibleComponent.newlyVisibleTo);
}
}
private static void queueUpdatesFor(@Nonnull Ref<EntityStore> ref, @Nonnull ActiveAnimationComponent animationComponent, @Nonnull Map<Ref<EntityStore>, EntityTrackerSystems.EntityViewer> visibleTo) {
ComponentUpdate update = new ComponentUpdate();
update.type = ComponentUpdateType.ActiveAnimations;
update.activeAnimations = animationComponent.getActiveAnimations();
for(Map.Entry<Ref<EntityStore>, EntityTrackerSystems.EntityViewer> entry : visibleTo.entrySet()) {
((EntityTrackerSystems.EntityViewer)entry.getValue()).queueUpdate(ref, update);
}
}
}
}