#API Discussions General

1512 messages · Page 2 of 2 (latest)

velvet mirage
#

i scared of key duplication

warped canyon
#

use -ids clueless

versed prairie
#

How about nesting it under a guid?

warped canyon
#

no it needs to be guid

#

because mods will do the same

#

overwrite each other,
use the same id,
etc...

velvet mirage
#

it is really hard to made some thing fool-proof

warped canyon
#

I feel like it has to be a separate save file

#

or else you break the original

#

unless you can append it somehow

#

without breaking the original

quartz raft
warped canyon
#

it has to be invisible to the original parser

quartz raft
#

oh

#

im just using the og parser lol

#

¯_(ツ)_/¯

warped canyon
#

well if you are appending it should be invisible data

quartz raft
#

oh

warped canyon
#

that way they can remove mods and continue

quartz raft
#

what i do i just make the game make more saves

#

and it only uses those when modded

warped canyon
#

well I feel like if playing modded, you should be able to switch to unmodded and load successfully

quartz raft
quartz raft
#

could be done w/ an edit to the transpiler

versed prairie
#

ModData file:


{
"saveFile": "savefile_name_goes_here",
"modData": {
  "mod_guid1": {
    // serialised data goes here, under the mod's preferred key-value pairs
    },
  "mod_guid2": {
    // ...
    },
  // ...
  }
}
warped canyon
#

so yeah if that works it should be fine

versed prairie
#

This should be clean

quartz raft
#

switching to unmodded ingame is hell

quartz raft
warped canyon
#

We should make an attribute for save files

versed prairie
warped canyon
#

I think our api should serialize and deserialize it for the mods though

versed prairie
#

That's a separate save file though

#

That runs into the issue where you can't use QoL / fix / performance / graphical mods on vanilla saves

quartz raft
#

bit hacky but

velvet mirage
#

i don't want to get to the hell of serialization

quartz raft
#

¯_(ツ)_/¯

velvet mirage
#

and made it fool-proof

versed prairie
quartz raft
#

config should be used

versed prairie
#

Having separate ModData allows us to customise things a lot more.

quartz raft
#

for configs then

versed prairie
#

What?

quartz raft
#

jsut the bepinex.config api

#

or whatever

#

that fixes that problem

versed prairie
#

Yeah, obviously we should be using the BepInEx.Configuration API

quartz raft
#

so for configuration stuff

versed prairie
#

But for modded save data, we shouldn't enforce modded saves

quartz raft
#

config api

#

for items stuff

#

modded saves

quartz raft
warped canyon
#

ie:

public class MyMod
{
    [SaveData]
    public SaveFile Save;
}
public class SaveInfo
{
    public string Version { get; set; }
    public int Value1 { get; set; }
}
quartz raft
#

its just kinda a simple switch esp if i make the transpiles dynamic

warped canyon
#

thats my thought

#

we can serialize it and deserialize it automatically for the plugin

quartz raft
#
private static IEnumerable<CodeInstruction> SpoofSaveData(IEnumerable<CodeInstruction> instructions)
        {
            var codes = new List<CodeInstruction>(instructions);
            for (int i = 0; i < codes.Count; i++)
            {
                CodeInstruction code = codes[i];
                if (code.opcode == OpCodes.Ldstr)
                {
                    if (code.operand.ToString() == "LCGeneralSaveData" || code.operand.ToString().Contains("LCSaveFile"))
                    {
                        code.operand = "ModSaves/" + code.operand.ToString().Replace("LC", "BC");
                    }
                }
            }
            return codes.AsEnumerable();
        }```
warped canyon
#

we should also configure it to ignore extra keys, and use defaults automatically for missing keys

quartz raft
#

could be possible to change that to be dynamic variables

#

which, if we do that actually allows us to easily add more saves

velvet mirage
#

@versed prairie pushed another so called 'final' commit to move the save directory to ModSaves/

quartz raft
#

for example filename += pagenum

#

and having arrows on the slots for selecting a save

#

then all you have to do is reinit the slots when that changes

#

yeah

#

thats a simple solution that allows for inf save

#

s

warped canyon
#

well

quartz raft
#

rest of the ways r kinda a pain

warped canyon
#

does that save the basegame to one file, and modded to a second

versed prairie
#

So, what I had in mind for ModData was this:

using API.ModData

public class Plugin
{
  private ModData modData = ModData.load(PluginInfo.GUID)

  public void SomeMethod()
  {
    var someValue = modData.getData<SomeModType>("someKey");
  }
}
#

Transparent for the modder, saves to a ModData file, and can be added or removed without breaking vanilla.

quartz raft
#

effectively it makes 3 alternative saves

#

to use when modding

#

like minecraft or tmodloader

#

then you can just use es3

#

afaik the existing save system wont care about unknown keys

velvet mirage
warped canyon
# quartz raft nope

I figure we just store the data normally, then create a second file for modded.
Whenever the game loads / saves, we can call our custom implementation for saving /loading the modded data separately

quartz raft
#

so normal players saves can be loaded

warped canyon
#

then the basegame file is preserved

versed prairie
#

Yeah, exactly

quartz raft
#

but modded saves are seperate?

versed prairie
#

No, we shouldn't separate modded saves imo

quartz raft
#

so saving itd be somewhere else

versed prairie
#

it should be transparent

quartz raft
#

see this is why i dont wanna do that here ill send an ss of what we'd have to do

velvet mirage
#

because overloading

quartz raft
warped canyon
velvet mirage
quartz raft
#

theres a lot

#

lot

#

we would have to fix

#

this is how other mod systems do it

#

personally im fine with that

versed prairie
quartz raft
#

its clean and intuitive

versed prairie
#

This is my suggestion

warped canyon
#

I agree

quartz raft
#

yeah

#

i dont know

#

i think im gonna keep using my way

warped canyon
#

so the base save is safe

versed prairie
#

It's clean, doesn't write into the vanilla save data

versed prairie
warped canyon
#

its best for everyone

quartz raft
#

i agree but this simply isnt the way to do it i feel

versed prairie
#

Bizzle already uses their own API, so I'm not sure how conforming we can get with them unless they're interested in switching to our ecosystem.

warped canyon
#

I think it is the safest way

versed prairie
quartz raft
#

my way prevents any save corruption

warped canyon
#

it can screw with things

quartz raft
#

ever

#

your vanilla saves

#

will be fine definitively

versed prairie
#

We're not writing into vanilla savefiles, so there's no risk of corruption

#

¯_(ツ)_/¯

quartz raft
#

i understand yours does this as well

warped canyon
#

we dont touch the vanilla system

quartz raft
#

mods can still corrupt vanilla saves

warped canyon
#

how?

quartz raft
#

for example saving settings data anything

#

like a mod wants to change keybinds to be

#

imaginary keybinds

#

ok so

#

yeah

#

you can save that

warped canyon
#

thats so far beyond our scope

quartz raft
#

in modded savesd

#

i see that

#

but

#

loading it is just

velvet mirage
quartz raft
#

hardly feasible

velvet mirage
warped canyon
#

its json

quartz raft
#

my system requires no work on the modders part whatsoever

versed prairie
#

Loading some JSON data is amongst the most simple things you can do in programming.

quartz raft
warped canyon
#

look at this idea

#

ie:

public class MyMod
{
    [SaveData]
    public SaveFile Save;
}
public class SaveInfo
{
    public string Version { get; set; }
    public int Value1 { get; set; }
}
quartz raft
#

ok lets say

#

custom scrap right

#

after you add that

#

you have to spoof this function

#

here

#

the save key for scrap is shipScrapValues

velvet mirage
#

uhh, aren't we all arguing thing that is exactly same functionality but different code

warped canyon
#

to define a save, all the modder would have to do is add a field with the [SaveData] attribute

versed prairie
#

Alright, can we move on, we're discussing in circles and I'd like to get back to being productive 😅

quartz raft
#

ok

quartz raft
#

my system focuses on extending the existing saved data

#

ie items and moons

#

its possible these could be seperate systems

#

as yours seems focused on saving new items

velvet mirage
#

anyway, how is the result of the lobby metadata you got @versed prairie ?

warped canyon
quartz raft
#

lobby metadatas fun

versed prairie
#

So, for our core API I assume we're going with the following file format in practice. Correct?

ModData being JSON / serialised data - I don't mind working on that if you don't want to, Ozzy.

@warped canyon @velvet mirage @shell nest @languid tusk

versed prairie
velvet mirage
#

and it would require me to rewrote the entire save

quartz raft
velvet mirage
#

yes

#

i want it

#

give it to me

warped canyon
#

an override method

#

that way they can parse old saves and convert to new ones

velvet mirage
#

go speed

#

and use binary serialization for simple value?

#

but nvm it too godlike to work with

#

we only want 'simple' thing

warped canyon
#

but I think we should have a default converter

versed prairie
#

Do we want to make the syntax something akin to this?

using API.ModData

public class Plugin
{
  private ModData modData = ModData.load(PluginInfo.GUID)

  public void SomeMethod()
  {
    var someValue = modData.getData<SomeModType>("someKey");
  }
}

We could add a method like this for custom deserialising, as per Red's suggestion:

var someValue = modData.deserialiseData<SomeModType>("someKey", someDeserialiser);
velvet mirage
#

gimme

#

39s

versed prairie
quartz raft
#

anyway yeah

#

also dont other mods do it w/ sep saves?

velvet mirage
#

ok t here is newtonsoft json

quartz raft
#

all modded games ive played have done that

velvet mirage
#

withoutt the need to break everything i done and build again from scratch

quartz raft
#

ah wait

versed prairie
#

I've barely ever known a modded game that has entirely separate saves for modding. In any case, we don't need to copy another solution if we can validate this is a fine one. Each game is different.

quartz raft
#

i see the usecase i believe

warped canyon
quartz raft
#

this is for client mods that need to load per save values

#

ahhhh

#

ok that makes sense

#

ok yeah i see the use of this sytem

#

by alot

#

yeah this is nescessary

versed prairie
quartz raft
#

for example custom cozy light colors

velvet mirage
#

shit it 2:40am at my place

#

gotta go fast

quartz raft
#

you change the colors only on one save

#

for example

versed prairie
#

I'll get on your review now, Ozzy.

quartz raft
#

thats a good system

warped canyon
#

then if the developer wants to specify their own save data deserializer, we pass the json for their key.

velvet mirage
#

@versed prairie so i trash the currentt ModData and make a new one?

versed prairie
#

Gimme 5 minutes.

warped canyon
versed prairie
quartz raft
#

i do think that it works w/ the modded save system aswell

quartz raft
warped canyon
#

oh\

#

yeah

#

thats just my thoughts

versed prairie
#

If you do start from scratch, use a branch! @velvet mirage

quartz raft
#

i think both systems can be utilized as they both have their own use cases

warped canyon
#

I do waaay to much config serialization, but I have code to do that

versed prairie
#

Do you want me to review your current PR, or do we close the PR and re-review the new system?

quartz raft
#

perhaps the best solution is just to make a more saves mod

#

ill do that

#

and this api can save

versed prairie
#

Modded saves really should just be a More Saves mod, yeah.

warped canyon
quartz raft
#

ill be using this api youre making for items

versed prairie
#

More saves is nice 👌

quartz raft
#

hell i can actually put more profiles in there too

warped canyon
#

I think we incorporate a basic method into the api

#

like my method

quartz raft
#

if youve noticed some data is excanged between saves

warped canyon
#

and then a mod can extend functionality

velvet mirage
quartz raft
#

if you dont mind the request could you add a modded save for LCGeneralSaveData

warped canyon
#

@velvet mirage did you see my pr for stylecop

quartz raft
#

this is actually a really clean approach to saves

#

good shit

warped canyon
#

if not ill just do it in the official repo

velvet mirage
quartz raft
#

i do wonder if you could combine the existing es3 system w/ the new modded saves system

velvet mirage
#

pr the stylecop on the offical repo

warped canyon
quartz raft
#

for example saves.getkey("SavedItems") would check if thats in modded saves then check the es3 saves

velvet mirage
#

since each pr must a per-feature

warped canyon
quartz raft
#

hmm

warped canyon
#

its xml annotations

#

I can annotate nothing

versed prairie
#

Hold up

warped canyon
#

thats Why i had to pr to your repo thoughj

velvet mirage
velvet mirage
warped canyon
#

weird

quartz raft
#

one idea is as follows
mods can read any value from es3 but saving that value writes it to modsaves
the existing es3 system is modified to read from modsaves first before reading from the actual saves to check

warped canyon
#

anyways

versed prairie
#

Can you PR the style changes? @warped canyon

quartz raft
warped canyon
#

half of the pr is xml annotations

versed prairie
#

/ Are we keeping the current ModData you made?

quartz raft
#

for example, lets say i need to change this value w/ a transpiler

#

would there be an easy way to do that via this api

#

if not is a modification to es3 a better solution?

velvet mirage
quartz raft
#

maybe moddedsaves could use the es3 system

velvet mirage
#

i will push a commit to delete it

quartz raft
#

for serializing and deserializing

#

considering its already there

#

we will (or atleast I will) likely need to change the loading of a normal value to a "value exists in moddedsaves or exists in normal saves"

#

utilizing only transpilers

velvet mirage
versed prairie
velvet mirage
#

i will do the ModData tomorrow

#

it 2:50am at my place

#

gotta slleep

#

or else i'm gonna burn all of my brain cell

versed prairie
#

Sleep! 😄

#

Oh, and use a branch (for ModData) bruh

warped canyon
#

@versed prairie I talked to the creators of MEC, and they said we can include it in the repo. If we use MEC, we don’t have to make our own timing / asynchronous api.

#

I’m trying to see if I can also add the pro version if I buy it. (Licensing and adding it to the build may be weird)

versed prairie
#

Let's hold off on pro versions until we actually get people to use it

#

Thanks for looking into it, though

warped canyon
#

Yeah that’s a good point. I’m still gonna see if it’s possible to include it in the future. I’ll add the free version in later today.

#

I’ll make a pr

#

Also I’m gonna start hooking a few functions and working on an event api

#

So that plug-in authors (and us) can hook events

#

I have a few specific implementations for the events that I’d like to use but I’ll have to make a demo to show it

warped canyon
hollow hemlock
#

Idk if we could reasonably use the pro version unless we get some special permission. Extension assets have to be purchased by seat (per developer / independent contractor)

versed prairie
#

Never worked with MEC before

warped canyon
# versed prairie Never worked with MEC before

It’s pretty great. The only downside I’ve ever had is that coroutines don’t report errors they have. I have a “safe coroutine” that my friend made to fix this problem.

For the events I’m gonna start with saving (ie Saving and LoadingSave) then we can hook those for our custom save options

#

We could then start branching to player events like DamagingPlayer and PlayerDied

versed prairie
#

Alright

#

I'll work on the lobby metadata and dependency matching

versed prairie
quartz raft
#

yeah 2018s lc api is super scuffed

#

¯_(ツ)_/¯

#

idk i just wanna add all my stuff to it so people only have to install one lmao

#

i dont use git often so i probably dont see the issues everyone has w/ that approach

#

but imo it feels like a nice way to avoid the complications that come w/ cross plugin communication

#

and makes it much simplier for the end user

#

and I understand that it has previously been argued that the end user's experience is not relevant to the development of mods

#

this is normally argued as that its because the multi plugin approach is "right for the modding community"

#

but what are the users if not the modding community itself

#

¯_(ツ)_/¯

#

idk lmao

versed prairie
#

Shimmy posted some nice reasons I agree with, over in #1172376119194951730.

#

And we're obviously going for a git-first approach to collaboration.

#

So if you miss context surrounding the benefits of that / miss experience with git, it's understandable.

quartz raft
#

yeah

versed prairie
#

We can easily set up git workflow that build into a single .dll, pulling the code from all separate APIs.

quartz raft
#

oh sick

#

ok yeah im so down for that

#

sure

versed prairie
#

There's also Thunderstore which auto-adds dependencies, so multiple APIs is a non-issue for users if we go that route.

quartz raft
#

that too

#

sounds good

#

ill pub my savespoofer to git

versed prairie
#

But yeah, read Shimmy's reasoning. It's clear and concise imo.

quartz raft
#

yeah i can see that

#

just read em

#

good points

#

ok cool

#

here ya are

#

was made for v38

tough totem
quartz raft
#

should be fine but untested

tough totem
#

on save data: make it an option to overwrite vanilla saved w/ modded progress or backup original save and restore it when modding is disabled

tough totem
#

oh i missed that thread

versed prairie
#

No worries

#

A lot of talking happened the past ~12 hours

shell nest
#

sounds good to me

shell nest
versed prairie
#

Yup, I agree

quartz raft
#

Sounds good

#

I'll send my moonapi code if/when it's done

#

I got that like half sone

#

Tbh I need saveapi to fin it so

versed prairie
#

What are you doing in the moon API?

#

I have some dynamic moon code I used for a mod I'm working on, and it works fine on a vanilla save. (Adds two moons, and some terminal nodes for travel)

shell nest
versed prairie
#

What's ConfigPersists?

tough totem
shell nest
#

for config settings that modify game elements

warped canyon
#

me when "AAAAAA"

#

We probably should make a basic player api to help with the items

#

so you can find a player and do player.giveitem

#

or something of the sorts

#

idk exactly whats out there, as there may be a basic api for this already

warped canyon
#

@versed prairie thoughts on dynamic patching. The api that im basing the event system does this. Basically events don't have to be patched until something hooks onto the event.

versed prairie
#

Pros & cons?

warped canyon
#

it is good for updates, because if events break but aren't actually in use, it won't patch them

versed prairie
#

I can see it improve compatibility if nothing uses the patched method

#

Possibly performance as well, though likely negligible

warped canyon
#

but it can also be more complicated and confusing

versed prairie
#

Could you get a demo / example snippet to showcase how it's done?

warped canyon
#

as adding and removing transpilers can be questionable

versed prairie
#

I like the idea in theory. But depending on how it's done, it might add development complexity

warped canyon
#
public class Event
{
    public static Event operator +(Event @event, CustomEventHandler handler)
    {
        @event.Subscribe(handler);
        return @event;
    }
    public void Subscribe(CustomEventHandler<T> handler)
    {
        if (Events.Instance.Config.UseDynamicPatching && !patched)
        {
            Events.Instance.Patcher.Patch(this);
            patched = true;
        }

        InnerEvent += handler;
    }
}
public static class EventHandlers
{
    // Developers hook to this with the += 
    public static Event<Event1EventArgs> Event1 { get; set; } = new ();
    // Allows invoking the event from outside the class (inside separate patch classes)
    public static void OnEvent1(Event1EventArgs ev) => Event1.InvokeSafely(ev);
}

public class Plugin
{
    public Plugin()
    {
        EventHandlers.Event1 += OnEvent1;
    }
    public void OnEvent1(Event1EventArgs ev)
    {
        // Developer runs code
    }
}
warped canyon
#

as I look through it it kinda blows my mind

#

fairly clean and organized and very well thought through

#

it does require all of our patches to use an attribute with the respective event type

#
 public void Patch(ILcApiEvent @event)
        {
            try
            {
                List<Type> types = new(UnpatchedTypes.Where(x => x.GetCustomAttributes<EventPatchAttribute>().Any((epa) => epa.Event == @event)));

                foreach (Type type in types)
                {
                    List<MethodInfo> methodInfos = new PatchClassProcessor(Harmony, type).Patch();
                    if (DisabledPatchesHashSet.Any(x => methodInfos.Contains(x)))
                        ReloadDisabledPatches();
                    UnpatchedTypes.Remove(type);
                }

            }
            catch (Exception ex)
            {
                Log.Error($"Patching by event failed!\n{ex}");
            }
        }
#

Each patch must have the [EventPatch] attribute so the patcher can find it:

[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.IssuingMute))]
[HarmonyPatch(typeof(VoiceChatMutes), nameof(VoiceChatMutes.IssueLocalMute))]
internal static class IssuingMute
{
}
versed prairie
#

You can review & accept or deny.

warped canyon
versed prairie
#

Yeah, I read up on it a bit when I first saw it. Just been doing it since then, but forgot the actual reasons.

warped canyon
#

Door event could be opening / closing / leaving

AttackerEvent - Player v Player, (maybe enemies - this could be separate)
IDeniableEvent - Basic Functions that can be cancelled such as dealing damage, closing doors
IDoorEvent - Opening, Closing, Entering, Leaving
IFirearmEvent - Gun 
IHazardEvent - Player steps in cobwebs, mine, or in sight of turret
IItemEvent - Drop, etc...
ILcApiEvent - Basic Event that everything inherits
IPickupEvent - this is probably better just being IItemEvent
IPlayerEvent - Join, Leave, and other general actions
IRagdollEvent - Body Events
IRoomEvent - Steam Event? - could just be added as a hazard
IUsableEvent - Key usage, bell ring, etc... 
versed prairie
#

Can you create a forum thread for this?

warped canyon
#

yeah'

versed prairie
#

It's something we can put on the potential TODO. I think it's neat in theory, but it'll require a better understanding of the game's codebase to properly define events and organise it.

warped canyon
#

I think this adds power to our api

#

plenty of other cool things, but this is what I think is really important for simplifying the modding process

tough totem
#

event based is definitely the way to go

versed prairie
#

Sure, if you want to work on it, by all means! 😄

shell nest
versed prairie
versed prairie
#

I went off of the method's documentation, but wasn't certain

shell nest
#

yea, TerminalNodes are command responses

velvet mirage
#

@warped canyon wow, for random unknown reason, my vs won't detect the Assembly-CSharp after your commit

#

wow

#

for some random reason again it now working

#

vs is magic

#

@versed prairie i have created a new pr for the isolation between vanilla and modded user

warped canyon
versed prairie
#

Yeah, Rider was being funky with assembly decompiling until a restart.

versed prairie
#

Resolve them and we can merge 👌

velvet mirage
#

don't see any in the pr comment

versed prairie
#

Uh, should have requested changes

velvet mirage
#

is github server being funky?

versed prairie
#

Gimme a sec

quartz raft
#

interesting

#

not how we've done it in the past

versed prairie
#

That's just how code reviews & PR's work on Github?

quartz raft
#

im talking ab

#

making the servers modded

versed prairie
#

It's still WIP. I'll be expanding it with dependency checks later

quartz raft
#

its jsut that

#

i dont recommend doing it that way

#

esp cuz unmodded clients

velvet mirage
quartz raft
#

and that dosent allow you a custom playerlist without some complicated workarounds

velvet mirage
#

lol, github didn't update it somehhow

versed prairie
velvet mirage
#

hhmm

#

might want to add something like a switch (plus counter) that will force a user to modded only when it switched on

#

not by default enabled like this

versed prairie
#

I'll update it to use the dependency check system after you've merged @velvet mirage

#

So a switch won't be necessary then

#

This is a good base to go from for now

#

I also think we should use public patches. The TerminalCommands API, and all the relevant docs use it. Best to conform to common standards.

velvet mirage
#

oke

#

@versed prairie done

versed prairie
#

@shell nest or @warped canyon

Can you give a final review? Looks alright to me.

#

@velvet mirage approved. We can merge, or wait for shimmy or red to have a final look

velvet mirage
#

a switch

#

for mod to use

#

that will force player to only able to join modded lobbies?

#

and it will by default disabled?

#

instead of enabled like current pr

versed prairie
velvet mirage
#

you can merge it now

#

i will find anything else to work on

versed prairie
#

You'll want to discuss it with Red. They have a good idea on how to approach it

warped canyon
#

I looked at the terminal api

#

it looks good

versed prairie
#

Shimmy's Terminal API is a work of art

versed prairie
#

(Cleaning up some unrelated-to-our-API messages)

tough totem
quartz raft
#

I've been thinking

#

Maybe one of the goals of the API should be to allow complete cross version usability of mods

#

If only the API breaks between updates

#

The only one mod needs to be fixed

versed prairie
#

That's a big part of APIs, yeah

quartz raft
#

yeah

versed prairie
#

We're trying abstracts a lot away and act as middleware already

quartz raft
#

Yeah

versed prairie
#

The Terminal API is a superb example

quartz raft
#

So this could effectively turn into a wrapper for the entire game

#

Really interesting

#

I do think that's the best solution

#

Another goal could be to make it so no one needs to use patches

versed prairie
#

Patches are unavoidable I think, but yeah: the point of APIs is providing as useful of a middleware between the game and mods. Mods should be able to achieve as much as possible using our APIs, since this also improves compatibility.

A strong object-oriented design, and a similar style between all APIs is a must as well. Usage needs to be intuitive between all APIs.

versed prairie
#

Need to do something with a terminal? Use the terminal API.

Want to add an item? Use the Item API. Want to additionally add it to the shop? Use the Store API, which bridges between the Item and Terminal API.

#

Etc

quartz raft
#

yeah

versed prairie
#

Once events are done by Red, we can use dynamic patching too. That'll improve compatibility a fair bit.

versed prairie
#

@quartz raft @tough totem @languid tusk @austere gyro @shell nest @velvet mirage

We'll move API development to a separate server. Easier to make a number of channels / mass ping for votes / etc...

I'll be setting it up properly tomorrow, but here is the invite for now:

https://discord.com/invite/GRrMt8kyEH

#

Considering the planned size of the project, a forum isn't sufficient anymore to organise this.

upper bramble
#

Hey this ever come about?

#

That's exactly the mod i'm looking for

shell nest
#

yea

#

I made it, save for the teleport command
well, I did make the command, but last update broke it and I haven't looked into it