Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ javascript/public/build/
.sass-cache
vendor

.DS_Store
.DS_Store

scripts/src/lib/mappings/mapping-io.wasm
scripts/src/lib/mappings/mapping-io.wasm-runtime.js
2 changes: 1 addition & 1 deletion assets/dark.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ $content-width: 1024px;
@import "{{ site.theme }}";
@import "fabric";

code, select, pre, input {
code, select, pre, input, textarea {
background-color: $background-color;
color: $text-color;
}
Expand Down
11 changes: 11 additions & 0 deletions crash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
layout: page
title: Crash Report Remapper
permalink: /develop/crash/
topnav: false
---

<div class="fabric-component" data-component="Crash"></div>
{% assign cacheBust = site.time | date:'?v=%s' %}
<script type="text/javascript" src="{{ "/scripts/main.js" | relative_url | append: cacheBust }}"></script>
<link href="{{ "/scripts/style.css" | relative_url | append: cacheBust }}" rel="stylesheet">
50 changes: 50 additions & 0 deletions scripts/src/lib/Crash.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script lang="ts">
import { getYarnMappings } from "./mappings/yarn"

var text = "";
let mappings = getYarnMappings()

async function remapLog() {
const mappingTree = await mappings;
const intermediary = mappingTree.getNamespaceId("intermediary");
const named = mappingTree.getNamespaceId("named");

const exp = /(net\.minecraft\.)?class_(?<classId>\d+)(.method_(?<methodId>\d+))?/g;

text = text.replaceAll(exp, (match, ...args) => {
const groups = args[args.length - 1];
const srcClassName = `net/minecraft/class_${groups.classId}`;
const className = mappingTree.mapClassName(srcClassName, intermediary, named);

var formattedName = match.startsWith("net.minecraft.") ? className.replaceAll("\/", ".") : className.substring(className.lastIndexOf("/") + 1);

if (groups.methodId) {
const srcMethodName = `method_${groups.methodId}`;
formattedName += "." + mappingTree.getMethod(srcClassName, srcMethodName, null)?.getDstName(named) ?? srcMethodName;
}

return formattedName;
});
}
</script>

<textarea
id="large-textarea"
bind:value={text}
class="textarea"
placeholder="Paste crash report here..."
on:input={remapLog}
wrap="off"
></textarea>

<style>
.textarea {
flex-grow: 1;
resize: none;
font-size: 1rem;
padding: 10px;
width: 100%;
height: 70vh;
overflow: auto;
}
</style>
30 changes: 30 additions & 0 deletions scripts/src/lib/mappings/mapping-io.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
interface MappingIoWasm {
readTinyV2(mappings: string) : WasmMappingView;
}

interface WasmMappingView {
getSrcNamespace(): string;
getDstNamespaces(): string[];
getNamespaceId(namespace: string): number;
getClasses(): WasmClassViewWasm[];
getClass(srcName: string): WasmClassViewWasm | undefined;
getClass(srcName: string, namespaceId: number): WasmClassViewWasm | undefined;
getMethod(srcClsName: string, srcName: string, srcDesc: string | null): WasmMethodViewWasm | undefined;
getMethod(srcClsName: string, srcName: string, srcDesc: string | undefined, namespaceId: number): WasmMethodViewWasm | undefined;
mapClassName(name: string, namespaceId: number): string;
mapClassName(name: string, namespaceId: number, dstNamespace: number): string;
mapMethodName(name: string, srcNamespace: number, dstNamespace: number): string;
}

interface WasmElementView {
getSrcName(): string;
getDstName(namespaceId: number): string;
getComments(): string | undefined;
}

interface WasmClassViewWasm extends WasmElementView {
getMethods(): WasmMethodViewWasm[];
}

interface WasmMethodViewWasm extends WasmElementView {
}
30 changes: 30 additions & 0 deletions scripts/src/lib/mappings/yarn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import JSZip from "jszip";
import { TeaVM } from "./mapping-io.wasm-runtime.js";
import mappingIoWasm from './mapping-io.wasm?url'


export async function getYarnMappings(): Promise<WasmMappingView> {
const data = await fetchData("https://maven.fabricmc.net/net/fabricmc/yarn/1.21.4%2Bbuild.8/yarn-1.21.4%2Bbuild.8-v2.jar");
const mapping = await extractMappings(data);
return await openMappings(mapping);
}

async function fetchData(url: string): Promise<ArrayBuffer> {
const response = await fetch(url);
return await response.arrayBuffer();
}

async function extractMappings(data: ArrayBuffer): Promise<string> {
const zip = await JSZip.loadAsync(data);
const file = zip.file('mappings/mappings.tiny')
if (file === null) {
throw new Error('Mappings file not found');
}
return await file.async('string');
}

async function openMappings(mapping: string): Promise<WasmMappingView> {
const teavm = await TeaVM.wasmGC.load(mappingIoWasm);
const mappingio = teavm.exports as MappingIoWasm;
return mappingio.readTinyV2(mapping);
}
4 changes: 3 additions & 1 deletion scripts/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const Server = lazy("Server");
const Versions = lazy("Versions");
const Documentation = lazy("Documentation");
const Template = lazy("Template");
const Crash = lazy("Crash");

let Components: Record<string, () => Promise<Module>> = {
Installer,
Expand All @@ -25,7 +26,8 @@ let Components: Record<string, () => Promise<Module>> = {
Server,
Versions,
Documentation,
Template
Template,
Crash
};

function initComponents() {
Expand Down
Loading