package com.hypixel.hytale.builtin.adventure.objectives.task; import com.hypixel.hytale.builtin.adventure.objectives.Objective; import com.hypixel.hytale.builtin.adventure.objectives.config.task.ObjectiveTaskAsset; import com.hypixel.hytale.builtin.adventure.objectives.config.task.ReachLocationTaskAsset; import com.hypixel.hytale.builtin.adventure.objectives.markers.reachlocation.ReachLocationMarker; import com.hypixel.hytale.builtin.adventure.objectives.transaction.TransactionRecord; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.math.vector.Transform; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.protocol.packets.worldmap.MapMarker; import com.hypixel.hytale.server.core.entity.UUIDComponent; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.util.PositionUtil; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ReachLocationTask extends ObjectiveTask { public static final BuilderCodec CODEC = BuilderCodec.builder(ReachLocationTask.class, ReachLocationTask::new, BASE_CODEC) .append( new KeyedCodec<>("Completed", Codec.BOOLEAN), (reachLocationTask, aBoolean) -> reachLocationTask.completed = aBoolean, reachLocationTask -> reachLocationTask.completed ) .add() .append( new KeyedCodec<>("MarkerLoaded", Codec.BOOLEAN), (reachLocationTask, transactionRecord) -> reachLocationTask.markerLoaded = transactionRecord, reachLocationTask -> reachLocationTask.markerLoaded ) .add() .build(); @Nonnull public static String MARKER_ICON = "Home.png"; private static final ComponentType TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType(); private static final ComponentType REACH_LOCATION_MARKER_COMPONENT_TYPE = ReachLocationMarker.getComponentType(); private boolean completed; private boolean markerLoaded; public ReachLocationTask(@Nonnull ObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) { super(asset, taskSetIndex, taskIndex); } protected ReachLocationTask() { } @Override public boolean checkCompletion() { return this.completed; } @Nonnull public ReachLocationTaskAsset getAsset() { return (ReachLocationTaskAsset)this.asset; } @Nonnull private String getMarkerId(@Nonnull Objective objective) { return String.format("ReachLocation_%s_%d", objective.getObjectiveUUID(), this.taskIndex); } @Nullable @Override protected TransactionRecord[] setup0(@Nonnull Objective objective, @Nonnull World world, @Nonnull Store store) { if (!this.markers.isEmpty()) { return null; } else { String targetLocationId = this.getAsset().getTargetLocationId(); List> reachLocationMarkerEntities = new ObjectArrayList(); store.forEachChunk(REACH_LOCATION_MARKER_COMPONENT_TYPE, (archetypeChunk, componentStoreCommandBuffer) -> { for (int index = 0; index < archetypeChunk.size(); index++) { ReachLocationMarker reachLocationMarkerComponent = archetypeChunk.getComponent(index, REACH_LOCATION_MARKER_COMPONENT_TYPE); if (reachLocationMarkerComponent != null && reachLocationMarkerComponent.getMarkerId().equals(targetLocationId)) { reachLocationMarkerEntities.add(archetypeChunk.getReferenceTo(index)); } } }); if (!reachLocationMarkerEntities.isEmpty()) { Vector3d currentLocation = objective.getPosition(store); Ref closestMarker = reachLocationMarkerEntities.getFirst(); TransformComponent closestMarkerTransformComponent = store.getComponent(closestMarker, TRANSFORM_COMPONENT_TYPE); assert closestMarkerTransformComponent != null; ReachLocationMarker closestMarkerReachComponent = store.getComponent(closestMarker, REACH_LOCATION_MARKER_COMPONENT_TYPE); assert closestMarkerReachComponent != null; Vector3d closestPosition = closestMarkerTransformComponent.getPosition(); double shortestDistance = closestPosition.distanceSquaredTo(currentLocation); String closestLocationName = closestMarkerReachComponent.getLocationName(); for (int i = 1; i < reachLocationMarkerEntities.size(); i++) { Ref markerEntityReference = reachLocationMarkerEntities.get(i); TransformComponent markerTransformComponent = store.getComponent(markerEntityReference, TRANSFORM_COMPONENT_TYPE); assert markerTransformComponent != null; ReachLocationMarker markerReachLocationComponent = store.getComponent(markerEntityReference, REACH_LOCATION_MARKER_COMPONENT_TYPE); assert markerReachLocationComponent != null; Vector3d pos = markerTransformComponent.getPosition(); double distance = pos.distanceSquaredTo(currentLocation); String locationName = markerReachLocationComponent.getLocationName(); if (distance < shortestDistance && locationName != null) { shortestDistance = distance; closestPosition = pos; closestLocationName = locationName; } } if (closestLocationName != null) { this.addMarker( new MapMarker( this.getMarkerId(objective), closestLocationName, MARKER_ICON, PositionUtil.toTransformPacket(new Transform(closestPosition)), null ) ); this.markerLoaded = true; return null; } } return null; } } public void setupMarker( @Nonnull Objective objective, @Nonnull ReachLocationMarker locationMarkerEntity, @Nonnull Vector3d position, @Nonnull CommandBuffer commandBuffer ) { if (!this.markerLoaded) { String markerId = locationMarkerEntity.getMarkerId(); if (markerId.equals(this.getAsset().getTargetLocationId())) { String locationName = locationMarkerEntity.getLocationName(); if (locationName != null) { this.addMarker( new MapMarker(this.getMarkerId(objective), locationName, MARKER_ICON, PositionUtil.toTransformPacket(new Transform(position)), null) ); this.markerLoaded = true; } } } } @Nonnull public com.hypixel.hytale.protocol.ObjectiveTask toPacket(@Nonnull Objective objective) { com.hypixel.hytale.protocol.ObjectiveTask packet = new com.hypixel.hytale.protocol.ObjectiveTask(); packet.taskDescriptionKey = this.asset.getDescriptionKey(objective.getObjectiveId(), this.taskSetIndex, this.taskIndex); packet.currentCompletion = this.completed ? 1 : 0; packet.completionNeeded = 1; return packet; } public void onPlayerReachLocationMarker( @Nonnull Store store, @Nonnull Ref ref, @Nonnull String locationMarkerId, @Nonnull Objective objective ) { if (locationMarkerId.equals(this.getAsset().getTargetLocationId())) { UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType()); assert uuidComponent != null; if (objective.getActivePlayerUUIDs().contains(uuidComponent.getUuid())) { if (this.areTaskConditionsFulfilled(store, ref, null)) { this.completed = true; objective.markDirty(); this.sendUpdateObjectiveTaskPacket(objective); this.consumeTaskConditions(store, ref, objective.getActivePlayerUUIDs()); this.complete(objective, store); objective.checkTaskSetCompletion(store); } } } } @Nonnull @Override public String toString() { return "ReachLocationTask{completed=" + this.completed + "} " + super.toString(); } }