package com.hypixel.hytale.builtin.buildertools.prefabeditor;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.component.AddReason;
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.math.codec.Vector3iArrayCodec;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolShowAnchor;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.entity.entities.BlockEntity;
import com.hypixel.hytale.server.core.io.PacketHandler;
import com.hypixel.hytale.server.core.modules.entity.component.EntityScaleComponent;
import com.hypixel.hytale.server.core.modules.entity.component.Intangible;
import com.hypixel.hytale.server.core.modules.time.TimeResource;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class PrefabEditingMetadata {
private static final float PREFAB_ANCHOR_ENTITY_SCALE = 2.1F;
@Nonnull
public static final BuilderCodec<PrefabEditingMetadata> CODEC;
private UUID uuid;
private Path prefabPath;
private Vector3i minPoint;
private Vector3i maxPoint;
private Vector3i anchorPoint;
private Vector3i pastePosition;
@Nullable
private UUID anchorEntityUuid;
private Vector3i anchorEntityPosition;
private Vector3i originalFileAnchor;
private boolean dirty = false;
private PrefabEditingMetadata() {
}
public PrefabEditingMetadata(@Nonnull Path prefabPath, @Nonnull Vector3i minPoint, @Nonnull Vector3i maxPoint, @Nonnull Vector3i anchorPoint, @Nonnull Vector3i pastePosition, @Nonnull World world) {
this.prefabPath = prefabPath;
this.minPoint = minPoint;
this.maxPoint = maxPoint;
if (minPoint.x > maxPoint.x) {
throw new IllegalStateException("minX must be less than or equal to maxX: " + String.valueOf(prefabPath));
} else if (minPoint.y > maxPoint.y) {
throw new IllegalStateException("minY must be less than or equal to maxY: " + String.valueOf(prefabPath));
} else if (minPoint.z > maxPoint.z) {
throw new IllegalStateException("minZ must be less than or equal to maxZ: " + String.valueOf(prefabPath));
} else {
this.uuid = UUID.randomUUID();
this.anchorPoint = anchorPoint;
this.pastePosition = pastePosition;
this.originalFileAnchor = new Vector3i(anchorPoint.x - pastePosition.x, anchorPoint.y - pastePosition.y, anchorPoint.z - pastePosition.z);
this.createAnchorEntityAt(pastePosition, world);
}
}
private void createAnchorEntityAt(@Nonnull Vector3i position, @Nonnull World world) {
this.anchorEntityPosition = position.clone();
Store<EntityStore> store = world.getEntityStore().getStore();
if (this.anchorEntityUuid != null) {
Ref<EntityStore> entityReference = ((EntityStore)store.getExternalData()).getRefFromUUID(this.anchorEntityUuid);
if (entityReference != null && entityReference.isValid()) {
world.execute(() -> store.removeEntity(entityReference, RemoveReason.REMOVE));
}
}
TimeResource timeResource = (TimeResource)store.getResource(TimeResource.getResourceType());
Holder<EntityStore> blockEntityHolder = BlockEntity.assembleDefaultBlockEntity(timeResource, "Editor_Anchor", position.toVector3d().add(0.5, 0.0, 0.5));
blockEntityHolder.addComponent(Intangible.getComponentType(), Intangible.INSTANCE);
blockEntityHolder.addComponent(PrefabAnchor.getComponentType(), PrefabAnchor.INSTANCE);
blockEntityHolder.addComponent(EntityScaleComponent.getComponentType(), new EntityScaleComponent(2.1F));
this.anchorEntityUuid = ((UUIDComponent)blockEntityHolder.ensureAndGetComponent(UUIDComponent.getComponentType())).getUuid();
world.execute(() -> store.addEntity(blockEntityHolder, AddReason.SPAWN));
}
public void setPrefabPath(@Nonnull Path prefabPath) {
this.prefabPath = prefabPath;
}
public void setAnchorPoint(@Nonnull Vector3i newEntityPosition, @Nonnull World world) {
int deltaX = newEntityPosition.x - this.anchorEntityPosition.x;
int deltaY = newEntityPosition.y - this.anchorEntityPosition.y;
int deltaZ = newEntityPosition.z - this.anchorEntityPosition.z;
this.anchorPoint = new Vector3i(this.anchorPoint.x + deltaX, this.anchorPoint.y + deltaY, this.anchorPoint.z + deltaZ);
this.createAnchorEntityAt(newEntityPosition, world);
}
public void recreateAnchorEntity(@Nonnull World world) {
if (this.anchorEntityPosition != null) {
this.createAnchorEntityAt(this.anchorEntityPosition, world);
}
}
public void sendAnchorHighlightingPacket(@Nonnull PacketHandler displayTo) {
displayTo.writeNoCache(new BuilderToolShowAnchor(this.anchorEntityPosition.x, this.anchorEntityPosition.y, this.anchorEntityPosition.z));
}
public boolean isLocationWithinPrefabBoundingBox(@Nonnull Vector3i location) {
return location.x >= this.getMinPoint().x && location.x <= this.getMaxPoint().x && location.y >= this.getMinPoint().y && location.y <= this.getMaxPoint().y && location.z >= this.getMinPoint().z && location.z <= this.getMaxPoint().z;
}
void setMinPoint(Vector3i minPoint) {
this.minPoint = minPoint;
}
void setMaxPoint(Vector3i maxPoint) {
this.maxPoint = maxPoint;
}
public Vector3i getAnchorPoint() {
return this.anchorPoint;
}
public Vector3i getPastePosition() {
return this.pastePosition;
}
public Vector3i getOriginalFileAnchor() {
return this.originalFileAnchor;
}
public Path getPrefabPath() {
return this.prefabPath;
}
public Vector3i getMinPoint() {
return this.minPoint;
}
public Vector3i getMaxPoint() {
return this.maxPoint;
}
@Nullable
public UUID getAnchorEntityUuid() {
return this.anchorEntityUuid;
}
public Vector3i getAnchorEntityPosition() {
return this.anchorEntityPosition;
}
public UUID getUuid() {
return this.uuid;
}
public boolean isDirty() {
return this.dirty;
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
public boolean isReadOnly() {
return this.prefabPath != null && this.prefabPath.getFileSystem() != FileSystems.getDefault();
}
static {
CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.builder(PrefabEditingMetadata.class, PrefabEditingMetadata::new).append(new KeyedCodec("Path", Codec.PATH), (o, path) -> o.prefabPath = path, (o) -> o.prefabPath).add()).append(new KeyedCodec("MinPoint", new Vector3iArrayCodec()), (o, minPoint) -> o.minPoint = minPoint, (o) -> o.minPoint).add()).append(new KeyedCodec("MaxPoint", new Vector3iArrayCodec()), (o, maxPoint) -> o.maxPoint = maxPoint, (o) -> o.maxPoint).add()).append(new KeyedCodec("AnchorPoint", new Vector3iArrayCodec()), (o, anchorPoint) -> o.anchorPoint = anchorPoint, (o) -> o.anchorPoint).add()).append(new KeyedCodec("PastePosition", new Vector3iArrayCodec()), (o, pastePosition) -> o.pastePosition = pastePosition, (o) -> o.pastePosition).add()).append(new KeyedCodec("AnchorEntityUuid", Codec.UUID_STRING, false), (o, anchorEntityUuid) -> o.anchorEntityUuid = anchorEntityUuid, (o) -> o.anchorEntityUuid).add()).append(new KeyedCodec("AnchorEntityPosition", new Vector3iArrayCodec(), false), (o, anchorEntityPosition) -> o.anchorEntityPosition = anchorEntityPosition, (o) -> o.anchorEntityPosition).add()).append(new KeyedCodec("Uuid", Codec.UUID_STRING), (o, uuid) -> o.uuid = uuid, (o) -> o.uuid).add()).append(new KeyedCodec("Dirty", Codec.BOOLEAN, true), (o, dirty) -> o.dirty = dirty, (o) -> o.dirty).add()).build();
}
}