hytale-server/com/hypixel/hytale/builtin/adventure/objectives/task/ObjectiveTask.java

343 lines
13 KiB
Java

package com.hypixel.hytale.builtin.adventure.objectives.task;
import com.hypixel.hytale.builtin.adventure.objectives.Objective;
import com.hypixel.hytale.builtin.adventure.objectives.ObjectivePlugin;
import com.hypixel.hytale.builtin.adventure.objectives.config.task.ObjectiveTaskAsset;
import com.hypixel.hytale.builtin.adventure.objectives.config.taskcondition.TaskConditionAsset;
import com.hypixel.hytale.builtin.adventure.objectives.transaction.TransactionRecord;
import com.hypixel.hytale.builtin.adventure.objectives.transaction.TransactionUtil;
import com.hypixel.hytale.builtin.adventure.objectives.transaction.WorldTransactionRecord;
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.lookup.CodecMapCodec;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.event.EventRegistry;
import com.hypixel.hytale.math.vector.Transform;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.protocol.packets.assets.UpdateObjectiveTask;
import com.hypixel.hytale.protocol.packets.worldmap.MapMarker;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.codec.ProtocolCodecs;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.io.NetworkSerializer;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.Universe;
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.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class ObjectiveTask implements NetworkSerializer<Objective, com.hypixel.hytale.protocol.ObjectiveTask> {
public static final CodecMapCodec<ObjectiveTask> CODEC = new CodecMapCodec<>("Type");
public static final BuilderCodec<ObjectiveTask> BASE_CODEC = BuilderCodec.abstractBuilder(ObjectiveTask.class)
.append(
new KeyedCodec<>("Task", ObjectiveTaskAsset.CODEC),
(aObjectiveTask, objectiveTaskAsset) -> aObjectiveTask.asset = objectiveTaskAsset,
aObjectiveTask -> aObjectiveTask.asset
)
.add()
.append(
new KeyedCodec<>("Complete", Codec.BOOLEAN),
(aObjectiveTask, aBoolean) -> aObjectiveTask.complete = aBoolean,
aObjectiveTask -> aObjectiveTask.complete
)
.add()
.append(
new KeyedCodec<>("TransactionRecords", new ArrayCodec<>(TransactionRecord.CODEC, TransactionRecord[]::new)),
(objectiveTask, transactionRecords) -> objectiveTask.serializedTransactionRecords = transactionRecords,
objectiveTask -> objectiveTask.serializedTransactionRecords
)
.add()
.append(
new KeyedCodec<>("TaskIndex", Codec.INTEGER), (objectiveTask, integer) -> objectiveTask.taskIndex = integer, objectiveTask -> objectiveTask.taskIndex
)
.add()
.append(new KeyedCodec<>("Markers", ProtocolCodecs.MARKER_ARRAY), (objectiveTask, markers) -> {
objectiveTask.markers.clear();
Collections.addAll(objectiveTask.markers, markers);
}, objectiveTask -> objectiveTask.markers.toArray(MapMarker[]::new))
.add()
.append(
new KeyedCodec<>("TaskSetIndex", Codec.INTEGER),
(objectiveTask, integer) -> objectiveTask.taskSetIndex = integer,
objectiveTask -> objectiveTask.taskSetIndex
)
.add()
.build();
protected ObjectiveTaskAsset asset;
protected boolean complete = false;
@Nullable
protected EventRegistry eventRegistry;
@Nullable
protected TransactionRecord[] serializedTransactionRecords;
@Nullable
protected TransactionRecord[] nonSerializedTransactionRecords;
protected int taskIndex;
@Nonnull
protected List<MapMarker> markers = new ObjectArrayList();
protected int taskSetIndex;
protected ObjectiveTaskRef<? extends ObjectiveTask> taskRef;
public ObjectiveTask(@Nonnull ObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) {
this.asset = asset;
this.taskIndex = taskIndex;
this.taskSetIndex = taskSetIndex;
}
protected ObjectiveTask() {
}
@Nonnull
public ObjectiveTaskAsset getAsset() {
return this.asset;
}
public void setAsset(@Nonnull ObjectiveTaskAsset asset) {
this.asset = asset;
}
public boolean isComplete() {
return this.complete;
}
@Nullable
public TransactionRecord[] getSerializedTransactionRecords() {
return this.serializedTransactionRecords;
}
@Nullable
public TransactionRecord[] getNonSerializedTransactionRecords() {
return this.nonSerializedTransactionRecords;
}
@Nonnull
public Message getInfoMessage(@Nonnull Objective objective) {
return Message.translation(this.asset.getDescriptionKey(objective.getObjectiveId(), this.taskSetIndex, this.taskIndex));
}
@Nonnull
public List<MapMarker> getMarkers() {
return this.markers;
}
public void addMarker(@Nonnull MapMarker marker) {
this.markers.add(marker);
}
public void removeMarker(String id) {
for (MapMarker marker : this.markers) {
if (marker.id.equals(id)) {
this.markers.remove(marker);
return;
}
}
}
public abstract boolean checkCompletion();
@Nullable
protected abstract TransactionRecord[] setup0(@Nonnull Objective var1, @Nonnull World var2, @Nonnull Store<EntityStore> var3);
@Nullable
public final TransactionRecord[] setup(@Nonnull Objective objective, @Nonnull Store<EntityStore> store) {
World world = Universe.get().getWorld(objective.getWorldUUID());
if (world == null) {
String transactionMessage = "This World doesn't exist in this Universe: " + objective.getWorldUUID();
return TransactionRecord.appendFailedTransaction(this.nonSerializedTransactionRecords, new WorldTransactionRecord(), transactionMessage);
} else if (this.eventRegistry != null) {
throw new IllegalStateException("ObjectiveTask.eventRegistry is not null, setup() shouldn't be run more than once!");
} else {
this.eventRegistry = new EventRegistry(new CopyOnWriteArrayList<>(), () -> true, null, world.getEventRegistry());
Vector3i[] mapMarkerPositions = this.asset.getMapMarkers();
if (mapMarkerPositions != null) {
String objectiveUUIDString = objective.getObjectiveUUID().toString();
for (int i = 0; i < mapMarkerPositions.length; i++) {
Vector3i mapMarkerPosition = mapMarkerPositions[i];
this.addMarker(
new MapMarker(
"ObjectiveMarker_" + objectiveUUIDString + "_" + i,
"Objective",
"Home.png",
PositionUtil.toTransformPacket(new Transform(mapMarkerPosition)),
null
)
);
}
}
this.taskRef = new ObjectiveTaskRef<>(objective.getObjectiveUUID(), this);
this.registerTaskRef();
TransactionRecord[] transactionRecords = this.setup0(objective, world, store);
if (transactionRecords == null) {
return null;
} else {
int serializedCount = 0;
for (TransactionRecord transactionRecord : transactionRecords) {
if (transactionRecord.shouldBeSerialized()) {
serializedCount++;
}
}
this.serializedTransactionRecords = new TransactionRecord[serializedCount];
this.nonSerializedTransactionRecords = new TransactionRecord[transactionRecords.length - serializedCount];
int serializedIndex = 0;
int nonSerializedIndex = 0;
for (TransactionRecord transactionRecordx : transactionRecords) {
if (transactionRecordx.shouldBeSerialized()) {
this.serializedTransactionRecords[serializedIndex++] = transactionRecordx;
} else {
this.nonSerializedTransactionRecords[nonSerializedIndex++] = transactionRecordx;
}
}
return transactionRecords;
}
}
}
public void complete(@Nonnull Objective objective, @Nullable ComponentAccessor<EntityStore> componentAccessor) {
if (!this.complete) {
if (componentAccessor != null) {
objective.forEachParticipant((participantReference, message) -> {
Player playerComponent = componentAccessor.getComponent(participantReference, Player.getComponentType());
if (playerComponent != null) {
playerComponent.sendMessage(message);
}
}, Message.translation("server.modules.objective.task.completed").insert(this.getInfoMessage(objective)));
}
this.markers.clear();
this.complete = true;
this.completeTransactionRecords();
}
}
private void registerTaskRef() {
ObjectivePlugin.get().getObjectiveDataStore().addTaskRef(this.taskRef);
}
private void unregisterTaskRef() {
ObjectivePlugin.get().getObjectiveDataStore().removeTaskRef(this.taskRef);
}
public void completeTransactionRecords() {
TransactionUtil.completeAll(this.serializedTransactionRecords);
this.serializedTransactionRecords = null;
TransactionUtil.completeAll(this.nonSerializedTransactionRecords);
this.nonSerializedTransactionRecords = null;
this.shutdownEventRegistry();
this.unregisterTaskRef();
}
public void revertTransactionRecords() {
TransactionUtil.revertAll(this.serializedTransactionRecords);
this.serializedTransactionRecords = null;
TransactionUtil.revertAll(this.nonSerializedTransactionRecords);
this.nonSerializedTransactionRecords = null;
this.shutdownEventRegistry();
this.unregisterTaskRef();
}
public void unloadTransactionRecords() {
TransactionUtil.unloadAll(this.serializedTransactionRecords);
this.serializedTransactionRecords = null;
TransactionUtil.unloadAll(this.nonSerializedTransactionRecords);
this.nonSerializedTransactionRecords = null;
this.shutdownEventRegistry();
this.unregisterTaskRef();
}
private void shutdownEventRegistry() {
if (this.eventRegistry != null) {
this.eventRegistry.shutdown();
this.eventRegistry = null;
}
}
public void assetChanged(@Nonnull Objective objective) {
if (!this.complete) {
if (this.checkCompletion()) {
this.consumeTaskConditions(null, null, objective.getActivePlayerUUIDs());
this.complete(objective, null);
}
}
}
public void sendUpdateObjectiveTaskPacket(@Nonnull Objective objective) {
UpdateObjectiveTask updateObjectiveTaskPacket = new UpdateObjectiveTask(objective.getObjectiveUUID(), this.taskIndex, this.toPacket(objective));
Universe universe = Universe.get();
for (UUID playerUUID : objective.getActivePlayerUUIDs()) {
PlayerRef player = universe.getPlayer(playerUUID);
if (player != null) {
player.getPacketHandler().writeNoCache(updateObjectiveTaskPacket);
}
}
}
public boolean areTaskConditionsFulfilled(
@Nullable ComponentAccessor<EntityStore> componentAccessor, @Nullable Ref<EntityStore> ref, @Nullable Set<UUID> objectivePlayers
) {
TaskConditionAsset[] taskConditions = this.asset.getTaskConditions();
if (taskConditions == null) {
return true;
} else {
for (TaskConditionAsset taskCondition : taskConditions) {
if (!taskCondition.isConditionFulfilled(componentAccessor, ref, objectivePlayers)) {
return false;
}
}
return true;
}
}
public void consumeTaskConditions(
@Nullable ComponentAccessor<EntityStore> componentAccessor, @Nullable Ref<EntityStore> ref, @Nonnull Set<UUID> objectivePlayers
) {
TaskConditionAsset[] taskConditions = this.asset.getTaskConditions();
if (taskConditions != null) {
for (TaskConditionAsset taskCondition : taskConditions) {
taskCondition.consumeCondition(componentAccessor, ref, objectivePlayers);
}
}
}
@Nonnull
@Override
public String toString() {
return "ObjectiveTask{asset="
+ this.asset
+ ", complete="
+ this.complete
+ ", eventRegistry="
+ this.eventRegistry
+ ", serializedTransactionRecords="
+ Arrays.toString((Object[])this.serializedTransactionRecords)
+ ", nonSerializedTransactionRecords="
+ Arrays.toString((Object[])this.nonSerializedTransactionRecords)
+ ", taskIndex="
+ this.taskIndex
+ ", markers="
+ this.markers
+ ", taskSetIndex="
+ this.taskSetIndex
+ "}";
}
}