use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.
the class PhasePrinter method printEmptyStackOnCompletion.
static void printEmptyStackOnCompletion(final PhaseContext<@NonNull ?> context) {
if (PhasePrinter.hasPrintedEmptyOnce) {
// because of it.
return;
}
final PrettyPrinter printer = new PrettyPrinter(60).add("Unexpectedly Completing An Empty Stack").centre().hr().addWrapped(60, "Sponge's tracking system is very dependent on knowing when" + " a change to any world takes place, however, we have been told" + " to complete a \"phase\" without having entered any phases." + " This is an error usually on Sponge's part, so a report" + " is required on the issue tracker on GitHub.").hr().add("StackTrace:").add(new Exception()).add("Phase being completed:");
PhasePrinter.PHASE_PRINTER.accept(printer, context);
printer.add();
PhasePrinter.generateVersionInfo(printer);
if (PhasePrinter.IN_DEVELOPMENT) {
printer.print(System.err);
} else {
printer.log(SpongeCommon.logger(), Level.ERROR);
}
if (!SpongeConfigs.getCommon().get().phaseTracker.verbose) {
PhasePrinter.hasPrintedEmptyOnce = true;
}
}
use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.
the class PhasePrinter method printNonEmptyStack.
static void printNonEmptyStack(final PhaseStack stack) {
final PrettyPrinter printer = new PrettyPrinter(60);
printer.add("Phases Not Completed").centre().hr();
printer.add("One or more phases were started but were not properly completed by the end of the server tick. They will be automatically " + "closed, but this is an issue that should be reported to Sponge.");
stack.forEach(data -> PhasePrinter.PHASE_PRINTER.accept(printer, data));
printer.add();
PhasePrinter.generateVersionInfo(printer);
if (PhasePrinter.IN_DEVELOPMENT) {
printer.print(System.err);
} else {
printer.log(SpongeCommon.logger(), Level.ERROR);
}
}
use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.
the class PhasePrinter method printNullSourceBlockWithTile.
static void printNullSourceBlockWithTile(final BlockPos pos, final Block blockIn, final BlockPos otherPos, final ResourceLocation type, final boolean useTile, final NullPointerException e) {
final PhaseTracker instance = PhaseTracker.getInstance();
final PrettyPrinter printer = new PrettyPrinter(60).add("Null Source Block on TileEntity!").centre().hr().addWrapped("Hey, Sponge is saving the game from crashing because a TileEntity " + "is sending out a 'null' Block as it's source (more likely) and " + "attempting to perform a neighbor notification with it. Because " + "this is guaranteed to lead to a crash or a spam of reports, " + "Sponge is going ahead and fixing the issue. The offending Tile " + "is " + type.toString()).add().add("%s : %s", "Source position", pos).add("%s : %s", "Source TileEntity", type).add("%s : %s", "Recovered using TileEntity as Source", useTile).add("%s : %s", "Source Block Recovered", blockIn).add("%s : %s", "Notified Position", otherPos);
PhasePrinter.printPhaseStackWithException(instance.stack, printer, e);
printer.log(SpongeCommon.logger(), Level.WARN);
}
use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.
the class SpongeBlockSnapshot method restore.
@Override
public boolean restore(final boolean force, final BlockChangeFlag flag) {
// TODO - rewrite with the PhaseTracker being the hook or use SpongeImplHooks to do the restore.
final Optional<ServerLevel> optionalWorld = Optional.ofNullable(this.world.get());
if (!optionalWorld.isPresent()) {
return false;
}
final ServerLevel world = optionalWorld.get();
// this way we guarantee an exit.
try (final PhaseContext<?> context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER)) {
context.buildAndSwitch();
final BlockPos pos = VecHelper.toBlockPos(this.pos);
if (!net.minecraft.world.level.Level.isInWorldBounds(pos)) {
// Invalid position. Inline this check
return false;
}
final net.minecraft.world.level.block.state.BlockState current = world.getBlockState(pos);
final net.minecraft.world.level.block.state.BlockState replaced = (net.minecraft.world.level.block.state.BlockState) this.blockState;
if (!force && (current.getBlock() != replaced.getBlock() || current != replaced)) {
return false;
}
// being created during block change removals
if (!current.is(((net.minecraft.world.level.block.state.BlockState) this.blockState).getBlock())) {
world.removeBlockEntity(pos);
}
world.setBlock(pos, replaced, BlockChangeFlagManager.andNotifyClients(flag).getRawFlag());
if (this.compound != null) {
@Nullable BlockEntity te = world.getBlockEntity(pos);
if (te != null) {
te.load((net.minecraft.world.level.block.state.BlockState) this.blockState, this.compound);
} else {
// In cases like this, we need to directly just say "fuck it" and deserialize from the compound directly.
try {
te = BlockEntity.loadStatic((net.minecraft.world.level.block.state.BlockState) this.blockState, this.compound);
if (te != null) {
world.getChunk(pos).setBlockEntity(pos, te);
}
} catch (final Exception e) {
// Seriously? The mod should be broken then.
final PrettyPrinter printer = new PrettyPrinter(60).add("Unable to restore").centre().hr().add("A mod is not correctly deserializing a TileEntity that is being restored. ").addWrapped(60, "Note that this is not the fault of Sponge. Sponge is understanding that " + "a block is supposed to have a TileEntity, but the mod is breaking the contract" + "on how to re-create the tile entity. Please open an issue with the offending mod.").add("Here's the provided compound:");
printer.add();
try {
printer.addWrapped(80, "%s : %s", "This compound", this.compound);
} catch (final Throwable error) {
printer.addWrapped(80, "Unable to get the string of this compound. Printing out some of the entries to better assist");
}
printer.add().add("Desired World: " + this.worldKey).add("Position: " + this.pos).add("Desired BlockState: " + this.blockState);
printer.add();
printer.log(SpongeCommon.logger(), Level.ERROR);
// I mean, I guess. the block was set up, but not the tile entity.
return true;
}
}
if (te != null) {
te.setChanged();
}
}
// Finally, mark the location as being updated.
world.getChunkSource().blockChanged(pos);
return true;
}
}
use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.
the class ChunkMapMixin_Tracker method tracker$startLoad.
@Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;runPostLoad()V"), slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;setFullStatus(Ljava/util/function/Supplier;)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addAllPendingBlockEntities(Ljava/util/Collection;)V")))
private void tracker$startLoad(final LevelChunk chunk) {
chunk.runPostLoad();
final boolean isFake = ((LevelBridge) chunk.getLevel()).bridge$isFake();
if (isFake) {
return;
}
if (!PhaseTracker.SERVER.onSidedThread()) {
new PrettyPrinter(60).add("Illegal Async Chunk Load").centre().hr().addWrapped("Sponge relies on knowing when chunks are being loaded as chunks add entities" + " to the parented world for management. These operations are generally not" + " threadsafe and shouldn't be considered a \"Sponge bug \". Adding/removing" + " entities from another thread to the world is never ok.").add().add(" %s : %s", "Chunk Pos", chunk.getPos().toString()).add().add(new Exception("Async Chunk Load Detected")).log(SpongeCommon.logger(), Level.ERROR);
return;
}
if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) {
return;
}
GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.getInstance()).source(chunk).world((ServerLevel) chunk.getLevel()).chunk(chunk).buildAndSwitch();
}
Aggregations