sisby-folk / switchy

A minecraft mod that combines player personalization features from other mods into presets.
https://modrinth.com/mod/switchy
GNU Lesser General Public License v3.0
12 stars 8 forks source link

Fix Figura compatibility #76

Closed GrandpaScout closed 1 month ago

GrandpaScout commented 3 months ago

Fabric expects a public constructor with no parameters to be the entrypoint.

Figura will later use build(Avatar) to run the private SwitchyFiguraApi(Avatar) constructor.

From my quick testing this does not cause any issues. Should fix #75

GrandpaScout commented 3 months ago

I made a pull request to the 1.19 branch specifically since it is listed as the main branch but from what I can see this affects all versions.

GrandpaScout commented 3 months ago

Seems like there's more issues with Figura compat that need addressed.

GrandpaScout commented 3 months ago

Considering the idea of turning this compat into a true Figura Event instead. Then users could just do

events["SWITCHY.SWITCH"]:register(function(newpreset, oldpreset, enabledmodules)
  -- blah blah
end)

and it would Just Work™

edit: I have decided to go against that idea mostly because Java is a pain to work with.

sisby-folk commented 3 months ago

Looks good to us - can you send through the reference / code you had for how proper figura events are set up? we couldl take a look.

GrandpaScout commented 3 months ago

I tried to make the code in the code block below which works fine until it tries to compile .getUser(), after which it throws an error in gradle. Something about missing the Minecraft Entity class. I think it probably has something to do with mappings but I'm not familiar enough with Minecraft modding to be sure. There's probably a fix for this that I'm not smart enough to see.

FiguraMC has an example of how an event should be set up at https://github.com/FiguraMC/Example-Figura-Plugin/blob/main/common/src/main/java/org/figuramc/exampleplugin/ExampleEventPlugin.java

The code below defines two events: SWITCHY.SWITCH for when someone switches in render distance of the current client, and SWITCHY.WORLD_SWITCH when someone switches as long as their avatar is loaded in by the current client. These events use different instruction limits, WORLD_SWITCH uses the WORLD_TICK limit of 128 instructions and is meant for global changes like nameplates and SWITCH uses the TICK limit of around 32k instructions and is meant for full model changes. The other reason for both of them is that WORLD_SWITCH might not have the current player loaded while SWITCH will always have the current player loaded.

./compat/src/main/java/folk/sisby/switchy/client/FiguraSwitchyEvent.java

package folk.sisby.switchy.client;

import folk.sisby.switchy.client.api.SwitchyClientEvents;
import com.mojang.datafixers.util.Pair;
import org.figuramc.figura.entries.FiguraEvent;
import org.figuramc.figura.entries.annotations.FiguraEventPlugin;
import org.figuramc.figura.lua.LuaWhitelist;
import org.figuramc.figura.lua.api.event.LuaEvent;
import org.figuramc.figura.lua.docs.LuaFieldDoc;
import org.figuramc.figura.avatar.AvatarManager;
import org.figuramc.figura.avatar.Avatar;

import java.util.Collection;
import java.util.List;

@FiguraEventPlugin
public class FiguraSwitchyEvent implements FiguraEvent {
  @LuaWhitelist
  @LuaFieldDoc("events.switchy.world_switch")
  public static LuaEvent WORLD_SWITCH = new LuaEvent();
  @LuaWhitelist
  @LuaFieldDoc("events.switchy.switch")
  public static LuaEvent SWITCH = new LuaEvent();

  @Override
  public String getID() {
    return "switchy";
  }

  static {
    SwitchyClientEvents.SWITCH.register((event) -> {
      Avatar avatar = AvatarManager.getAvatarForPlayer(event.player());

      if (avatar != null) {
        String newPreset = event.currentPreset();
        String oldPreset = event.previousPreset();
        List<String> enabledModules = event.enabledModules();

        avatar.run(WORLD_SWITCH, avatar.worldTick, newPreset, oldPreset, enabledModules);

        if (avatar.loaded && avatar.luaRuntime != null && avatar.luaRuntime.getUser() != null)
          avatar.run(SWITCH, avatar.tick, newPreset, oldPreset, enabledModules);
      }
    });
  }

  @Override
  public Collection<Pair<String, LuaEvent>> getEvents() {
    return List.of(
      new Pair<>("SWITCH", SWITCH),
      new Pair<>("WORLD_SWITCH", WORLD_SWITCH)
    );
  }
}
sisby-folk commented 1 month ago

merging this now and i'll fiddle with events

sisby-folk commented 1 month ago

@GrandpaScout could you give 2.9.3 a shot and figure out if it needs any more work & if the readme is correct?