Today I tried fixing a lot of the methods and mappings in the API. It took way longer than I expected, and for some reason every time I fixed something, something else would break. Because of that I ended up rewriting parts of the transpiler just to get a clearer view of where the issues were coming from.
I managed to fix quite a few things. The scheduler was completely broken before — RunRepeating was basically just a comment and RunLater was using Thread.sleep which would’ve frozen the server. I reworked both of them properly using Fabric tick events. I also fixed enchantments since Mojang changed how registries work in 1.21.1, so now it uses the dynamic registry system instead of just outputting useless comments.
There were also issues with type resolution, especially with things like armor slot chains (like player.Helmet.GetItem()), so I added a lookup system to help the transpiler understand return types better. Particle constants were also wrong before, so I mapped them properly to strings like “minecraft:flame”. I also added proper handling for array creation since that was just throwing warnings before, and improved how McGameRule generics are handled so they don’t silently break anymore.
There are still some issues, but most of the major ones are fixed for now.
One thing that really fought back was the scoreboard API. I thought I was using a bad workaround and tried switching to the proper method, but it turns out Mojang removed it in 1.21.1. So I had to go back to the workaround anyway.
Also I took a screenshot of a java file before being built. I don’t think I need to say anything - it just looks ugly.
This is how much cleaner it looks when making it using this API:
// /kit — give starter kit to yourself
McCommand.Register(“kit”, (src) =>
{
McPlayer p = src.Player;
if (p == null) { src.SendError(“Players only!”); return; }
p.GiveItem(“examplemod:ruby_sword”, 1);
p.GiveItem(“examplemod:ruby_pickaxe”, 1);
p.GiveItem(“examplemod:ruby_helmet”, 1);
p.GiveItem(“minecraft:bread”, 32);
p.GiveEffect(“minecraft:speed”, 600, 1);
p.GiveEffect(“minecraft:haste”, 600, 1);
src.SendMessage(“Ruby kit granted!”);
});
// /heal <target> — op only, heals a named player
McCommand.RegisterOpWithPlayer("heal", "target", (src, target) =>
{
target.Heal(target.MaxHealth);
target.ClearEffects();
target.GiveEffect("minecraft:regeneration", 100, 1);
target.SendMessage("You were healed by an admin.");
src.SendMessage("Healed " + target.Name + "!");
});
// /spawn — teleport to world spawn
McCommand.Register("spawn", (src) =>
{
McPlayer p = src.Player;
if (p == null) return;
McWorld w = p.World;
McBlockPos sp = w.SpawnPos;
p.Teleport(sp.X, sp.Y, sp.Z);
p.PlaySound("minecraft:entity.enderman.teleport");
src.SendMessage("Teleported to spawn!");
});