minecraft-src/net/minecraft/world/level/BaseCommandBlock.java
2025-07-04 03:45:38 +03:00

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();
}