let it leave me like a long breath

let it dissipate or fade in the background

Nov. 19th, 2017

Profile

xax: purple-orange {11/3 knotwork star, pointed down (Default)
howling howling howling

Nav

  • Recent Entries
  • Archive
  • Reading
  • Tags
  • Memories
  • Profile

Tags

  • art - 2 uses
  • asteroid garden - 4 uses
  • code - 19 uses
  • demos - 1 use
  • dreams - 5 uses
  • ff7 fangame - 23 uses
  • fic prompts - 13 uses
  • gamedev challenge - 82 uses
  • hell game - 76 uses
  • nanowrimo - 11 uses
  • plants - 9 uses
  • process - 52 uses
  • programming - 51 uses
  • screenshots - 5 uses
  • writing log - 83 uses

May 2025

S M T W T F S
    123
45678 910
1112131415 1617
18192021222324
25262728293031
    • Previous Day
    • |
    • Next Day

    Nov. 19th, 2017

  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    Tags:
    • programming
    posted @ 09:04 pm

    ooof after dawdling on it for like two months i finally got the hell's half-acre plant parser to a stable state. not a working stable state, mind you. just one that doesn't crash.

    (okay admittedly about half the delay here was because i got super sick. but. half the delay was just me being lazy.)

    it was also an interesting test of coming back to java after some time away? the language itself still seems fairly painless, it's just that everything built on top of it seems... bad. or maybe "unwieldy"; i'm in this situation where i'm using GSON (the google json library) to decode data files. the default is apparently to use reflection to shotgun all object properties into a json object, and then do the reverse when deserializing. (i didn't actually try running it with any defaults, because it seemed like that would be a huge mess.) but you can also write a custom serializer/deserializer, which lets you shape the files a little bit smoother. so far so good.

    there are a few things that go wrong at this point.

    first, the deserializers take the form of a type instance: class ... implements JsonDeserializer<T>. this means, barring any wacky class Thing<T> implements JsonDeserializer<T> antics (where you'd have to instance them with a deserialize function, i guess?), you're stuck making one class per type you want to deserialize. and because of the way java works, each class needs to be in its own code file. if you have ten data structures to decode, you're gonna need an entire folder devoted to those ten classes that exist only to be instanced once.

    secondly, you have to explicitly register these custom deserializers, on a per-value basic -- the deserialization is all done through a class Gson, which instances of have a fromJson function. if you want it to check for custom deserializers, you need to build a gson value, and call .registerTypeAdapter(Type type, Object typeAdapter) on it. the object is an instance of a thing with the correct deserializing instance, and the type is the type it deserializes. it's entirely possible for them to not match, and i have no clue what happens if they do.

    (an aside: Type here is generally the .class value of the type, but since parametric types (Type<T>) don't have .class values, you have to make a type token for them. this isn't really that annoying, but it's another example of how the basic unit of code in java is assumed to be the class, not the instance.)

    where registering gets really annoying, though, is when you have nested objects to deserialize. because those deserializing instances then need to call fromJson from within their deserialize functions. which appears to mean that i need to have code like

    ThingDeserializer thingDeserializer = new ThingDeserializer();
    Gson gson = new gsonBuilder()
        .registerTypeAdapter (Thing.class, thingDeserializer)
        .create();
    thingDeserializer.setGson (gson);

    so that thingDeserializer has a gson value with all the custom handlers set that it can use in its deserializing function. only since there are like ten of them, it's actually more like

    FooDeserializer fooDeserializer = new FooDeserializer();
    BarDeserializer barDeserializer = new BarDeserializer();
    BazDeserializer bazDeserializer = new BazDeserializer();
    QuuxDeserializer quuxDeserializer = new QuuxDeserializer();
    BlorchDeserializer blorchDeserializer = new BlorchDeserializer();
    Gson gson = new gsonBuilder()
        .registerTypeAdapter (Foo.class, fooDeserializer)
        .registerTypeAdapter (Bar.class, barDeserializer)
        .registerTypeAdapter (Baz.class, bazDeserializer)
        .registerTypeAdapter (Quux.class, quuxDeserializer)
        .registerTypeAdapter (Blorch.class, blorchDeserializer)
        .create();
    fooDeserializer.setGson (gson);
    barDeserializer.setGson (gson);
    bazDeserializer.setGson (gson);
    quuxDeserializer.setGson (gson);
    blorchDeserializer.setGson (gson);

    and it's kind of a gigantic mess of boilerplate.

    third, it seems like manually writing deserializers isn't really encouraged -- it sounds like the suggested workflow is dumping and restoring huge opaque data globs that contain all the perhaps-transitory internal state, and trusting that nothing in the internals of the type has changed between when it got dumped and when it got restored. so what you actually have to write for the deserialize function is like. hey here's a JsonElement that you can call .getAsInt or .getAsJsonArray or .getAsJsonObject or .getAsString on, and i guess from all of those things you need to cobble together some parsing. like, if you have "{"name": "foobar"}", to get to the name value you'd have to have, like, elem.getAsJsonObject.get("name").getAsString(), and if any of those lookups don't correspond to the data, well, i hope you enjoy null reference errors. (i've been wrapping them in Optional, but that can only really do so much, and like,

    Optional.of(elem)
        .map (e -> e.getAsJsonObject())
        .map (e -> e.get("name"))
        .map (e -> e.getAsString())

    ISN'T EXACTLY AN IMPROVEMENT HERE. might as well just wrap a try around everything and hope for the best.)

    anyway it's working but not as flexible as it needs to be, and it's not loading/using the textures correctly or something. still, it's nice making progress on this again.

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
    • Previous Day
    • |
    • Next Day
Page generated Jun. 9th, 2025 07:55 am
Powered by Dreamwidth Studios

Style Credit

  • Style: (No Theme) for vertical