← Blognews

Phantom is finally here

I've been working on Phantom for a while now and it's finally ready. A new modding client for Animal Jam Classic, built from the ground up.

Sxip

I've been working on Phantom for a while now and I'm finally ready to release it.

Phantom has always been a dream of mine. It's what I originally wanted Jam to be, and after months of work it's finally everything I wanted it to be.

Phantom is a new modding client with a bunch of stuff I've wanted for a long time, and I'm going to go through the bigger bits below.

One thing before I get into it: Phantom is still in beta. There will be bugs, and there's plenty I still want to add and improve. If you run into something broken, tell me and I'll get it sorted.

The TypeScript part

This is probably the biggest thing. You aren't stuck with whatever features I decide to add. You can modify Phantom itself, make your own features, automate things and change how stuff works however you want.

Scripts are a few lines of TypeScript you run against one game or all of them at once. They can move your avatar, chat, trade, play an adventure, read your inventory, whatever. If you want something more permanent, turn it into a plugin.

The SDK behind all of this covers the whole game. Every message the game sends and receives has a proper typed listener or action, so if the game can do it, you can do it from TypeScript.

The Flash API

If the SDK doesn't cover something, you can go straight into the game itself. Phantom runs the real Animal Jam client, and the Flash API lets you reach any class, method or field in it from TypeScript, including the ones the game marks as private. Your editor even autocompletes the game's own classes.

Read something straight out of the running game:

TypeScript
const main = phantom.flash.global('gMainFrame');
console.log(await main.userInfo.myUserName.$get());
Those two lines, against a game that is actually running

Call the game's own code:

TypeScript
const audio = phantom.flash.use('com.sbi.corelib.audio.SBAudio');
if (!(await audio.areSoundsMuted.$get())) await audio.muteSounds();

Or hook one of its methods and hear every time it runs:

TypeScript
const room = 'room.RoomManagerWorld.loadRoom';
await phantom.flash.hook(room, { capture: { args: [0] } }, (call) =>
  console.log('loading', call.argList[0])
);
The game calling its own method, with Phantom listening

Hooks can also change what a method gets or gives back, or replace it completely, so you can change how the game behaves, not just watch it. The docs go through all of it.

Plugins

Plugins add their own pages, panels next to the game and commands. There's a store in the app and on the website, and anyone can publish to it.

Before a plugin runs anything, Phantom shows you exactly what it wants to do and waits for you to say yes. Every plugin in the store gets looked at by a person before it's listed, and if one does something dodgy you can report it.

Live stuff

Plugins can talk to each other across the internet, and Phantom does the hard parts.

Your plugin gets a channel: everyone in the same room, everyone running the plugin, or a group it names. On top of that it gets the things you always end up writing yourself and wishing you hadn't:

  • A shared value the channel keeps, so somebody who turns up late sees the score, the board or the queue straight away instead of asking the room what they missed.
  • Presence, so each person carries their own bit of state. Ready, typing, what colour they picked.
  • Asking one person a question and awaiting their answer, instead of shouting at the room and matching up the replies.
  • A referee. For a game somebody has to be in charge, and the server picks one and picks another the moment they leave. A plugin can't lie about being it, which is the whole point.

Games, lobbies, leaderboards, trading tools, whatever. There's a working example in the repo: noughts and crosses against somebody in your room, with everyone else watching the same board.

Custom rooms

We also have a custom room creation SDK. If you want to make your own rooms and have other people join them through Phantom, you can do that too. You make the room from your own pictures, say where people can walk and what's in it, and anyone running your plugin can walk in and hang out.

Animal Jam never sees any of it. As far as the game's concerned, you're still standing in the room you came from.

How it's different

Most clients, Jam and Strawberry Jam included, ship a modified copy of the Animal Jam client. You decompile the game, add your features into its code, recompile the whole thing and ship that. It works, but it decides a lot for you:

  • You get a fixed list of toggles, and if what you want isn't on it, you wait for whoever maintains the client.
  • Every feature lives inside the game's own code, so one mistake can take the client down with it.
  • When Animal Jam ships a new build, the whole thing has to be decompiled and rebuilt again before anything works.

Phantom doesn't touch the client's code. It runs the real, unmodified client and changes it while it's running:

  • Hooks. Any method in the game can be watched, have its arguments or its answer changed, or be replaced outright, from TypeScript, while you play. Walk through walls is one override of the method the game asks whether a tile is walkable.
  • The whole client, typed. Phantom ships typed declarations for all 1,078 of the game's classes, generated from the client itself, so phantom.flash reaches any class, method or field, private ones included, with autocomplete in your editor.
  • Every message, both ways. All 191 messages the server sends and all 156 the game sends have a typed listener or action in the SDK, so trades, dens, buddies, shops, adventures and rooms are all a line or two.
  • It survives updates. Nothing is baked into a copy of the client, so a new game build doesn't throw everything out. When something moves it's one fix in Phantom, instead of every plugin breaking at once.

That's the whole argument, really. Anything on someone else's toggle list is a few lines here, and so is the stuff nobody's built yet.

And the bits that come with that

  • Plugins can't run off with your stuff. Each one runs sandboxed in its own frame with its own permissions, so it can't see your Phantom account, your Animal Jam login, or any game you didn't allow it on.
  • Eight games at once, each in its own tab or side by side, with its own packet console showing every message going past in plain words.

What it costs

$6.99 a month, or $39.99 once and it's yours.

Phantom is a lot more work to keep running than Jam ever was. There's a server behind the plugin store, the live stuff and your account, and I'd rather charge for it than cut corners or let it rot.

The website is live at phantm.site. Pricing, downloads and everything else are there.

Thanks for all the support with Jam ❤️

FAQ

Why would I use Phantom over Jam or Strawberry Jam?

Jam's been discontinued for a long time now, as you all know. The code was pretty bad and some of the design choices I made back then were questionable lmao.

Strawberry Jam is basically a fork of Jam with a bunch of other stuff added to it.

Phantom is what I originally wanted Jam to be. There's more on how it's actually different further up, under "How it's different".

What if I can't afford it?

If you genuinely can't afford it, message me and I'll see about giving you lifetime access. I don't want money to be the reason you can't use it.

Do I need to know TypeScript?

Nope. You can use Phantom normally without knowing any. It's there if you want to go deeper and start messing with the client yourself.

Can I make my own plugins?

Yep, that's what the plugin system is for. Run npm create @phantomclient/plugin@latest and the docs take it from there.

What platforms does Phantom support?

Windows and Linux right now. macOS is on the way.

Is Phantom still being developed?

Yes. I'm going to keep working on it, adding stuff and keeping it updated.

Is there a lifetime option?

Yep, $39.99 lifetime.

What can I actually do with the live stuff?

Anything where two people running your plugin need to see the same thing at once. Games, lobbies, leaderboards, a trading queue. The shared value, presence, asking one person a question and having a referee are all handled for you, so you write the game rather than the plumbing.

What is the custom room SDK?

It lets you make your own rooms and have other Phantom users join them. You can build your own experiences around rooms instead of being stuck with the normal game ones.