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