diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b63da45
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..27a117c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024-2025 OmniMC
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2d33390
--- /dev/null
+++ b/README.md
@@ -0,0 +1,101 @@
+# Lumina
+
+Welcome to Lumina, a Java-based framework designed to simplify how you handle mappings, serialization, and
+deserialization.
+Whether you’re working with full mappings, compressed mappings, or something in between,
+Lumina makes it easy, efficient, and reliable. It’s built with flexibility in mind, so you can integrate it into your
+projects seamlessly.
+
+## **What does Lumina do?**
+
+This project is the mapping handler for [OmniMC](https://omnimc.org). We use this to control the mappings.
+
+- **Extensible Design**:
+ - Works with custom serializers like `LineSerializer` and `CompressedLineSerializer` for greater flexibility.
+
+- **Robust Error Handling**:
+ - The `FailedState` system handles errors gracefully and gives you all the info you need to debug.
+
+- **Centralized Failure Consumers**:
+ - Simplifies error management with classes like `AcceptConsumer` for reusable and streamlined handling.
+
+## **Getting Started**
+
+Here’s how to get Lumina up and running:
+
+1. **Check your setup**: Make sure you’re using Java 21 or higher.
+2. **Add Lumina to your project**:
+ - Clone the repository:
+ ```shell
+ git clone https://github.com//lumina.git
+ ```
+Or, include it as a dependency in your build system:
+
+- **Maven**:
+```xml
+
+ org.omnimc
+ lumina
+ 1.0.0
+
+```
+
+- **Gradle**
+```groovy
+ implementation 'org.omnimc:lumina:1.0.0'
+```
+
+## **How to Use**
+### **Deserializing Mappings**
+Lumina gives you specialized tools for deserialization, so you can adapt it to whatever kind of mapping format you’re working with.
+
+#### Full Deserialization:
+For handling complete mappings like classes, fields, and methods, use `FullDeserializer`:
+```java
+FullDeserializer deserializer = new FullDeserializer();
+Mappings mappings = ...; // Your Mappings instance
+File mappingsDir = new File("mappings/");
+
+if (deserializer.deserializeToFile(mappings, mappingsDir)) {
+ System.out.println("Full mappings deserialized successfully!");
+}
+```
+
+### **Understanding Mapping Types**
+`MappingType` indicates what kind of mapping you're working with. Each type is tied to a specific serializer:
+- `FULL`: For uncompressed mappings.
+- `COMPRESSED`: Uses the `CompressedLineSerializer` for compressed data.
+- `PARAMETERS`: Specifically for parameter mappings.
+- `UNKNOWN`: For scenarios where the mapping type isn’t defined.
+
+#### Example usage
+```java
+MappingType type = MappingType.FULL;
+LineSerializer serializer = type.getLineSerializer();
+System.out.println("Serializer for FULL: "+serializer);
+```
+
+### **Error Handling That Works for You**
+If something goes wrong, Lumina has you covered with `FailedState`. You can create meaningful error states and handle them however you see fit:
+
+```java
+FailedState error = FailedState.of("Failed to deserialize", ParameterDeserializer.class);
+System.err.println(error);
+```
+And if you want to automate failure handling, you can set up custom consumers with `AcceptConsumer`:
+```java
+AcceptConsumer consumer = new AcceptConsumer();
+consumer.setConsumer(failedState -> {
+ System.err.println("Error occurred: " + failedState);
+});
+```
+
+## **Contributing**
+We love contributions! Here’s how you can help grow Lumina:
+1. Fork the repo.
+2. Create a new branch for your feature or fix.
+3. Submit a pull request with a clear explanation of your changes.
+
+Every contribution is appreciated, no matter how big or small.
+## **License**
+This project is licensed under the [MIT License](LICENSE). That means you can use, modify, and distribute it freely, as long as you give credit where it’s due.
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..bbdfd17
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,39 @@
+# **Security Policy**
+
+Thank you for helping to improve Lumina’s security! We take security vulnerabilities seriously and appreciate your
+contributions to keeping this project safe for everyone.
+
+## **Supported Versions**
+
+We make every effort to backport security fixes to recent versions of Lumina. The following versions are currently
+supported with security updates:
+
+| Version | Supported |
+|---------|-------------------|
+| 1.0.0 | ✅ Fully supported |
+
+Older versions may not receive security fixes. We strongly recommend updating to the latest version whenever possible.
+
+## **Reporting a Vulnerability**
+
+If you believe you’ve found a security issue related to Lumina, please **DO NOT** post it in public forums or as an
+issue on the repository. Instead, help us responsibly disclose the vulnerability by emailing us at:
+**security@omnimc.org**
+When reporting a vulnerability, please include the following information:
+
+- A detailed description of the vulnerability.
+- Steps to reproduce the issue (if applicable).
+- Information about potential impact or severity.
+- Any relevant logs or screenshots.
+
+Our security team will review your report, respond within a reasonable timeframe, and work on a fix as quickly as
+possible.
+
+## **Security Fix Process**
+
+- Once a vulnerability has been verified, we will:
+ 1. Develop and test a patch.
+ 2. Coordinate a private disclosure with impacted parties (if applicable).
+ 3. Release a public update, including a formal acknowledgment of the reporter (with their consent).
+
+Thank you for helping us keep Lumina secure and reliable!
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..d743dd3
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,21 @@
+plugins {
+ id 'java'
+}
+
+group = 'org.omnimc'
+version = '0.0.1'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation platform('org.junit:junit-bom:5.10.0')
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+
+ implementation 'org.jetbrains:annotations:26.0.1'
+}
+
+test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..7596c8b
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Nov 04 04:18:59 CST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..1b6c787
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/jitpack.yml b/jitpack.yml
new file mode 100644
index 0000000..90234fe
--- /dev/null
+++ b/jitpack.yml
@@ -0,0 +1,6 @@
+jdk:
+ - openjdk21
+
+build:
+ commands:
+ - ./gradlew build
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..2659c37
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'Lumina'
+
diff --git a/src/main/java/org/omnimc/lumina/MappingType.java b/src/main/java/org/omnimc/lumina/MappingType.java
new file mode 100644
index 0000000..ed18fa8
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/MappingType.java
@@ -0,0 +1,99 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina;
+
+import org.omnimc.lumina.serialization.LineSerializer;
+import org.omnimc.lumina.serialization.compressed.CompressedLineSerializer;
+
+/**
+ * Represents the different types of mappings supported and provides associated line serializers for each type.
+ *
+ * The `MappingType` enum is used to define distinct mapping modes within the system.
+ * Each mapping type is associated with a specific {@link LineSerializer}, which handles the serialization
+ * and deserialization of that type of mapping.
+ *
+ * Available Mapping Types:
+ *
+ * - FULL: Uses an empty serializer for handling full mappings.
+ * - COMPRESSED: Utilizes a {@link CompressedLineSerializer} for compressed mappings.
+ * - PARAMETERS: Uses an empty serializer for mapping parameters specifically.
+ * - UNKNOWN: Represents an undefined mapping type, with no serializer.
+ *
+ *
+ * @see LineSerializer
+ * @see CompressedLineSerializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public enum MappingType {
+ /**
+ * Represents full mappings with no compression applied.
+ *
+ * This type utilizes an empty implementation of {@link LineSerializer} for handling mappings.
+ */
+ FULL(LineSerializer.getEmptySerializer()),
+ /**
+ * Represents mappings that are serialized in a compressed format.
+ *
+ *
This type uses the {@link CompressedLineSerializer}, which is designed to manage compressed mapping data effectively.
+ */
+ COMPRESSED(new CompressedLineSerializer()),
+ /**
+ * Represents mappings that are specific to method or class parameters.
+ *
+ * Similar to {@code FULL}, this type also uses an empty implementation of {@link LineSerializer}.
+ */
+ PARAMETERS(LineSerializer.getEmptySerializer()),
+ /**
+ * Represents an unknown or undefined mapping type.
+ *
+ * No {@link LineSerializer} is provided for this type, and it is effectively treated as a placeholder.
+ */
+ UNKNOWN(null);
+
+ /**
+ * The {@link LineSerializer} associated with the mapping type.
+ */
+ private final LineSerializer lineSerializer;
+
+ /**
+ * Constructs an instance of the mapping type with the provided {@link LineSerializer}.
+ *
+ * @param lineSerializer The serializer to be associated with the mapping type.
+ */
+ MappingType(LineSerializer lineSerializer) {
+ this.lineSerializer = lineSerializer;
+ }
+
+ /**
+ * Retrieves the {@link LineSerializer} associated with this mapping type.
+ *
+ * @return The associated {@link LineSerializer}, or {@code null} if not available.
+ */
+ public LineSerializer getLineSerializer() {
+ return lineSerializer;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/Mappings.java b/src/main/java/org/omnimc/lumina/Mappings.java
new file mode 100644
index 0000000..3ab3481
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/Mappings.java
@@ -0,0 +1,307 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.deserialization.compressed.CompressedDeserializer;
+import org.omnimc.lumina.deserialization.full.FullDeserializer;
+import org.omnimc.lumina.deserialization.parameter.ParameterDeserializer;
+import org.omnimc.lumina.param.ParameterMap;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * The {@code Mappings} class is responsible for maintaining mappings between obfuscated
+ * and de-obfuscated elements of a program. This includes mappings for classes, methods, fields,
+ * and parameters, which are used to interpret obfuscated code and map it back to meaningful names.
+ *
+ * The class provides utilities for retrieving, adding, and managing these mappings, with methods
+ * to handle individual elements as well as bulk operations. It also integrates with different types
+ * of deserializers to output mappings in various formats.
+ *
+ * This class is designed to be thread-safe due to the use of {@link ConcurrentHashMap}.
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class Mappings {
+
+ /**
+ * Creates an empty {@code Mappings} object.
+ *
+ * @return A new instance of {@code Mappings}.
+ */
+ public static Mappings of() {
+ return new Mappings();
+ }
+
+ /**
+ * Map for class mappings where the key is the obfuscated class name
+ * and the value is the de-obfuscated class name.
+ */
+ private final Map classes;
+
+ /**
+ * Map for method mappings where the key is the obfuscated method name,
+ * and the value is another map. The inner map maps obfuscated class names
+ * to de-obfuscated method names.
+ */
+ private final Map> methods;
+
+ /**
+ * Map for field mappings where the key is the obfuscated class name,
+ * and the value is another map. The inner map maps obfuscated field names
+ * to de-obfuscated field names.
+ */
+ private final Map> fields;
+
+ /**
+ * A {@link ParameterMap} for managing parameter name mappings.
+ */
+ private final ParameterMap parameters;
+
+ /**
+ * Constructs an empty {@code Mappings} object with default empty data structures.
+ */
+ public Mappings() {
+ this(new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new ParameterMap());
+ }
+
+ /**
+ * Constructs a {@code Mappings} object with the specified data.
+ *
+ * @param classes Mappings for class names.
+ * @param methods Mappings for method names.
+ * @param fields Mappings for field names.
+ * @param parameterMap Mapping for parameters.
+ */
+ public Mappings(@NotNull Map classes, @NotNull Map> methods,
+ @NotNull Map> fields, @NotNull ParameterMap parameterMap) {
+ this.classes = classes;
+ this.methods = methods;
+ this.fields = fields;
+ this.parameters = parameterMap;
+ }
+
+ /**
+ * Retrieves all class mappings.
+ *
+ * @return A copy of the class mappings.
+ */
+ public Map getClasses() {
+ return new ConcurrentHashMap<>(classes);
+ }
+
+ /**
+ * Retrieves the de-obfuscated class name for a given obfuscated name.
+ *
+ * @param obfuscatedName The obfuscated class name.
+ * @return The de-obfuscated class name, or {@code null} if not found.
+ */
+ public String getClassName(@NotNull String obfuscatedName) {
+ return classes.get(obfuscatedName);
+ }
+
+ /**
+ * Retrieves the obfuscated class name from a de-obfuscated name.
+ *
+ * @param unObfuscatedName The de-obfuscated class name.
+ * @return The obfuscated class name, or {@code null} if not found.
+ */
+ public String getClassNameByValue(@NotNull String unObfuscatedName) {
+ Optional> nameOptional = classes
+ .entrySet()
+ .stream()
+ .filter(entry -> entry.getValue().equals(unObfuscatedName))
+ .findFirst();
+
+ return nameOptional.map(Map.Entry::getKey).orElse(null);
+ }
+
+ /**
+ * Adds a new class mapping.
+ *
+ * @param obfuscatedName The obfuscated class name.
+ * @param unObfuscatedName The de-obfuscated class name.
+ * @return {@code true} if an existing mapping was replaced, otherwise {@code false}.
+ */
+ public boolean addClass(@NotNull String obfuscatedName, @NotNull String unObfuscatedName) {
+ String put = classes.put(obfuscatedName, unObfuscatedName);
+ return put != null;
+ }
+
+ /**
+ * Retrieves all method mappings.
+ *
+ * @return A copy of the method mappings.
+ */
+ public Map> getMethods() {
+ return new ConcurrentHashMap<>(methods);
+ }
+
+ /**
+ * Gets the de-obfuscated method name for the given obfuscated class and method names.
+ *
+ * @param obfuscatedClassName The obfuscated class name.
+ * @param obfuscatedMethodName The obfuscated method name.
+ * @return The de-obfuscated method name, or {@code null} if not found.
+ */
+ public String getMethodName(@NotNull String obfuscatedClassName, @NotNull String obfuscatedMethodName) {
+ Map methodMap = methods.get(obfuscatedClassName);
+
+ if (methodMap == null) {
+ return null;
+ }
+
+ return methodMap.get(obfuscatedMethodName);
+ }
+
+ /**
+ * Adds a new method mapping.
+ *
+ * @param obfuscatedClassName The obfuscated class name.
+ * @param obfuscatedMethodName The obfuscated method name.
+ * @param methodName The de-obfuscated method name.
+ * @return {@code true} if the mapping was successfully added.
+ */
+ public boolean addMethod(@NotNull String obfuscatedClassName, @NotNull String obfuscatedMethodName, @NotNull String methodName) {
+ return addToMap(obfuscatedClassName, obfuscatedMethodName, methodName, methods);
+ }
+
+ public Map> getFields() {
+ return new ConcurrentHashMap<>(fields);
+ }
+
+ public String getFieldName(@NotNull String obfuscatedClassName, @NotNull String obfuscatedFieldName) {
+ Map fieldMap = fields.get(obfuscatedClassName);
+ if (fieldMap == null) {
+ return null;
+ }
+
+ return fieldMap.get(obfuscatedFieldName);
+ }
+
+ public boolean addField(@NotNull String obfuscatedClassName, @NotNull String obfuscatedFieldName, @NotNull String fieldName) {
+ return addToMap(obfuscatedClassName, obfuscatedFieldName, fieldName, fields);
+ }
+
+ public ParameterMap getParameterMap() {
+ return parameters;
+ }
+
+ public void addAllClasses(@NotNull Mappings mappings) {
+ addAllClasses(mappings.getClasses());
+ }
+
+ public void addAllClasses(@NotNull Map classes) {
+ this.classes.putAll(classes);
+ }
+
+ public void addAllMethods(@NotNull Mappings mappings) {
+ addAllMethods(mappings.getMethods());
+ }
+
+ public void addAllMethods(@NotNull Map> methods) {
+ this.methods.putAll(methods);
+ }
+
+ public void addAllFields(@NotNull Mappings mappings) {
+ addAllFields(mappings.getFields());
+ }
+
+ public void addAllFields(@NotNull Map> fields) {
+ this.fields.putAll(fields);
+ }
+
+ public void addAllParameters(@NotNull Mappings mappings) {
+ addAllParameters(mappings.parameters);
+ }
+
+ public void addAllParameters(@NotNull ParameterMap params) {
+ this.parameters.addAll(params);
+ }
+
+ public void addAll(@NotNull Mappings mappings) {
+ addAllClasses(mappings);
+ addAllMethods(mappings);
+ addAllFields(mappings);
+ addAllParameters(mappings);
+ }
+
+ /**
+ * Converts the mapping to a string representation based on the specified {@link MappingType}.
+ *
+ * @param type The type of the mapping format.
+ * @return A string representation of the mappings.
+ */
+ public String toString(MappingType type) {
+ return switch (type) {
+ case PARAMETERS -> {
+ ParameterDeserializer deserializer = new ParameterDeserializer();
+ yield deserializer.deserializeToString(this);
+ }
+ case COMPRESSED -> {
+ CompressedDeserializer deserializer = new CompressedDeserializer();
+ yield deserializer.deserializeToString(this);
+ }
+ case FULL -> {
+ FullDeserializer deserializer = new FullDeserializer();
+ yield deserializer.deserializeToString(this);
+ }
+ default -> "Mappings{" +
+ "classes=" + classes +
+ ", methods=" + methods +
+ ", fields=" + fields +
+ ", parameters=" + parameters +
+ '}';
+ };
+ }
+
+ @Override
+ public String toString() {
+ return toString(MappingType.UNKNOWN);
+ }
+
+ /**
+ * Utility method for adding mappings to a nested map structure.
+ *
+ * @param obfuscatedClassName The obfuscated class name.
+ * @param obfuscatedFieldName The obfuscated field or method name.
+ * @param fieldName The de-obfuscated name.
+ * @param map The map to modify.
+ * @return {@code true} if the mapping already existed.
+ */
+ private boolean addToMap(String obfuscatedClassName, String obfuscatedFieldName, String fieldName, Map> map) {
+ try {
+ Map specificMap = map.computeIfAbsent(obfuscatedClassName, k -> new ConcurrentHashMap<>());
+ specificMap.put(obfuscatedFieldName, fieldName);
+ return true;
+ } catch (NullPointerException e) {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/consumer/AcceptConsumer.java b/src/main/java/org/omnimc/lumina/consumer/AcceptConsumer.java
new file mode 100644
index 0000000..4a5501c
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/consumer/AcceptConsumer.java
@@ -0,0 +1,85 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.consumer;
+
+import java.util.function.Consumer;
+
+/**
+ * Provides a base class for handling failure states using a {@link Consumer} of {@link FailedState}.
+ *
+ * The `AcceptConsumer` allows for flexible error handling by defining a consumer
+ * callback that can handle `FailedState` instances. This enables a mechanism for propagating or processing
+ * failures in a central, configurable way.
+ *
+ * Key Features:
+ *
+ * - Defines a **protected** mechanism to handle failures for subclasses.
+ * - Supports late binding of the `FailedState` consumer, allowing it to be set at runtime.
+ * - Acts as an extensible base for other classes that require failure handling.
+ *
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class AcceptConsumer {
+
+ /**
+ * The consumer used to handle failure states.
+ */
+ private Consumer failedStateConsumer;
+
+ /**
+ * Retrieves the currently configured consumer for handling {@link FailedState}.
+ *
+ * @return The configured consumer, or {@code null} if none is set.
+ */
+ protected Consumer getConsumer() {
+ return failedStateConsumer;
+ }
+
+
+ /**
+ * Sets the consumer that will handle {@link FailedState} objects.
+ *
+ * @param failedStateConsumer The consumer to handle `FailedState` instances.
+ */
+ public void setConsumer(Consumer failedStateConsumer) {
+ this.failedStateConsumer = failedStateConsumer;
+ }
+
+ /**
+ * Dispatches a {@link FailedState} object to the configured consumer, if one is set.
+ *
+ * If no consumer is set, calling this method has no effect.
+ *
+ * @param failedState The failure state to dispatch.
+ */
+ protected void fail(FailedState failedState) {
+ Consumer consumer = getConsumer();
+ if (consumer != null) {
+ consumer.accept(failedState);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/consumer/FailedState.java b/src/main/java/org/omnimc/lumina/consumer/FailedState.java
new file mode 100644
index 0000000..da11f63
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/consumer/FailedState.java
@@ -0,0 +1,106 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.consumer;
+
+/**
+ * Represents a failure state, containing information about the failure reason, the exception (if any), and the caller's class.
+ *
+ * The `FailedState` record stores information that can be used for debugging or reporting errors in the deserialization process
+ * or other operations. It supports various ways to construct a failure state with or without a reason or throwable.
+ *
+ * Key Features:
+ *
+ * - Immutable by design due to being implemented as a record.
+ * - Provides static factory methods to simplify construction.
+ * - Includes a detailed `toString()` implementation for easy logging and debugging.
+ *
+ *
+ * @param reason The reason for the failure, represented as a string (nullable).
+ * @param throwable The associated exception, if applicable (nullable).
+ * @param caller The class in which the failure occurred, represented as a {@link Class} object.
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public record FailedState(String reason, Throwable throwable, Class> caller) {
+
+ /**
+ * Creates a new {@link FailedState} with a reason, an associated throwable, and the caller's class.
+ *
+ * @param reason The reason for the failure.
+ * @param throwable The associated exception.
+ * @param caller The class in which the failure occurred.
+ * @return A new instance of {@link FailedState}.
+ */
+ public static FailedState of(String reason, Throwable throwable, Class> caller) {
+ return new FailedState(reason, throwable, caller);
+ }
+
+ /**
+ * Creates a new {@link FailedState} with only a throwable and the caller's class.
+ *
+ * @param throwable The associated exception.
+ * @param caller The class in which the failure occurred.
+ * @return A new instance of {@link FailedState}.
+ */
+ public static FailedState of(Throwable throwable, Class> caller) {
+ return new FailedState(null, throwable, caller);
+ }
+
+ /**
+ * Creates a new {@link FailedState} with only a failure reason and the caller's class.
+ *
+ * @param reason The reason for the failure.
+ * @param caller The class in which the failure occurred.
+ * @return A new instance of {@link FailedState}.
+ */
+ public static FailedState of(String reason, Class> caller) {
+ return new FailedState(reason, null, caller);
+ }
+
+ /**
+ * Converts the failure state to a string representation for logging or debugging.
+ *
+ * The `toString()` outputs details of the reason, throwable, and caller. If no throwable is present,
+ * it omits the throwable-related information.
+ *
+ * @return A string representation of the failure state.
+ */
+ @Override
+ public String toString() {
+ if (throwable == null) {
+ return "FailedState{" +
+ "reason='" + reason + '\'' +
+ ", caller=" + caller +
+ '}';
+ }
+
+ return "FailedState{" +
+ "reason='" + reason + '\'' +
+ ", throwable=" + throwable +
+ ", caller=" + caller +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/deserialization/AbstractMappingDeserializer.java b/src/main/java/org/omnimc/lumina/deserialization/AbstractMappingDeserializer.java
new file mode 100644
index 0000000..a47941e
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/deserialization/AbstractMappingDeserializer.java
@@ -0,0 +1,82 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.deserialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.AcceptConsumer;
+
+import java.io.File;
+
+/**
+ * An abstract base class for mapping deserializers that provides a foundation for implementing mapping deserialization logic.
+ *
+ * This class extends {@link AcceptConsumer}, allowing deserialization implementations to leverage consumer-based
+ * error handling. The class implements {@link MappingDeserializer} and serves as a base for defining:
+ *
+ * - Deserialization to a string representation.
+ * - Deserialization to a single file.
+ * - Deserialization to multiple files.
+ *
+ * Subclasses are required to provide specific implementations for these methods.
+ *
+ * @see MappingDeserializer
+ * @see AcceptConsumer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public abstract class AbstractMappingDeserializer extends AcceptConsumer implements MappingDeserializer {
+
+ /**
+ * Serializes mappings to a string representation.
+ *
+ * @param mappings The {@link Mappings} object containing classes, methods, and field mappings.
+ * @return A string representation of the mappings.
+ */
+ @Override
+ public abstract String deserializeToString(@NotNull Mappings mappings);
+
+ /**
+ * Serializes mappings to a single file.
+ *
+ * @param mappings The {@link Mappings} object containing classes, methods, and field mappings.
+ * @param file The file where the deserialization output will be written.
+ * @return {@code true} if successful, otherwise {@code false}.
+ */
+ @Override
+ public abstract boolean deserializeToFile(@NotNull Mappings mappings, @NotNull File file);
+
+ /**
+ * Serializes mappings to multiple files.
+ *
+ * @param mappings The {@link Mappings} object containing classes, methods, and field mappings.
+ * @param locations An array of files representing output locations for serialized data.
+ * @return {@code true} if successful, otherwise {@code false}.
+ */
+ @Override
+ public abstract boolean deserializeToFiles(@NotNull Mappings mappings, @NotNull File[] locations);
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/deserialization/MappingDeserializer.java b/src/main/java/org/omnimc/lumina/deserialization/MappingDeserializer.java
new file mode 100644
index 0000000..2086751
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/deserialization/MappingDeserializer.java
@@ -0,0 +1,76 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.deserialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.Mappings;
+
+import java.io.File;
+
+/**
+ * A contract for converting {@link Mappings} objects into various deserialized outputs.
+ *
+ * This interface defines methods for serializing mappings into different formats,
+ * including:
+ *
+ * - String-based representation.
+ * - File-based representation for single files.
+ * - File-based representation across multiple files.
+ *
+ * Implementing classes are expected to define specific serialization logic for these operations.
+ *
+ * @see Mappings
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public interface MappingDeserializer {
+
+ /**
+ * Serializes the provided {@link Mappings} into a string representation.
+ *
+ * @param mappings The mappings to be serialized.
+ * @return A string representation of the mappings.
+ */
+ String deserializeToString(@NotNull Mappings mappings);
+
+ /**
+ * Serializes the provided {@link Mappings} into a single file.
+ *
+ * @param mappings The mappings to be serialized.
+ * @param file The file where the serialized result will be written.
+ * @return {@code true} if the operation is successful, otherwise {@code false}.
+ */
+ boolean deserializeToFile(@NotNull Mappings mappings, @NotNull File file);
+
+ /**
+ * Serializes the provided {@link Mappings} into multiple files.
+ *
+ * @param mappings The mappings to be serialized.
+ * @param locations An array of files to distribute mapping data across.
+ * @return {@code true} if the operation is successful, otherwise {@code false}.
+ */
+ boolean deserializeToFiles(@NotNull Mappings mappings, @NotNull File[] locations);
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/deserialization/compressed/CompressedDeserializer.java b/src/main/java/org/omnimc/lumina/deserialization/compressed/CompressedDeserializer.java
new file mode 100644
index 0000000..88a5ddd
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/deserialization/compressed/CompressedDeserializer.java
@@ -0,0 +1,221 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.deserialization.compressed;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.deserialization.AbstractMappingDeserializer;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A {@link AbstractMappingDeserializer} implementation for handling compressed mapping deserialization.
+ *
+ * This class provides logic for serializing mapping data into a compressed format that is
+ * human-readable but compact. It supports deserialization into:
+ *
+ * - A single file with the extension `.mmap`.
+ * - A string representation of the mapping data.
+ *
+ * Multiple files are not supported by this deserializer.
+ *
+ * Entries written by this deserializer include class, method, and field mappings, where:
+ *
+ * - Class entries are prefixed with `CLASS`.
+ * - Method entries are prefixed with `METHOD`.
+ * - Field entries are prefixed with `FIELD`.
+ *
+ *
+ *
+ * @see AbstractMappingDeserializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class CompressedDeserializer extends AbstractMappingDeserializer {
+
+ /**
+ * Serializes the provided {@link Mappings} object into a string representation.
+ *
+ * The returned string is encoded in a compact format that uses prefixes
+ * (`CLASS`, `METHOD`, `FIELD`) to define different types of mappings.
+ *
+ * @param mappings The {@link Mappings} object containing data to serialize.
+ * @return A string representation of the mapping data.
+ */
+ @Override
+ public String deserializeToString(@NotNull Mappings mappings) {
+ return makeOutput(mappings);
+ }
+
+ /**
+ * Serializes the given {@link Mappings} object into a single `.mmap` file.
+ *
+ * The output file must:
+ *
+ * - Have a `.mmap` file extension.
+ * - Not be a directory.
+ * - Be writable.
+ *
+ *
+ *
+ * @param mappings The {@link Mappings} to serialize.
+ * @param file The target file for the serialized output.
+ * @return {@code true} if the operation is successful, otherwise {@code false}.
+ */
+ @Override
+ public boolean deserializeToFile(@NotNull Mappings mappings, @NotNull File file) {
+ Objects.requireNonNull(mappings, "Mappings is null");
+ Objects.requireNonNull(file, "File is null");
+
+ if (file.isDirectory()) {
+ this.fail(FailedState.of("File cannot be a directory!", this.getClass()));
+ return false;
+ }
+
+ if (!file.getName().endsWith(".mmap")) {
+ this.fail(FailedState.of("File must end with `.mmap`", this.getClass()));
+ return false;
+ }
+
+ if (!file.exists()) {
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ this.fail(FailedState.of(e, this.getClass()));
+ return false;
+ }
+ } else {
+ file.delete();
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ this.fail(FailedState.of(e, this.getClass()));
+ return false;
+ }
+ }
+
+ String output = makeOutput(mappings);
+
+ try {
+ FileWriter writer = new FileWriter(file);
+ writer.write(output);
+ writer.flush();
+ writer.close();
+ } catch (IOException e) {
+ this.fail(FailedState.of(e, this.getClass()));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Deserialization to multiple files is unsupported by this deserializer.
+ *
+ * @param mappings The {@link Mappings} object.
+ * @param locations An array of files to which mappings will be serialized.
+ * @return Always returns {@code false}.
+ */
+ @Override
+ public boolean deserializeToFiles(@NotNull Mappings mappings, @NotNull File[] locations) {
+ this.fail(FailedState.of("Compressed Deserializer does not support Multiple Files!", this.getClass()));
+ return false;
+ }
+
+ /**
+ * Converts the given {@link Mappings} object into a formatted string.
+ *
+ * Each mapping is written as a line in the following format:
+ *
+ * - Class: {@code CLASS obfuscated:deobfuscated}
+ * - Method: {@code METHOD obfuscated:deobfuscated}
+ * - Field: {@code FIELD obfuscated:deobfuscated}
+ *
+ * Method and field mappings are grouped under their respective classes.
+ *
+ * @param mainMappings The {@link Mappings} object to format.
+ * @return A formatted string representing the mappings.
+ */
+ private String makeOutput(Mappings mainMappings) {
+ StringBuilder builder = new StringBuilder();
+
+ for (Map.Entry classEntry : mainMappings.getClasses().entrySet()) {
+ String obfuscatedName = classEntry.getKey();
+ String unObfuscatedName = classEntry.getValue();
+
+ builder.append("CLASS")
+ .append(" ")
+ .append(obfuscatedName)
+ .append(":")
+ .append(unObfuscatedName)
+ .append("\n");
+
+ Map> methods = mainMappings.getMethods();
+ if (methods != null) {
+ Map methodMappings = methods.get(obfuscatedName);
+ if (methodMappings != null) {
+ for (Map.Entry methodNames : methodMappings.entrySet()) {
+ String obfuscatedMethodName = methodNames.getKey();
+ String unObfuscatedMethodName = methodNames.getValue();
+
+ builder.append("METHOD")
+ .append(" ")
+ .append(obfuscatedMethodName)
+ .append(":")
+ .append(unObfuscatedMethodName)
+ .append("\n");
+ }
+ }
+ }
+
+
+ Map> fields = mainMappings.getFields();
+ if (fields != null) {
+ Map fieldMappings = fields.get(obfuscatedName);
+ if (fieldMappings != null) {
+ for (Map.Entry fieldNames : fieldMappings.entrySet()) {
+ String obfuscatedFieldName = fieldNames.getKey();
+ String unObfuscatedFieldName = fieldNames.getValue();
+
+ builder.append("FIELD")
+ .append(" ")
+ .append(obfuscatedFieldName)
+ .append(":")
+ .append(unObfuscatedFieldName)
+ .append("\n");
+ }
+ }
+ }
+ }
+
+ return builder.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/deserialization/full/FullDeserializer.java b/src/main/java/org/omnimc/lumina/deserialization/full/FullDeserializer.java
new file mode 100644
index 0000000..4e77f8a
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/deserialization/full/FullDeserializer.java
@@ -0,0 +1,279 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.deserialization.full;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.deserialization.AbstractMappingDeserializer;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A {@link AbstractMappingDeserializer} implementation for handling complete mapping deserialization.
+ *
+ * The `FullDeserializer` allows for the serialization of all mapping categories (classes, fields, and methods) into
+ * string and file formats. It supports multiple files, where each file is dedicated to a specific mapping category.
+ *
+ * The serialized output separates mappings for:
+ *
+ * - Classes – Written into `*.class.mmap` files.
+ * - Methods – Written into `*.method.mmap` files.
+ * - Fields – Written into `*.field.mmap` files.
+ *
+ *
+ *
+ * @see AbstractMappingDeserializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class FullDeserializer extends AbstractMappingDeserializer {
+
+ /**
+ * Serializes all mappings into a structured, multi-segment string representation.
+ *
+ * The output is divided into sections with clearly defined headers:
+ *
+ * - Classes
+ * - Methods
+ * - Fields
+ *
+ *
+ * @param mappings The {@link Mappings} object containing mapping data.
+ * @return A formatted string containing all mappings.
+ */
+ @Override
+ public String deserializeToString(@NotNull Mappings mappings) {
+ StringBuilder builder = new StringBuilder();
+
+ String classOutput = makeClassOutput(mappings);
+ builder.append("#################### Classes ####################\n");
+ builder.append(classOutput);
+ String methodOutput = makeMethodOutput(mappings);
+ builder.append("#################### Methods ####################\n");
+ builder.append(methodOutput);
+ String fieldOutput = makeFieldOutput(mappings);
+ builder.append("#################### Fields ####################\n");
+ builder.append(fieldOutput);
+
+ return builder.toString();
+ }
+
+ /**
+ * Serializes mappings into files when the output directory is specified.
+ *
+ * If the provided file `file` is a directory, the deserializer will attempt to locate
+ * the following files within the directory to write the mappings:
+ *
+ * - `.class.mmap` file for class mappings.
+ * - `.field.mmap` file for field mappings.
+ * - `.method.mmap` file for method mappings.
+ *
+ *
+ * If an appropriate file is not found in the directory, the method will create the required
+ * files. If the provided file is not a directory, this operation fails, as writing to a single
+ * file is unsupported by this deserializer.
+ *
+ * @param mappings The {@link Mappings} object containing mapping data.
+ * @param file The directory to write the output into.
+ * @return {@code true} if successful; {@code false} otherwise.
+ */
+ @Override
+ public boolean deserializeToFile(@NotNull Mappings mappings, @NotNull File file) {
+ if (file.isDirectory()) {
+ File classLocation = null;
+ File fieldLocation = null;
+ File methodLocation = null;
+
+ for (File listFile : Objects.requireNonNull(file.listFiles())) {
+ String name = listFile.getName().toLowerCase();
+ if (name.endsWith(".class.mmap")) {
+ classLocation = listFile;
+ }
+
+ if (name.endsWith(".field.mmap")) {
+ fieldLocation = listFile;
+ }
+
+ if (name.endsWith(".method.mmap")) {
+ methodLocation = listFile;
+ }
+ }
+
+ return writeOutput(classLocation, fieldLocation, methodLocation, mappings);
+ }
+
+ this.fail(FailedState.of("`FullDeserializer` does not support single file deserialization!", this.getClass()));
+ return false;
+ }
+
+ /**
+ * Writes serialized mappings into multiple files based on mapping categories.
+ *
+ * The appropriate categories are identified by file extensions:
+ *
+ * - `.class.mmap` for classes.
+ * - `.field.mmap` for fields.
+ * - `.method.mmap` for methods.
+ *
+ * Existing files are overwritten, and missing files are created.
+ *
+ * @param mappings The {@link Mappings} object containing mapping data.
+ * @param locations An array of file objects to write data into.
+ * @return {@code true} if serialization is successful; {@code false} otherwise.
+ */
+ @Override
+ public boolean deserializeToFiles(@NotNull Mappings mappings, @NotNull File[] locations) {
+ Objects.requireNonNull(mappings);
+ Objects.requireNonNull(locations);
+
+ File classLocation = null;
+ File fieldLocation = null;
+ File methodLocation = null;
+
+ for (@NotNull File location : locations) {
+ String name = location.getName().toLowerCase();
+ if (name.endsWith(".class.mmap")) {
+ classLocation = location;
+ }
+
+ if (name.endsWith(".field.mmap")) {
+ fieldLocation = location;
+ }
+
+ if (name.endsWith(".method.mmap")) {
+ methodLocation = location;
+ }
+ }
+
+ return writeOutput(classLocation, fieldLocation, methodLocation, mappings);
+ }
+
+ /**
+ * Serializes all mappings into their respective output files.
+ *
+ * The mappings are split into three components:
+ *
+ * - Class mappings are written into `classLocation`.
+ * - Field mappings are written into `fieldLocation`.
+ * - Method mappings are written into `methodLocation`.
+ *
+ * Existing files are overwritten, and missing files are created.
+ *
+ * @param classLocation The file for class mappings.
+ * @param fieldLocation The file for field mappings.
+ * @param methodLocation The file for method mappings.
+ * @param mappings The {@link Mappings} object containing mapping data.
+ * @return {@code true} if successful; otherwise {@code false}.
+ */
+ private boolean writeOutput(File classLocation, File fieldLocation, File methodLocation, Mappings mappings) {
+ writeFile(classLocation, makeClassOutput(mappings));
+ writeFile(fieldLocation, makeFieldOutput(mappings));
+ writeFile(methodLocation, makeMethodOutput(mappings));
+ return true;
+ }
+
+ /**
+ * Writes serialized data into the specified file.
+ *
+ * @param file The file to write into.
+ * @param data The serialized data as a string.
+ */
+ private void writeFile(File file, String data) {
+ if (file != null) {
+ if (file.exists()) {
+ file.delete();
+ }
+
+ try (FileWriter writer = new FileWriter(file)) {
+ writer.write(data);
+ writer.flush();
+ } catch (IOException e) {
+ this.fail(FailedState.of(e, this.getClass()));
+ }
+ }
+ }
+
+ private String makeClassOutput(Mappings mappings) {
+ StringBuilder builder = new StringBuilder();
+
+ for (Map.Entry classEntry : mappings.getClasses().entrySet()) {
+ String obfuscatedClassName = classEntry.getKey();
+ String unObfuscatedClassName = classEntry.getValue();
+
+ builder.append(obfuscatedClassName).append(":").append(unObfuscatedClassName).append("\n");
+ }
+
+ return builder.toString();
+ }
+
+ private String makeMethodOutput(Mappings mappings) {
+ StringBuilder builder = new StringBuilder();
+
+ for (Map.Entry classEntry : mappings.getClasses().entrySet()) {
+ String obfuscatedClassName = classEntry.getKey();
+
+ Map methodMappings = mappings.getMethods().get(obfuscatedClassName);
+ append(builder, obfuscatedClassName, methodMappings);
+ }
+ return builder.toString();
+ }
+
+ private String makeFieldOutput(Mappings mappings) {
+ StringBuilder builder = new StringBuilder();
+
+ for (Map.Entry classEntry : mappings.getClasses().entrySet()) {
+ String obfuscatedClassName = classEntry.getKey();
+
+ Map fieldMappings = mappings.getFields().get(obfuscatedClassName);
+ append(builder, obfuscatedClassName, fieldMappings);
+ }
+ return builder.toString();
+ }
+
+ private void append(StringBuilder builder, String obfuscatedClassName, Map mappings) {
+ if (mappings == null) {
+ return;
+ }
+
+ builder.append(obfuscatedClassName).append(":\n");
+
+ for (Map.Entry entry : mappings.entrySet()) {
+ String obfuscatedMethodName = entry.getKey();
+ String unObfuscatedMethodName = entry.getValue();
+
+ builder.append(obfuscatedMethodName)
+ .append(":")
+ .append(unObfuscatedMethodName)
+ .append("\n");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/deserialization/parameter/ParameterDeserializer.java b/src/main/java/org/omnimc/lumina/deserialization/parameter/ParameterDeserializer.java
new file mode 100644
index 0000000..9dbc7cb
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/deserialization/parameter/ParameterDeserializer.java
@@ -0,0 +1,177 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.deserialization.parameter;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.deserialization.AbstractMappingDeserializer;
+import org.omnimc.lumina.param.ParameterMap;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * A {@link AbstractMappingDeserializer} implementation responsible for serializing parameter mappings.
+ *
+ * The `ParameterDeserializer` handles mappings where parameters of methods are serialized into
+ * structured outputs. It generates outputs in both string and file formats, with the following structure:
+ *
+ * - Classes are prefixed with CLASS and enclosed in square brackets.
+ * - Methods are prefixed with METHOD and enclosed in square brackets.
+ * - Parameters are listed with their index and value.
+ *
+ *
+ * Examples of the serialized structure:
+ *
+ * CLASS [MyClass] {
+ * METHOD [myMethod] {
+ * 0: param1;
+ * 1: param2;
+ * };
+ * };
+ *
+ *
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class ParameterDeserializer extends AbstractMappingDeserializer {
+
+ /**
+ * Converts the parameter mappings in {@link Mappings} into a structured string representation.
+ *
+ * @param mappings The {@link Mappings} object containing mapping data.
+ * @return A structured string representation of the parameter mappings.
+ */
+ @Override
+ public String deserializeToString(@NotNull Mappings mappings) {
+ return makeOutput(mappings.getParameterMap());
+ }
+
+ /**
+ * Serializes parameter mappings from the {@link Mappings} object into a single `.parameter.mmap` file.
+ *
+ * If the file already exists, it will be overwritten.
+ *
+ * File extension validation is enforced, requiring `.parameter.mmap`. If the extension is invalid or
+ * the operation fails for any reason, the process will return {@code false} and a {@link FailedState} will
+ * be triggered.
+ *
+ * @param mappings The {@link Mappings} object containing mapping data.
+ * @param file The file to write the serialized data into.
+ * @return {@code true} if serialization is successful; {@code false} otherwise.
+ */
+ @Override
+ public boolean deserializeToFile(@NotNull Mappings mappings, @NotNull File file) {
+ Objects.requireNonNull(file);
+ Objects.requireNonNull(mappings);
+
+ if (!file.getName().endsWith(".parameter.mmap")) {
+ this.fail(FailedState.of("File has to end with `.parameter.mmap` for it to qualify!", this.getClass()));
+ return false;
+ }
+
+ if (file.exists()) {
+ file.delete();
+ }
+
+ try {
+ FileWriter writer = new FileWriter(file);
+ writer.write(makeOutput(mappings.getParameterMap()));
+ writer.flush();
+ writer.close();
+ } catch (IOException e) {
+ this.fail(FailedState.of(e, this.getClass()));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Denies support for serializing parameter mappings into multiple files.
+ *
+ * This method is deliberately unsupported, triggering a failure state when invoked.
+ *
+ * @param mappings The {@link Mappings} object.
+ * @param locations An array of file objects to write into.
+ * @return Always returns {@code false}.
+ */
+ @Override
+ public boolean deserializeToFiles(@NotNull Mappings mappings, @NotNull File[] locations) {
+ this.fail(FailedState.of("Parameter Deserializer does not support Multiple Files!", this.getClass()));
+ return false;
+ }
+
+ /**
+ * Generates a string representation of the parameter mappings.
+ *
+ * @param parameterMap The {@link ParameterMap} object to be serialized.
+ * @return A structured string representation of parameter mappings.
+ */
+ private String makeOutput(ParameterMap parameterMap) {
+ StringBuilder builder = new StringBuilder();
+
+ for (Map.Entry>> entry : parameterMap.getParameters().entrySet()) {
+ String className = entry.getKey();
+ builder.append("CLASS")
+ .append(" [")
+ .append(className)
+ .append("]")
+ .append(" {\n");
+
+ for (Map.Entry> methodEntry : entry.getValue().entrySet()) {
+ String methodName = methodEntry.getKey();
+ builder.append("\t")
+ .append("METHOD")
+ .append(" [")
+ .append(methodName)
+ .append("]")
+ .append(" {\n");
+
+ CopyOnWriteArrayList values = methodEntry.getValue();
+
+ for (int i = 0; i < values.size(); i++) {
+ builder.append("\t\t")
+ .append(i)
+ .append(": ")
+ .append(values.get(i))
+ .append(";\n");
+ }
+ builder.append("\t};\n");
+ }
+
+ builder.append("};\n");
+ }
+
+ return builder.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/param/ParameterMap.java b/src/main/java/org/omnimc/lumina/param/ParameterMap.java
new file mode 100644
index 0000000..42eba16
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/param/ParameterMap.java
@@ -0,0 +1,68 @@
+package org.omnimc.lumina.param;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * @author Caden
+ * @since 1.0.0
+ */
+public class ParameterMap {
+
+ // ClassName unobf, methodName unobf - ParamNode
+ private final Map>> parameters = new ConcurrentHashMap<>();
+
+ public Map>> getParameters() {
+ return new ConcurrentHashMap<>(parameters);
+ }
+
+ public boolean addParameterName(String className, String methodName, String paramName, int paramIndex) {
+ Map> methods = parameters.computeIfAbsent(className, k -> new ConcurrentHashMap<>());
+
+ CopyOnWriteArrayList params = methods.computeIfAbsent(methodName, k -> new CopyOnWriteArrayList<>());
+
+ while (params.size() <= paramIndex) {
+ params.add(null);
+ }
+
+ boolean isNewEntry = params.get(paramIndex) == null || !params.get(paramIndex).equals(paramName);
+
+ params.set(paramIndex, paramName);
+ methods.put(methodName, params);
+ parameters.put(className, methods);
+
+ return isNewEntry;
+ }
+
+ public String getParameterName(String className, String methodName, int index) {
+ Map> methodNames = parameters.get(className);
+ if (methodNames == null) {
+ return null;
+ }
+
+ CopyOnWriteArrayList paramNames = methodNames.get(methodName);
+ if (paramNames == null) {
+ return null;
+ }
+
+ return paramNames.get(index);
+ }
+
+ public void addAll(@NotNull Map>> other) {
+ this.parameters.putAll(other);
+ }
+
+ public void addAll(ParameterMap parameterMap) {
+ this.parameters.putAll(parameterMap.parameters);
+ }
+
+ @Override
+ public String toString() {
+ return "ParameterMap{" +
+ "parameters=" + parameters +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/param/Token.java b/src/main/java/org/omnimc/lumina/param/Token.java
new file mode 100644
index 0000000..ceba4d8
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/param/Token.java
@@ -0,0 +1,20 @@
+package org.omnimc.lumina.param;
+
+/**
+ * @author Caden
+ * @since 1.0.0
+ */
+public class Token {
+
+ public enum Type {
+ CLASS,
+ METHOD,
+ IDENTIFIER_OPEN,
+ IDENTIFIER_CLOSE,
+ BRACE_OPEN,
+ BRACE_CLOSE,
+ COMMA,
+ SEMICOLON,
+ NUMBER;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/AbstractMappingSerializer.java b/src/main/java/org/omnimc/lumina/serialization/AbstractMappingSerializer.java
new file mode 100644
index 0000000..c981d89
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/AbstractMappingSerializer.java
@@ -0,0 +1,158 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.AcceptConsumer;
+import org.omnimc.lumina.consumer.FailedState;
+
+import java.io.*;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+
+/**
+ * Abstract base class for mapping serializers, providing common logic for
+ * serializing mappings from various input sources (files, URIs, etc.).
+ *
+ * This class extends {@link AcceptConsumer} to manage serialization errors and failures,
+ * and implements the {@link MappingSerializer} interface to standardize the serialization process.
+ *
+ * Supports single-file and multi-file reading through the {@link LineSerializer} parser, with
+ * an abstract method {@code serialize} for customizing the serialization implementation.
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public abstract class AbstractMappingSerializer extends AcceptConsumer implements MappingSerializer {
+
+ /**
+ * A {@link Mappings} object to hold the parsed mappings.
+ */
+ protected final Mappings mappings = Mappings.of();
+
+ /**
+ * The {@link LineSerializer} used to parse each line of the file or input source.
+ */
+ protected final LineSerializer chosenSerializer;
+
+ /**
+ * Constructs an instance with the specified {@link LineSerializer}.
+ *
+ * @param chosenSerializer The serializer used to parse input lines.
+ */
+ protected AbstractMappingSerializer(LineSerializer chosenSerializer) {
+ this.chosenSerializer = chosenSerializer;
+ }
+
+ /**
+ * Serializes mappings from the given {@link URI} using a specified {@link LineSerializer}.
+ *
+ * @param uri The input source {@link URI}.
+ * @param parser The line parser to process the input.
+ * @return A {@link Mappings} object containing serialized mappings.
+ */
+ @Override
+ public abstract Mappings serialize(@NotNull URI uri, @NotNull LineSerializer parser);
+
+ /**
+ * Serializes mappings from the given {@link URI} using the default {@link LineSerializer}.
+ *
+ * @param uri The input source {@link URI}.
+ * @return A {@link Mappings} object containing serialized mappings.
+ */
+ @Override
+ public Mappings serialize(@NotNull URI uri) {
+ return serialize(uri, chosenSerializer);
+ }
+
+ /**
+ * Reads a single input file from the specified {@link URI} and parses it using the given {@link LineSerializer}.
+ *
+ * @param uri The location of the input file.
+ * @param parser The line parser to process each line.
+ * @return A {@link Mappings} object containing the parsed mappings, or {@link #mappings} if parsing fails.
+ */
+ protected Mappings singleFileRead(@NotNull URI uri, @NotNull LineSerializer parser) {
+ Objects.requireNonNull(uri, "URI cannot be NULL.");
+ Objects.requireNonNull(parser, "LineSerializer cannot be NULL.");
+
+ int lineNumber;
+
+ try {
+ InputStream inputStream;
+
+ if ("file".equalsIgnoreCase(uri.getScheme())) {
+ inputStream = Files.newInputStream(Path.of(uri));
+ } else if ("http".equalsIgnoreCase(uri.getScheme()) || "https".equalsIgnoreCase(uri.getScheme())) {
+ URL url = uri.toURL();
+ inputStream = url.openStream();
+ } else {
+ this.fail(FailedState.of("Unsupported URI scheme: " + uri.getScheme(), this.getClass()));
+ return null;
+ }
+
+ try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
+ LineNumberReader reader = new LineNumberReader(new InputStreamReader(bufferedInputStream))) {
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lineNumber = reader.getLineNumber();
+
+ if (!parser.serializeLine(line, mappings, getConsumer())) {
+ this.fail(FailedState.of("Failed to parse line: " + lineNumber, this.getClass()));
+ }
+ }
+ }
+
+ } catch (IOException e) {
+ this.fail(FailedState.of(e, this.getClass()));
+ return null;
+ }
+
+ return mappings;
+ }
+
+ /**
+ * Reads multiple input files from the specified array of {@link URI}s, parsing each using the given {@link LineSerializer}.
+ *
+ * @param uris An array of input {@link URI}s to parse.
+ * @param parser The line parser to process each file.
+ * @return A {@link Mappings} object containing the combined mappings from all input files.
+ */
+ protected Mappings multiFileRead(@NotNull URI[] uris, @NotNull LineSerializer parser) {
+ Objects.requireNonNull(uris, "uris cannot be NULL.");
+ Objects.requireNonNull(parser, "Parser cannot be NULL.");
+
+ for (@NotNull URI uri : uris) {
+ singleFileRead(uri, parser);
+ }
+
+ return mappings;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/LineSerializer.java b/src/main/java/org/omnimc/lumina/serialization/LineSerializer.java
new file mode 100644
index 0000000..b5192af
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/LineSerializer.java
@@ -0,0 +1,65 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization;
+
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+
+import java.util.function.Consumer;
+
+/**
+ * Represents a functional interface for parsing and serializing individual lines of input.
+ *
+ * Each implementation defines the logic for parsing a line, managing failures through
+ * the provided {@link Consumer} and updating the {@link Mappings} object.
+ *
+ * A helper method {@link #getEmptySerializer()} provides a no-op implementation that
+ * always returns {@code false} for parsing.
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public interface LineSerializer {
+
+ /**
+ * Provides a no-op implementation of {@link LineSerializer} that always fails.
+ *
+ * @return A {@link LineSerializer} instance that does nothing and fails for every line.
+ */
+ static LineSerializer getEmptySerializer() {
+ return (line, mappings, consumer) -> false;
+ }
+
+ /**
+ * Parses and serializes a single line of input and updates the given {@link Mappings} object.
+ *
+ * @param line The input line to parse.
+ * @param mappings The {@link Mappings} object to update with parsed data.
+ * @param consumer A {@link Consumer} to handle failures during serialization.
+ * @return {@code true} if the line was successfully serialized, or {@code false} otherwise.
+ */
+ boolean serializeLine(String line, Mappings mappings, Consumer consumer);
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/MappingSerializer.java b/src/main/java/org/omnimc/lumina/serialization/MappingSerializer.java
new file mode 100644
index 0000000..73f8a39
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/MappingSerializer.java
@@ -0,0 +1,82 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.MappingType;
+import org.omnimc.lumina.Mappings;
+
+import java.net.URI;
+
+/**
+ * Represents a contract for classes responsible for serializing mappings from various input sources.
+ *
+ * Implementations must provide methods to serialize mappings based on a given {@link URI},
+ * and optionally a {@link LineSerializer} or a {@link MappingType}.
+ *
+ * This interface abstracts the process of reading and converting obfuscated mappings into
+ * meaningful names using serializers.
+ *
+ * @see LineSerializer
+ * @see AbstractMappingSerializer
+ * @see Mappings
+ * @see MappingType
+ * @see URI
+ *
+ * @since 1.0.0
+ */
+public interface MappingSerializer {
+
+ /**
+ * Serializes mappings from the given {@link URI} and {@link MappingType}.
+ *
+ * The provided {@link MappingType} determines the type of {@link LineSerializer} to use.
+ *
+ * @param uri The input source {@link URI}.
+ * @param type The {@link MappingType} indicating the type of serialization to perform.
+ * @return A {@link Mappings} object containing the serialized mappings.
+ */
+ default Mappings serialize(@NotNull URI uri, MappingType type) {
+ return serialize(uri, type.getLineSerializer());
+ }
+
+ /**
+ * Serializes mappings from the given {@link URI} using the specified {@link LineSerializer}.
+ *
+ * @param uri The input source {@link URI}.
+ * @param parser The {@link LineSerializer} used to parse the input.
+ * @return A {@link Mappings} object containing the serialized mappings.
+ */
+ Mappings serialize(@NotNull URI uri, @NotNull LineSerializer parser);
+
+ /**
+ * Serializes mappings from the given {@link URI} using the default serializer.
+ *
+ * @param uri The input source {@link URI}.
+ * @return A {@link Mappings} object containing the serialized mappings.
+ */
+ Mappings serialize(@NotNull URI uri);
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/compressed/CompressedLineSerializer.java b/src/main/java/org/omnimc/lumina/serialization/compressed/CompressedLineSerializer.java
new file mode 100644
index 0000000..24d9036
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/compressed/CompressedLineSerializer.java
@@ -0,0 +1,129 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization.compressed;
+
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.serialization.LineSerializer;
+
+import java.util.function.Consumer;
+
+/**
+ * A {@link LineSerializer} implementation for processing compressed mapping lines.
+ *
+ *
This serializer processes each line in a mapping file, extracting and mapping the following types:
+ *
+ * - CLASS: Maps obfuscated class names to de-obfuscated names.
+ * - FIELD: Maps obfuscated field names to de-obfuscated names, tied to a parent class.
+ * - METHOD: Maps obfuscated method names to de-obfuscated names, tied to a parent class.
+ *
+ *
+ * Lines must follow the format: {@code TYPE OBFUSCATED_NAME:DEOBFUSCATED_NAME}.
+ *
+ * @see LineSerializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class CompressedLineSerializer implements LineSerializer {
+
+ /**
+ * Retrieves an instance of {@code CompressedLineSerializer}.
+ *
+ * @return A new instance of {@code CompressedLineSerializer}.
+ */
+ public static LineSerializer getInstance() {
+ return new CompressedLineSerializer();
+ }
+
+ /**
+ * Stores the parent class being processed to associate fields and methods with the correct class.
+ */
+ private String parentClass;
+
+ /**
+ * Parses and serializes a compressed mapping line, updating the given {@link Mappings}.
+ *
+ * @param line The line content to parse.
+ * @param mappings The {@link Mappings} instance where parsed data will be stored.
+ * @param consumer A {@link Consumer} to handle failures during processing.
+ * @return {@code true} if the line was successfully parsed, {@code false} otherwise.
+ */
+ @Override
+ public boolean serializeLine(String line, Mappings mappings, Consumer consumer) {
+ if (line == null || line.isBlank()) {
+ return false;
+ }
+
+ try {
+ int i = line.indexOf(" ");
+ if (i == -1) {
+ consumer.accept(FailedState.of("Invalid line format: missing type and value", this.getClass()));
+ return false;
+ }
+
+ String type = line.substring(0, i).trim();
+ String value = line.substring(i + 1).trim();
+
+ String[] split = value.split(":");
+ if (split.length != 2) {
+ consumer.accept(FailedState.of("Invalid value format: " + value, this.getClass()));
+ return false;
+ }
+
+ String obfuscatedName = split[0].trim();
+ String unObfuscatedName = split[1].trim();
+
+ switch (type.toUpperCase()) {
+ case "CLASS":
+ parentClass = obfuscatedName;
+ mappings.addClass(obfuscatedName, unObfuscatedName);
+ break;
+ case "FIELD":
+ if (parentClass == null) {
+ consumer.accept(FailedState.of("FIELD entry without a parent class: " + line, this.getClass()));
+ return false;
+ }
+ mappings.addField(parentClass, obfuscatedName, unObfuscatedName);
+ break;
+ case "METHOD":
+ if (parentClass == null) {
+ consumer.accept(FailedState.of("METHOD entry without a parent class: " + line, this.getClass()));
+ return false;
+ }
+ mappings.addMethod(parentClass, obfuscatedName, unObfuscatedName);
+ break;
+ default:
+ consumer.accept(FailedState.of("Unknown type: " + type, this.getClass()));
+ return false;
+ }
+
+ return true;
+ } catch (Exception e) {
+ consumer.accept(FailedState.of(e, this.getClass()));
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/compressed/CompressedSerializer.java b/src/main/java/org/omnimc/lumina/serialization/compressed/CompressedSerializer.java
new file mode 100644
index 0000000..375dbec
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/compressed/CompressedSerializer.java
@@ -0,0 +1,85 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization.compressed;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.serialization.AbstractMappingSerializer;
+import org.omnimc.lumina.serialization.LineSerializer;
+
+import java.net.URI;
+
+/**
+ * A serializer implementation for handling compressed mapping files.
+ *
+ * This class extends {@link AbstractMappingSerializer} and processes files
+ * with a `.mmap` extension using the {@link CompressedLineSerializer}. It ensures
+ * that only valid compressed mapping parsers are used during serialization.
+ *
+ * Usage: Compressed mapping files should adhere to a specific format
+ * containing information about classes, methods, and fields in a compact representation.
+ *
+ * @see AbstractMappingSerializer
+ * @see CompressedLineSerializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class CompressedSerializer extends AbstractMappingSerializer {
+
+ /**
+ * Constructs a {@code CompressedSerializer} with the {@link CompressedLineSerializer} as its default parser.
+ */
+ protected CompressedSerializer() {
+ super(CompressedLineSerializer.getInstance());
+ }
+
+ /**
+ * Serializes mappings from a given {@link URI} using {@link CompressedLineSerializer}.
+ *
+ * This method validates that the provided parser is an instance of {@link CompressedLineSerializer}.
+ * Additionally, it ensures that the mapping file has a `.mmap` extension, failing the operation otherwise.
+ *
+ * @param uri The input URI representing the mapping file.
+ * @param parser The parser, which must be a {@link CompressedLineSerializer}.
+ * @return A {@link Mappings} object containing the serialized mappings, or {@code null} if parsing fails.
+ */
+ @Override
+ public Mappings serialize(@NotNull URI uri, @NotNull LineSerializer parser) {
+ if (!(parser instanceof CompressedLineSerializer)) {
+ this.fail(FailedState.of("You cannot use non Compressed Parsers", this.getClass()));
+ return null;
+ }
+
+ String uriName = uri.toString();
+ if (!uriName.endsWith(".mmap")) {
+ this.fail(FailedState.of("URI does not end with .mmap", this.getClass()));
+ return null;
+ }
+
+ return super.singleFileRead(uri, parser);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/full/FullPathResolver.java b/src/main/java/org/omnimc/lumina/serialization/full/FullPathResolver.java
new file mode 100644
index 0000000..54c5037
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/full/FullPathResolver.java
@@ -0,0 +1,63 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization.full;
+
+/**
+ * Defines a structure for resolving the paths to class, method, and field mapping files within a directory.
+ *
+ * This record specifies the relative locations of mapping files inside a directory
+ * to support the {@link FullSerializer} in reading structured mappings.
+ *
+ * For example:
+ *
+ * - {@code classLocation} defines the file name or path for class mappings (e.g., "class.mmap").
+ * - {@code methodLocation} defines the file name or path for method mappings (e.g., "method.mmap").
+ * - {@code fieldLocation} defines the file name or path for field mappings (e.g., "field.mmap").
+ *
+ *
+ * @param classLocation The relative path or file name for class mappings.
+ * @param methodLocation The relative path or file name for method mappings.
+ * @param fieldLocation The relative path or file name for field mappings.
+ *
+ * @see FullSerializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public record FullPathResolver(String classLocation, String methodLocation, String fieldLocation) {
+
+ public static FullPathResolver of(String classLocation, String methodLocation, String fieldLocation) {
+ return new FullPathResolver(classLocation, methodLocation, fieldLocation);
+ }
+
+ @Override
+ public String toString() {
+ return "FullPathResolver{" +
+ "classLocation='" + classLocation + '\'' +
+ ", methodLocation='" + methodLocation + '\'' +
+ ", fieldLocation='" + fieldLocation + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/full/FullSerializer.java b/src/main/java/org/omnimc/lumina/serialization/full/FullSerializer.java
new file mode 100644
index 0000000..3ee8818
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/full/FullSerializer.java
@@ -0,0 +1,153 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization.full;
+
+import org.jetbrains.annotations.NotNull;
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.serialization.AbstractMappingSerializer;
+import org.omnimc.lumina.serialization.LineSerializer;
+import org.omnimc.lumina.serialization.full.line.ClassLineSerializer;
+import org.omnimc.lumina.serialization.full.line.FieldLineSerializer;
+import org.omnimc.lumina.serialization.full.line.MethodLineSerializer;
+
+import java.net.URI;
+import java.util.Objects;
+
+/**
+ * A serializer implementation for handling full mappings stored in structured directories or files.
+ *
+ * This class extends {@link AbstractMappingSerializer} and processes mappings
+ * from files with extensions such as `.class.mmap`, `.method.mmap`, and `.field.mmap`.
+ * It also allows handling structured directories with pre-defined paths for mapping files.
+ *
+ * Line serialization is delegated to the following line serializers:
+ *
+ * - {@link ClassLineSerializer} for class mappings.
+ * - {@link FieldLineSerializer} for field mappings.
+ * - {@link MethodLineSerializer} for method mappings.
+ *
+ *
+ * @see AbstractMappingSerializer
+ * @see FullPathResolver
+ * @see ClassLineSerializer
+ * @see FieldLineSerializer
+ * @see MethodLineSerializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class FullSerializer extends AbstractMappingSerializer {
+
+ /**
+ * Resolves the locations of class, method, and field mapping files in a directory.
+ */
+ private final FullPathResolver resolver;
+
+ /**
+ * Constructs a {@code FullSerializer} instance with the specified {@link FullPathResolver}.
+ *
+ * @param resolver The resolver for locating mapping files within a directory.
+ */
+ public FullSerializer(@NotNull FullPathResolver resolver) {
+ super(LineSerializer.getEmptySerializer());
+ Objects.requireNonNull(resolver);
+ this.resolver = resolver;
+ }
+
+ /**
+ * Serializes mappings from the specified URI using the correct line serializer.
+ *
+ * This method determines the type of file (class, method, field) based on the file extension
+ * or processes a directory containing structured mapping files. It ensures that only the
+ * * {@link LineSerializer#getEmptySerializer()} is used as a parser for the operation.
+ *
+ * @param uri The input URI representing the directory or mapping file.
+ * @param parser The line parser, which must be {@link LineSerializer#getEmptySerializer()}.
+ * @return A {@link Mappings} object containing the serialized mappings or {@code null} if an error occurs.
+ */
+ @Override
+ public Mappings serialize(@NotNull URI uri, @NotNull LineSerializer parser) {
+ if ((parser != LineSerializer.getEmptySerializer())) {
+ this.fail(FailedState.of("Cannot accept any parser except `LineSerializer.getEmptySerializer`!", this.getClass()));
+ return null;
+ }
+
+ String uriFull = uri.toString();
+
+ try {
+ if (uriFull.endsWith("/")) {
+ return readDirectoryMappings(uriFull);
+ } else if (uriFull.endsWith(".class.mmap")) {
+ return singleFileRead(uri, new ClassLineSerializer());
+ } else if (uriFull.endsWith(".method.mmap")) {
+ return singleFileRead(uri, new MethodLineSerializer());
+ } else if (uriFull.endsWith(".field.mmap")) {
+ return singleFileRead(uri, new FieldLineSerializer());
+ } else {
+ this.fail(FailedState.of("Unsupported file format: " + uriFull, this.getClass()));
+ return null;
+ }
+ } catch (IllegalArgumentException e) {
+ this.fail(FailedState.of("Invalid URI syntax: " + uriFull, this.getClass()));
+ return null;
+ } catch (Exception e) {
+ this.fail(FailedState.of("Unexpected error while reading mappings: " + e.getMessage(), this.getClass()));
+ return null;
+ }
+ }
+
+ /**
+ * Reads mappings from a structured directory defined by the {@link FullPathResolver}.
+ *
+ * The directory must contain files at the paths specified by the resolver:
+ * {@code classLocation}, {@code methodLocation}, and {@code fieldLocation}.
+ *
+ * @param uriFull A string representation of the URI pointing to the directory.
+ * @return A {@link Mappings} object containing the combined serialized mappings from all files.
+ */
+ private Mappings readDirectoryMappings(String uriFull) {
+ try {
+ String classLocation = uriFull + resolver.classLocation();
+ String methodLocation = uriFull + resolver.methodLocation();
+ String fieldLocation = uriFull + resolver.fieldLocation();
+
+ URI classURI = URI.create(classLocation);
+ mappings.addAll(singleFileRead(classURI, new ClassLineSerializer()));
+
+ URI methodURI = URI.create(methodLocation);
+ mappings.addAll(singleFileRead(methodURI, new MethodLineSerializer()));
+
+ URI fieldURI = URI.create(fieldLocation);
+ mappings.addAll(singleFileRead(fieldURI, new FieldLineSerializer()));
+ } catch (IllegalArgumentException e) {
+ this.fail(FailedState.of("Invalid directory structure or URI syntax: " + uriFull, this.getClass()));
+ } catch (Exception e) {
+ this.fail(FailedState.of("Unexpected error while reading directory mappings: " + e.getMessage(), this.getClass()));
+ }
+
+ return mappings;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/full/line/ClassLineSerializer.java b/src/main/java/org/omnimc/lumina/serialization/full/line/ClassLineSerializer.java
new file mode 100644
index 0000000..5d84e65
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/full/line/ClassLineSerializer.java
@@ -0,0 +1,81 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization.full.line;
+
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.serialization.LineSerializer;
+
+import java.util.function.Consumer;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * A {@link LineSerializer} implementation that serializes class mappings from textual entries.
+ *
+ * This serializer processes each line in the format `obfuscated:unobfuscated`,
+ * where:
+ *
+ * - obfuscated: The obfuscated class name.
+ * - unobfuscated: The corresponding de-obfuscated class name.
+ *
+ *
+ * If the format is invalid or any parsing error occurs, the operation fails with a {@link FailedState}.
+ *
+ * @see LineSerializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class ClassLineSerializer implements LineSerializer {
+
+ /**
+ * Parses and serializes a class mapping line into the {@link Mappings} object.
+ *
+ * @param line The line to serialize, expected in the format `obfuscated:unobfuscated`.
+ * @param mappings The {@link Mappings} object to store the serialized class mappings.
+ * @param consumer A {@link Consumer} to handle failures during serialization.
+ * @return {@code true} if the line was successfully serialized; otherwise, {@code false}.
+ */
+ @Override
+ public boolean serializeLine(String line, Mappings mappings, Consumer consumer) {
+ try {
+ String[] split = line.split(":");
+ if (split.length != 2) {
+ consumer.accept(FailedState.of("Invalid value format: " + line, this.getClass()));
+ return false;
+ }
+
+ String obfuscatedName = split[0].trim();
+ String unObfuscatedName = split[1].trim();
+
+ mappings.addClass(obfuscatedName, unObfuscatedName);
+ } catch (PatternSyntaxException e) {
+ consumer.accept(FailedState.of(e, this.getClass()));
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/full/line/FieldLineSerializer.java b/src/main/java/org/omnimc/lumina/serialization/full/line/FieldLineSerializer.java
new file mode 100644
index 0000000..b1f9dc9
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/full/line/FieldLineSerializer.java
@@ -0,0 +1,112 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization.full.line;
+
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.serialization.LineSerializer;
+
+import java.util.function.Consumer;
+
+/**
+ * A {@link LineSerializer} implementation that serializes field mappings from textual entries.
+ *
+ * This serializer processes lines in the following formats:
+ *
+ * - Parent Class Definition: Ends with a colon (`:`). Declares the parent class for subsequent entries.
+ * - Field Entries: Follow the format `obfuscated:unobfuscated`, defining a mapping for a field
+ * under the currently defined parent class.
+ *
+ *
+ * If no parent class is defined prior to parsing a field entry, or if the format is invalid, the operation fails
+ * with a {@link FailedState}.
+ *
+ * @see LineSerializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class FieldLineSerializer implements LineSerializer {
+
+ /**
+ * Stores the currently defined parent class for field entries.
+ */
+ private String parentClass;
+
+ /**
+ * Parses and serializes a field mapping line into the {@link Mappings} object.
+ *
+ * The parsing operates as follows:
+ *
+ * - If the line ends with a colon (`:`), it sets the parent class for subsequent field entries.
+ * - If the line is a field mapping (`obfuscated:unobfuscated`), it associates the mapping with the current parent class.
+ * - If the format is invalid or no parent class is defined, the {@link Consumer} handles a failure.
+ *
+ *
+ * @param line The line to serialize.
+ * @param mappings The {@link Mappings} object to store the serialized field mappings.
+ * @param consumer A {@link Consumer} to handle failures during serialization.
+ * @return {@code true} if the line was successfully serialized; otherwise, {@code false}.
+ */
+ @SuppressWarnings("DuplicatedCode")
+ @Override
+ public boolean serializeLine(String line, Mappings mappings, Consumer consumer) {
+ if (line == null || line.isBlank()) {
+ consumer.accept(FailedState.of("Line cannot be null or empty!", this.getClass()));
+ return false;
+ }
+
+ if (line.endsWith(":")) {
+ parentClass = line.substring(0, line.length() - 1).trim();
+ if (parentClass.isEmpty()) {
+ consumer.accept(FailedState.of("Parent class name cannot be empty!", this.getClass()));
+ return false;
+ }
+ return true;
+ }
+
+ if (parentClass == null) {
+ consumer.accept(FailedState.of("No parent class defined for line: " + line, this.getClass()));
+ return false;
+ }
+
+ String[] split = line.split(":");
+ if (split.length != 2) {
+ consumer.accept(FailedState.of("Invalid line format, expected 'obfuscated:unobfuscated': " + line, this.getClass()));
+ return false;
+ }
+
+ String obfuscatedName = split[0].trim();
+ String unobfuscatedName = split[1].trim();
+
+ if (obfuscatedName.isEmpty() || unobfuscatedName.isEmpty()) {
+ consumer.accept(FailedState.of("Obfuscated or unobfuscated name cannot be empty: " + line, this.getClass()));
+ return false;
+ }
+
+ mappings.addField(parentClass, obfuscatedName, unobfuscatedName);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/omnimc/lumina/serialization/full/line/MethodLineSerializer.java b/src/main/java/org/omnimc/lumina/serialization/full/line/MethodLineSerializer.java
new file mode 100644
index 0000000..6febedc
--- /dev/null
+++ b/src/main/java/org/omnimc/lumina/serialization/full/line/MethodLineSerializer.java
@@ -0,0 +1,112 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024-2025 OmniMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.omnimc.lumina.serialization.full.line;
+
+import org.omnimc.lumina.Mappings;
+import org.omnimc.lumina.consumer.FailedState;
+import org.omnimc.lumina.serialization.LineSerializer;
+
+import java.util.function.Consumer;
+
+/**
+ * A {@link LineSerializer} implementation that serializes method mappings from textual entries.
+ *
+ * This serializer processes lines in the following formats:
+ *
+ * - Parent Class Definition: Ends with a colon (`:`). Declares the parent class for subsequent entries.
+ * - Method Entries: Follow the format `obfuscated:unobfuscated`, defining a mapping for a method
+ * under the currently defined parent class.
+ *
+ *
+ * If no parent class is defined prior to parsing a method entry, or if the format is invalid, the operation fails
+ * with a {@link FailedState}.
+ *
+ * @see LineSerializer
+ *
+ * @author Caden
+ * @since 1.0.0
+ */
+public class MethodLineSerializer implements LineSerializer {
+
+ /**
+ * Stores the currently defined parent class for method entries.
+ */
+ private String parentClass;
+
+ /**
+ * Parses and serializes a method mapping line into the {@link Mappings} object.
+ *
+ * The parsing operates as follows:
+ *
+ * - If the line ends with a colon (`:`), it sets the parent class for subsequent method entries.
+ * - If the line is a method mapping (`obfuscated:unobfuscated`), it associates the mapping with the current parent class.
+ * - If the format is invalid or no parent class is defined, the {@link Consumer} handles a failure.
+ *
+ *
+ * @param line The line to serialize.
+ * @param mappings The {@link Mappings} object to store the serialized method mappings.
+ * @param consumer A {@link Consumer} to handle failures during serialization.
+ * @return {@code true} if the line was successfully serialized; otherwise, {@code false}.
+ */
+ @SuppressWarnings("DuplicatedCode")
+ @Override
+ public boolean serializeLine(String line, Mappings mappings, Consumer consumer) {
+ if (line == null || line.isBlank()) {
+ consumer.accept(FailedState.of("Line cannot be null or empty!", this.getClass()));
+ return false;
+ }
+
+ if (line.endsWith(":")) {
+ parentClass = line.substring(0, line.length() - 1).trim();
+ if (parentClass.isEmpty()) {
+ consumer.accept(FailedState.of("Parent class name cannot be empty!", this.getClass()));
+ return false;
+ }
+ return true;
+ }
+
+ if (parentClass == null) {
+ consumer.accept(FailedState.of("No parent class defined for line: " + line, this.getClass()));
+ return false;
+ }
+
+ String[] split = line.split(":");
+ if (split.length != 2) {
+ consumer.accept(FailedState.of("Invalid line format, expected 'obfuscated:unobfuscated': " + line, this.getClass()));
+ return false;
+ }
+
+ String obfuscatedName = split[0].trim();
+ String unobfuscatedName = split[1].trim();
+
+ if (obfuscatedName.isEmpty() || unobfuscatedName.isEmpty()) {
+ consumer.accept(FailedState.of("Obfuscated or unobfuscated name cannot be empty: " + line, this.getClass()));
+ return false;
+ }
+
+ mappings.addMethod(parentClass, obfuscatedName, unobfuscatedName);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/map_data.compressed.json b/src/main/resources/map_data.compressed.json
new file mode 100644
index 0000000..6020716
--- /dev/null
+++ b/src/main/resources/map_data.compressed.json
@@ -0,0 +1,4 @@
+{
+ "type": "COMPRESSED",
+ "location": "*.mmap"
+}
\ No newline at end of file
diff --git a/src/main/resources/map_data.full.json b/src/main/resources/map_data.full.json
new file mode 100644
index 0000000..6662b4f
--- /dev/null
+++ b/src/main/resources/map_data.full.json
@@ -0,0 +1,8 @@
+{
+ "type": "FULL",
+ "location": {
+ "class": "*.class.mmap",
+ "method": "*.method.mmap",
+ "field": "*.field.mmap"
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/Test.java b/src/test/java/Test.java
new file mode 100644
index 0000000..cd0d947
--- /dev/null
+++ b/src/test/java/Test.java
@@ -0,0 +1,13 @@
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Caden
+ * @since 1.0.0
+ */
+public class Test {
+
+ public static void main(String[] args) throws IOException {
+
+ }
+}
\ No newline at end of file