use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.
the class ChunkMapMixin_Tracker method tracker$wrapUnpackTicks.
@Redirect(method = "lambda$null$36(Lnet/minecraft/world/level/chunk/ChunkAccess;)Lnet/minecraft/world/level/chunk/LevelChunk;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;unpackTicks()V"))
private static void tracker$wrapUnpackTicks(final LevelChunk chunk) {
if (!PhaseTracker.SERVER.onSidedThread()) {
new PrettyPrinter(60).add("Illegal Async Chunk Unpacking").centre().hr().addWrapped("Someone is attempting to unpack chunk scheduled updates while off the main thread, this is" + "generally unsupported and Sponge would appreciate a report about this. Please attach " + "the generated classes output as a zip file after enabling -Dmixin.debug.export=true " + "and request triage support on discord. Do NOT report as an issue on GitHub.").add().add(" %s : %s", "Chunk Pos", chunk.getPos().toString()).add().add(new Exception("Async Chunk Scheduling Detected")).log(SpongeCommon.logger(), Level.ERROR);
return;
}
if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_LOADING) {
return;
}
try (final PhaseContext<@NonNull ?> ctx = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.getInstance()).source(chunk).world((ServerLevel) chunk.getLevel()).chunk(chunk)) {
ctx.buildAndSwitch();
chunk.unpackTicks();
}
}
use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method shadow$neighborChanged.
@Override
public void shadow$neighborChanged(final BlockPos pos, final Block blockIn, final BlockPos fromPos) {
final BlockPos immutableTarget = pos.immutable();
final BlockPos immutableFrom = fromPos.immutable();
// Sponge Start - Check asynchronicity,
// if not on the server thread and we're a server world, we've got problems...
final PhaseTracker server = PhaseTracker.SERVER;
if (server.getSidedThread() != Thread.currentThread()) {
// lol no, report the block change properly
new PrettyPrinter(60).add("Illegal Async PhaseTracker Access").centre().hr().addWrapped(PhasePrinter.ASYNC_TRACKER_ACCESS).add().add(new Exception("Async Block Notifcation Detected")).log(SpongeCommon.logger(), Level.ERROR);
// Maybe? I don't think this is wise to try and sync back a notification on the main thread.
return;
}
// world that Sponge isn't directly managing, so we'll just ignore trying to record on those.
if (this.bridge$isFake()) {
// If we're fake, well, we could effectively call this without recording on worlds we don't
// want to care about.
super.shadow$neighborChanged(immutableTarget, blockIn, immutableFrom);
return;
}
// Otherwise, we continue with recording, maybe.
final LevelChunk targetChunk = this.shadow$getChunkAt(immutableTarget);
final BlockState targetBlockState = targetChunk.getBlockState(immutableTarget);
// Sponge - Shortcircuit if the block has no neighbor logic
if (!((TrackableBlockBridge) targetBlockState.getBlock()).bridge$overridesNeighborNotificationLogic()) {
return;
}
// Sponge End
// Sponge start - prepare notification
final PhaseContext<@NonNull ?> peek = server.getPhaseContext();
// try { // Vanilla - We need to push the effect transactor so that it always pops
try {
final Supplier<ServerLevel> worldSupplier = VolumeStreamUtils.createWeaklyReferencedSupplier((ServerLevel) (Object) this, "ServerWorld");
final net.minecraft.world.level.block.entity.@Nullable BlockEntity existingTile = targetChunk.getBlockEntity(immutableTarget, LevelChunk.EntityCreationType.CHECK);
peek.getTransactor().logNeighborNotification(worldSupplier, immutableFrom, blockIn, immutableTarget, targetBlockState, existingTile);
peek.associateNeighborStateNotifier(immutableFrom, targetBlockState.getBlock(), immutableTarget, ((ServerLevel) (Object) this), PlayerTracker.Type.NOTIFIER);
// Sponge End
targetBlockState.neighborChanged(((ServerLevel) (Object) this), immutableTarget, blockIn, immutableFrom, false);
} catch (final Throwable throwable) {
final CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours");
final CrashReportCategory crashreportcategory = crashreport.addCategory("Block being updated");
crashreportcategory.setDetail("Source block type", () -> {
try {
return String.format("ID #%d (%s // %s)", Registry.BLOCK.getId(blockIn), blockIn.getDescriptionId(), blockIn.getClass().getCanonicalName());
} catch (final Throwable var2) {
return "ID #" + Registry.BLOCK.getId(blockIn);
}
});
CrashReportCategory.populateBlockDetails(crashreportcategory, immutableTarget, targetBlockState);
throw new ReportedException(crashreport);
}
}
use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.
the class ResolutionResult method printErrorsIfAny.
public void printErrorsIfAny(final Map<PluginCandidate<T>, String> failedInstance, final Map<PluginCandidate<T>, String> consequentialFailedInstance, final Logger logger) {
final int noOfFailures = this.numberOfFailures() + failedInstance.size() + consequentialFailedInstance.size();
if (noOfFailures == 0) {
return;
}
final PrettyPrinter errorPrinter = new PrettyPrinter(120);
errorPrinter.add("SPONGE PLUGINS FAILED TO LOAD").centre().hr().addWrapped("%d plugin(s) have unfulfilled or cyclic dependencies or failed to load. Your game will continue to load without" + " these plugins.", noOfFailures);
if (!this.duplicateIds.isEmpty()) {
errorPrinter.add();
errorPrinter.add("The following plugins IDs were duplicated - some plugins will not have been loaded:");
for (final String id : this.duplicateIds) {
errorPrinter.add(" * %s", id);
}
}
if (!this.missingDependencies.isEmpty()) {
errorPrinter.add();
errorPrinter.add("The following plugins are missing dependencies:");
for (final Map.Entry<PluginCandidate<T>, Collection<String>> entry : this.missingDependencies.entrySet()) {
errorPrinter.add(" * %s requires [ %s ]", entry.getKey().metadata().id(), String.join(", ", entry.getValue()));
}
}
if (!this.versionMismatch.isEmpty()) {
errorPrinter.add();
errorPrinter.add("The following plugins require different version(s) of dependencies you have installed:");
for (final Map.Entry<PluginCandidate<T>, Collection<Tuple<String, PluginCandidate<T>>>> entry : this.versionMismatch.entrySet()) {
final PluginCandidate<T> candidate = entry.getKey();
final Collection<Tuple<String, PluginCandidate<T>>> mismatchedDeps = entry.getValue();
final String errorString = mismatchedDeps.stream().map(x -> String.format("%s version %s (currently version %s)", x.second().metadata().id(), x.first(), x.second().metadata().version())).collect(Collectors.joining(", "));
errorPrinter.add(" * %s requires [ %s ]", candidate.metadata().id(), errorString);
}
}
if (!this.cyclicDependency.isEmpty()) {
errorPrinter.add();
errorPrinter.add("The following plugins were found to have cyclic dependencies:");
for (final Map.Entry<PluginCandidate<T>, Collection<PluginCandidate<T>>> node : this.cyclicDependency.entrySet()) {
errorPrinter.add(" * %s has dependency cycle [ ... -> %s -> ... ]", node.getKey().metadata().id(), node.getValue().stream().map(x -> x.metadata().id()).collect(Collectors.joining(" -> ")));
}
}
if (!failedInstance.isEmpty()) {
errorPrinter.add();
errorPrinter.add("The following plugins threw exceptions when being created (report these to the plugin authors):");
for (final Map.Entry<PluginCandidate<T>, String> node : failedInstance.entrySet()) {
errorPrinter.add(" * %s with the error message \"%s\"", node.getKey().metadata().id(), node.getValue());
}
}
if (!this.cascadedFailure.isEmpty() || !consequentialFailedInstance.isEmpty()) {
final Map<PluginCandidate<T>, String> mergedFailures = new HashMap<>(consequentialFailedInstance);
for (final Map.Entry<PluginCandidate<T>, Collection<PluginCandidate<T>>> entry : this.cascadedFailure.entrySet()) {
final String error = entry.getValue().stream().map(x -> x.metadata().id()).collect(Collectors.joining(", "));
mergedFailures.merge(entry.getKey(), error, (old, incoming) -> old + ", " + incoming);
}
errorPrinter.add();
errorPrinter.add("The following plugins are not loading because they depend on plugins that will not load:");
for (final Map.Entry<PluginCandidate<T>, String> node : mergedFailures.entrySet()) {
errorPrinter.add(" * %s depends on [ %s ]", node.getKey().metadata().id(), // so we just list all the plugins that failed
node.getValue());
}
}
errorPrinter.add().hr().addWrapped("DO NOT REPORT THIS TO SPONGE. These errors are not Sponge errors, they are plugin loading errors. Seek " + "support from the authors of the plugins listed above if you need help getting these plugins to load.").add();
errorPrinter.addWrapped("Your game will continue to start without the %d plugins listed above. Other plugins will continue to load, " + "however you may wish to stop your game and fix these issues. For any missing dependencies, you " + "may be able to find them at https://ore.spongepowered.org/. For any plugins that have cyclic dependencies or threw " + "exceptions, it is likely a bug in the plugin.", noOfFailures);
errorPrinter.log(logger, Level.ERROR);
}
Aggregations