231 lines
6.8 KiB
Java
231 lines
6.8 KiB
Java
package net.minecraft.world.level;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Date;
|
|
import net.minecraft.CrashReport;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.CrashReportDetail;
|
|
import net.minecraft.ReportedException;
|
|
import net.minecraft.commands.CommandSource;
|
|
import net.minecraft.commands.CommandSourceStack;
|
|
import net.minecraft.core.HolderLookup;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.NbtOps;
|
|
import net.minecraft.nbt.Tag;
|
|
import net.minecraft.network.chat.CommonComponents;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.chat.ComponentSerialization;
|
|
import net.minecraft.resources.RegistryOps;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.util.StringUtil;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public abstract class BaseCommandBlock implements CommandSource {
|
|
/**
|
|
* The formatting for the timestamp on commands run.
|
|
*/
|
|
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
|
|
private static final Component DEFAULT_NAME = Component.literal("@");
|
|
private static final int NO_LAST_EXECUTION = -1;
|
|
private long lastExecution = -1L;
|
|
private boolean updateLastExecution = true;
|
|
/**
|
|
* The number of successful commands run. (used for redstone output)
|
|
*/
|
|
private int successCount;
|
|
private boolean trackOutput = true;
|
|
/**
|
|
* The previously run command.
|
|
*/
|
|
@Nullable
|
|
private Component lastOutput;
|
|
/**
|
|
* The command stored in the command block.
|
|
*/
|
|
private String command = "";
|
|
@Nullable
|
|
private Component customName;
|
|
|
|
/**
|
|
* Returns the {@code successCount} int.
|
|
*/
|
|
public int getSuccessCount() {
|
|
return this.successCount;
|
|
}
|
|
|
|
public void setSuccessCount(int successCount) {
|
|
this.successCount = successCount;
|
|
}
|
|
|
|
/**
|
|
* Returns the lastOutput.
|
|
*/
|
|
public Component getLastOutput() {
|
|
return this.lastOutput == null ? CommonComponents.EMPTY : this.lastOutput;
|
|
}
|
|
|
|
public CompoundTag save(CompoundTag tag, HolderLookup.Provider levelRegistry) {
|
|
tag.putString("Command", this.command);
|
|
tag.putInt("SuccessCount", this.successCount);
|
|
RegistryOps<Tag> registryOps = levelRegistry.createSerializationContext(NbtOps.INSTANCE);
|
|
tag.storeNullable("CustomName", ComponentSerialization.CODEC, registryOps, this.customName);
|
|
tag.putBoolean("TrackOutput", this.trackOutput);
|
|
if (this.trackOutput) {
|
|
tag.storeNullable("LastOutput", ComponentSerialization.CODEC, registryOps, this.lastOutput);
|
|
}
|
|
|
|
tag.putBoolean("UpdateLastExecution", this.updateLastExecution);
|
|
if (this.updateLastExecution && this.lastExecution != -1L) {
|
|
tag.putLong("LastExecution", this.lastExecution);
|
|
}
|
|
|
|
return tag;
|
|
}
|
|
|
|
public void load(CompoundTag tag, HolderLookup.Provider levelRegistry) {
|
|
this.command = tag.getStringOr("Command", "");
|
|
this.successCount = tag.getIntOr("SuccessCount", 0);
|
|
this.setCustomName(BlockEntity.parseCustomNameSafe(tag.get("CustomName"), levelRegistry));
|
|
this.trackOutput = tag.getBooleanOr("TrackOutput", true);
|
|
if (this.trackOutput) {
|
|
this.lastOutput = BlockEntity.parseCustomNameSafe(tag.get("LastOutput"), levelRegistry);
|
|
} else {
|
|
this.lastOutput = null;
|
|
}
|
|
|
|
this.updateLastExecution = tag.getBooleanOr("UpdateLastExecution", true);
|
|
if (this.updateLastExecution) {
|
|
this.lastExecution = tag.getLongOr("LastExecution", -1L);
|
|
} else {
|
|
this.lastExecution = -1L;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the command.
|
|
*/
|
|
public void setCommand(String command) {
|
|
this.command = command;
|
|
this.successCount = 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the command of the command block.
|
|
*/
|
|
public String getCommand() {
|
|
return this.command;
|
|
}
|
|
|
|
public boolean performCommand(Level level) {
|
|
if (level.isClientSide || level.getGameTime() == this.lastExecution) {
|
|
return false;
|
|
} else if ("Searge".equalsIgnoreCase(this.command)) {
|
|
this.lastOutput = Component.literal("#itzlipofutzli");
|
|
this.successCount = 1;
|
|
return true;
|
|
} else {
|
|
this.successCount = 0;
|
|
MinecraftServer minecraftServer = this.getLevel().getServer();
|
|
if (minecraftServer.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) {
|
|
try {
|
|
this.lastOutput = null;
|
|
CommandSourceStack commandSourceStack = this.createCommandSourceStack().withCallback((bl, i) -> {
|
|
if (bl) {
|
|
this.successCount++;
|
|
}
|
|
});
|
|
minecraftServer.getCommands().performPrefixedCommand(commandSourceStack, this.command);
|
|
} catch (Throwable var6) {
|
|
CrashReport crashReport = CrashReport.forThrowable(var6, "Executing command block");
|
|
CrashReportCategory crashReportCategory = crashReport.addCategory("Command to be executed");
|
|
crashReportCategory.setDetail("Command", this::getCommand);
|
|
crashReportCategory.setDetail("Name", (CrashReportDetail<String>)(() -> this.getName().getString()));
|
|
throw new ReportedException(crashReport);
|
|
}
|
|
}
|
|
|
|
if (this.updateLastExecution) {
|
|
this.lastExecution = level.getGameTime();
|
|
} else {
|
|
this.lastExecution = -1L;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public Component getName() {
|
|
return this.customName != null ? this.customName : DEFAULT_NAME;
|
|
}
|
|
|
|
@Nullable
|
|
public Component getCustomName() {
|
|
return this.customName;
|
|
}
|
|
|
|
public void setCustomName(@Nullable Component customName) {
|
|
this.customName = customName;
|
|
}
|
|
|
|
@Override
|
|
public void sendSystemMessage(Component component) {
|
|
if (this.trackOutput) {
|
|
this.lastOutput = Component.literal("[" + TIME_FORMAT.format(new Date()) + "] ").append(component);
|
|
this.onUpdated();
|
|
}
|
|
}
|
|
|
|
public abstract ServerLevel getLevel();
|
|
|
|
public abstract void onUpdated();
|
|
|
|
public void setLastOutput(@Nullable Component lastOutputMessage) {
|
|
this.lastOutput = lastOutputMessage;
|
|
}
|
|
|
|
public void setTrackOutput(boolean shouldTrackOutput) {
|
|
this.trackOutput = shouldTrackOutput;
|
|
}
|
|
|
|
public boolean isTrackOutput() {
|
|
return this.trackOutput;
|
|
}
|
|
|
|
public InteractionResult usedBy(Player player) {
|
|
if (!player.canUseGameMasterBlocks()) {
|
|
return InteractionResult.PASS;
|
|
} else {
|
|
if (player.getCommandSenderWorld().isClientSide) {
|
|
player.openMinecartCommandBlock(this);
|
|
}
|
|
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
}
|
|
|
|
public abstract Vec3 getPosition();
|
|
|
|
public abstract CommandSourceStack createCommandSourceStack();
|
|
|
|
@Override
|
|
public boolean acceptsSuccess() {
|
|
return this.getLevel().getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK) && this.trackOutput;
|
|
}
|
|
|
|
@Override
|
|
public boolean acceptsFailure() {
|
|
return this.trackOutput;
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldInformAdmins() {
|
|
return this.getLevel().getGameRules().getBoolean(GameRules.RULE_COMMANDBLOCKOUTPUT);
|
|
}
|
|
|
|
public abstract boolean isValid();
|
|
}
|