Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4316f47
[KillTheRNG] Improve squid rng
ScribbleTAS Jun 19, 2026
959c0fa
[Savestates] First look at storing entity AI in savestates
ScribbleTAS Jun 19, 2026
230600c
[Savestates] Store revenge target and last attacked
ScribbleTAS Jul 12, 2026
45a03b4
[Savestates] Trying to add EntityAiTaskStorage
ScribbleTAS Jul 28, 2026
ede97bf
Trying to add gson again for readability
ScribbleTAS Jul 28, 2026
2c0db85
[Savestates] Update EntityAI deserialisation to merge with vanilla ac…
ScribbleTAS Aug 22, 2026
7a1d5f5
[Savestates] Merge SquidRotation, BatSpawn and TickTimers json into E…
ScribbleTAS Aug 26, 2026
f8b1ee8
[Savestates] Fix sub storage not working correctly
ScribbleTAS Aug 29, 2026
fd144a8
[Savestates] Fix entity AI not being applied correctly
ScribbleTAS Aug 29, 2026
f25ab40
[Savestates] Add PathFinding to sub storage
ScribbleTAS Aug 31, 2026
3fc91f9
[KillTheRNG] Add AI task changes to rng log
ScribbleTAS Sep 1, 2026
3d3e1e6
[Savestates] Actually apply the stored pathfinding to the entity
ScribbleTAS Sep 1, 2026
e3da868
[Savestates] Fixed panic task lasting too long
ScribbleTAS Sep 2, 2026
1316b79
[Savestates] Remove debug mixin
ScribbleTAS Sep 2, 2026
60c0988
[Savestates] Add attackTarget to savestates
ScribbleTAS Sep 2, 2026
9184634
[Savestates] Store fields from super class in entityai
ScribbleTAS Sep 2, 2026
022bf42
[Savestates] Failing to add a type adapter for path navigate
ScribbleTAS Sep 9, 2026
d757f2d
[MCTCommon] Create Gson Wrapper
ScribbleTAS Sep 9, 2026
9778534
[MCTCommon] Add TypeAdapterGenerator
ScribbleTAS Sep 11, 2026
c168082
[MCTCommon] Continue typeadapter generator
ScribbleTAS Sep 21, 2026
d78bb26
[Savestates] Generate EntityAI typeadapters
ScribbleTAS Sep 21, 2026
33d6140
[Savestates] Add improved serialisation
ScribbleTAS Sep 21, 2026
ef4bed3
Disable generator test
ScribbleTAS Sep 21, 2026
70d6185
[Savestates] More type adapters, more generators
ScribbleTAS Sep 21, 2026
1b133f6
[Savestates] Fix AI task deserialisation
ScribbleTAS Sep 27, 2026
0553709
[Savestates] Experimental FineTypeAdapter setting for targetting Anon…
ScribbleTAS Sep 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ dependencies {
// tasmod dependencies
embed "com.dselent:bigarraylist:1.6"
embed "com.github.KaptainWutax:SeedUtils:b6a383113c"

implementation "com.google.code.gson:gson:2.14.0"

// loom dependencies
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings ploceus.mcpMappings(project.mcp_channel, project.mcp_mcversion, project.mcp_build)
Expand Down
58 changes: 58 additions & 0 deletions src/main/java/com/minecrafttas/mctcommon/json/FineField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.minecrafttas.mctcommon.json;

import com.google.gson.JsonElement;

public class FineField {

private final String name;
private final FineMode mode;
private final FineSerializer serializer;
private final FineDeserializer deserializer;

public FineField(String name, FineMode mode) {
this.name = name;
this.mode = mode;
this.serializer = null;
this.deserializer = null;
}

public FineField(String name, FineSerializer serializer, FineDeserializer deserializer) {
this.name = name;
this.mode = FineMode.CUSTOM;
this.serializer = serializer;
this.deserializer = deserializer;
}

public static enum FineMode {
FINE,
EXCLUDED,
GSON,
CUSTOM;
}

public String getName() {
return name;
}

public FineMode getMode() {
return mode;
}

public JsonElement serialize(Object obj, FineGson fgson) {
return serializer.serialize(obj, fgson);
}

public Object deserialize(JsonElement element, FineGson fgson) {
return deserializer.deserialize(element, fgson);
}

@FunctionalInterface
public static interface FineSerializer {
public JsonElement serialize(Object obj, FineGson fgson);
}

@FunctionalInterface
public static interface FineDeserializer {
public Object deserialize(JsonElement element, FineGson fgson);
}
}
148 changes: 148 additions & 0 deletions src/main/java/com/minecrafttas/mctcommon/json/FineGson.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package com.minecrafttas.mctcommon.json;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.internal.ConstructorConstructor;
import com.google.gson.reflect.TypeToken;

/**
* A fine grained gson replacement
*
* @author Scribble
*/
public class FineGson {

private TypeAdapterMap typeAdapters = new TypeAdapterMap();

private final Gson gsonInstance;

public FineGson(Gson gsonInstance) {
this.gsonInstance = gsonInstance;
}

public void registerTypeAdapter(Class<?> type) {
if (type.isAnnotationPresent(FineMultiTarget.class)) {
List<Class<?>> classes = Arrays.asList(type.getDeclaredClasses());
for (Class<?> clazz : classes) {
registerTypeAdapter(clazz);
}
}
if (type.isAnnotationPresent(FineTarget.class)) {
if (!FineTypeAdapter.class.isAssignableFrom(type)) {
throw new RuntimeException(String.format("Trying to register type adapter %s, but it doesn't extend FineTypeAdapter", type.getName()));
}
FineTarget fineTargetAnnotation = type.getAnnotation(FineTarget.class);
Class<?> targetType = fineTargetAnnotation.value();
FineTypeAdapter adapter;

try {
adapter = (FineTypeAdapter) type.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(String.format("Failed to instantiate type adapter %s", type.getName()), e);
}
registerTypeAdapter(targetType, adapter);
}
}

public void registerTypeAdapter(Class<?> type, FineTypeAdapter adapter) {
typeAdapters.put(type, adapter);
}

public JsonElement serialize(Object obj) {
if (obj == null)
return JsonNull.INSTANCE;
Class<?> type = obj.getClass();
return serialize(obj, type);
}

public JsonElement serialize(Object obj, Class<?> type) {
if (!typeAdapters.containsKey(type))
return gsonInstance.toJsonTree(obj);

FineTypeAdapter adapter = typeAdapters.get(type);
JsonElement out = adapter.serialize(obj, this, type);

Class<?> superclass = type.getSuperclass();
if (superclass != Object.class) {
JsonObject superObject = serialize(obj, superclass).getAsJsonObject();
JsonObject jsonObj = out.getAsJsonObject();
for (Entry<String, JsonElement> objects : superObject.entrySet()) {
jsonObj.add(objects.getKey(), objects.getValue());
}
out = jsonObj;
}

return out;
}

public Object deserialize(JsonElement element, Class<?> type) {
if (!typeAdapters.containsKey(type))
return gsonInstance.fromJson(element, type);
Object obj = constructNew(type);
return deserialize(element, type, obj);
}

public Object deserialize(JsonElement element, Class<?> type, Object existing) {
if (!typeAdapters.containsKey(type))
return gsonInstance.fromJson(element, type);

FineTypeAdapter adapter = typeAdapters.get(type);
Object out = adapter.deserialize(element, type, this, existing);

Class<?> superclass = type.getSuperclass();
if (superclass != Object.class) {
FineTypeAdapter superadapter = typeAdapters.get(superclass);
out = superadapter.deserialize(element, superclass, this, out);
}
return out;
}

public Gson getGsonInstance() {
return gsonInstance;
}

public Map<Class<?>, FineTypeAdapter> getTypeAdapters() {
return typeAdapters;
}

private class TypeAdapterMap extends HashMap<Class<?>, FineTypeAdapter> {

@Override
public boolean containsKey(Object key) {
return get(key) != null;
}

@Override
public FineTypeAdapter get(Object key) {
Class<?> classKey = (Class<?>) key;
if (classKey.isAnonymousClass()) {
for (FineTypeAdapter adapter : values()) {
FineTarget fineTargetAnnotation = adapter.getClass().getAnnotation(FineTarget.class);
if (fineTargetAnnotation == null)
continue;
Class<?> enclosingType = fineTargetAnnotation.enclosingclazz();
Class<?> superType = fineTargetAnnotation.superclazz();
if (classKey.getEnclosingClass() == enclosingType && classKey.getSuperclass() == superType)
return adapter;
}
return null;
}
return super.get(key);
}
}

public static <T> T constructNew(Class<T> clazz) {
ConstructorConstructor constructor = new ConstructorConstructor(Collections.emptyMap(), true, Collections.emptyList());
TypeToken<T> token = TypeToken.get(clazz);
return constructor.get(token, true).construct();
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/minecrafttas/mctcommon/json/FineMultiTarget.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.minecrafttas.mctcommon.json;

import static java.lang.annotation.ElementType.TYPE;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface FineMultiTarget {

}
17 changes: 17 additions & 0 deletions src/main/java/com/minecrafttas/mctcommon/json/FineTarget.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.minecrafttas.mctcommon.json;

import static java.lang.annotation.ElementType.TYPE;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface FineTarget {
Class<?> value() default Object.class;

Class<?> superclazz() default Object.class;

Class<?> enclosingclazz() default Object.class;
}
Loading
Loading