use of net.minecraft.CrashReport in project SpongeCommon by SpongePowered.
the class SpongeWorldManager method prepareWorld.
private ServerLevel prepareWorld(final ServerLevel world, final boolean isDebugGeneration) {
final boolean isDefaultWorld = Level.OVERWORLD.equals(world.dimension());
final PrimaryLevelData levelData = (PrimaryLevelData) world.getLevelData();
if (isDefaultWorld) {
// Initialize scoreboard data. This will hook to the ServerScoreboard, needs to be made multi-world aware
((MinecraftServerAccessor) this.server).accessor$readScoreboard(world.getDataStorage());
((MinecraftServerAccessor) this.server).accessor$commandStorage(new CommandStorage(world.getDataStorage()));
}
final boolean isInitialized = levelData.isInitialized();
SpongeCommon.post(SpongeEventFactory.createLoadWorldEvent(PhaseTracker.getCauseStackManager().currentCause(), (org.spongepowered.api.world.server.ServerWorld) world, isInitialized));
PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(world);
// Set the view distance back on it's self to trigger the logic
((PrimaryLevelDataBridge) world.getLevelData()).bridge$viewDistance().ifPresent(v -> ((PrimaryLevelDataBridge) world.getLevelData()).bridge$setViewDistance(v));
world.getWorldBorder().applySettings(levelData.getWorldBorder());
if (!isInitialized) {
try {
final boolean hasSpawnAlready = ((PrimaryLevelDataBridge) world.getLevelData()).bridge$customSpawnPosition();
if (!hasSpawnAlready) {
if (isDefaultWorld || ((ServerWorldProperties) world.getLevelData()).performsSpawnLogic()) {
MinecraftServerAccessor.invoker$setInitialSpawn(world, levelData, levelData.worldGenSettings().generateBonusChest(), isDebugGeneration, !isDebugGeneration);
} else if (Level.END.equals(world.dimension())) {
((PrimaryLevelData) world.getLevelData()).setSpawn(ServerLevel.END_SPAWN_POINT, 0);
}
} else {
Features.BONUS_CHEST.place(world, world.getChunkSource().getGenerator(), world.random, new BlockPos(levelData.getXSpawn(), levelData.getYSpawn(), levelData.getZSpawn()));
}
levelData.setInitialized(true);
if (isDebugGeneration) {
((MinecraftServerAccessor) this.server).invoker$setupDebugLevel(levelData);
}
} catch (final Throwable throwable) {
final CrashReport crashReport = CrashReport.forThrowable(throwable, "Exception initializing world '" + world.dimension().location() + "'");
try {
world.fillReportDetails(crashReport);
} catch (final Throwable ignore) {
}
throw new ReportedException(crashReport);
}
levelData.setInitialized(true);
}
// Initialize PlayerData in PlayerList, add WorldBorder listener. We change the method in PlayerList to handle per-world border
this.server.getPlayerList().setLevel(world);
if (levelData.getCustomBossEvents() != null) {
((ServerLevelBridge) world).bridge$getBossBarManager().load(levelData.getCustomBossEvents());
}
return world;
}
use of net.minecraft.CrashReport 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 net.minecraft.CrashReport in project MinecraftForge by MinecraftForge.
the class CrashReportExtender method dumpModLoadingCrashReport.
public static File dumpModLoadingCrashReport(final Logger logger, final LoadingFailedException error, final File topLevelDir) {
final CrashReport crashReport = CrashReport.forThrowable(new Exception("Mod Loading has failed"), "Mod loading error has occurred");
error.getErrors().forEach(mle -> {
final Optional<IModInfo> modInfo = Optional.ofNullable(mle.getModInfo());
final CrashReportCategory category = crashReport.addCategory(modInfo.map(iModInfo -> "MOD " + iModInfo.getModId()).orElse("NO MOD INFO AVAILABLE"));
Throwable cause = mle.getCause();
int depth = 0;
while (cause != null && cause.getCause() != null && cause.getCause() != cause) {
category.setDetail("Caused by " + (depth++), cause + generateEnhancedStackTrace(cause.getStackTrace()).replaceAll(Strings.LINE_SEPARATOR + "\t", "\n\t\t"));
cause = cause.getCause();
}
if (cause != null)
category.applyStackTrace(cause);
category.setDetail("Mod File", () -> modInfo.map(IModInfo::getOwningFile).map(t -> t.getFile().getFileName()).orElse("NO FILE INFO"));
category.setDetail("Failure message", () -> mle.getCleanMessage().replace("\n", "\n\t\t"));
category.setDetail("Mod Version", () -> modInfo.map(IModInfo::getVersion).map(Object::toString).orElse("NO MOD INFO AVAILABLE"));
category.setDetail("Mod Issue URL", () -> modInfo.map(IModInfo::getOwningFile).map(IModFileInfo.class::cast).flatMap(mfi -> mfi.getConfig().<String>getConfigElement("issueTrackerURL")).orElse("NOT PROVIDED"));
category.setDetail("Exception message", Objects.toString(cause, "MISSING EXCEPTION MESSAGE"));
});
final File file1 = new File(topLevelDir, "crash-reports");
final File file2 = new File(file1, "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-fml.txt");
if (crashReport.saveToFile(file2)) {
logger.fatal("Crash report saved to {}", file2);
} else {
logger.fatal("Failed to save crash report");
}
System.out.print(crashReport.getFriendlyReport());
return file2;
}
Aggregations