#TimberAPI

1 messages · Page 3 of 1

full acorn
#

yeah, still lost, hey ho, I'll get there

stone shoal
#

lost ?

#

use a gps

full acorn
#

Hey Siri, direct me to TimberAPI.UIBuilderSystem

stone shoal
full acorn
#

To be honest I think it's just a lack of C# knowledge at this point

stone shoal
#

I don't know what you stuck at

north hatch
#

Skill issue

full acorn
stone shoal
#

Dang that's heavy

full acorn
#

Nah only joking around

calm copper
#

How does the game design align to the common singleton pattern? Is it considered a bad practice to use common pattern vs injecting the singleton via Bindito?

#

The both approaches would work just fine together. I'm just curious.

#

@ebon sparrow This question is probably to you 🙂

calm copper
#

Just to eleborate the case a bit. In the common pattern we have a private constructor in the class and a public static field that returns an instance (which was build somehow). Like:

var system = MyMegaSystem.Instance;
system.DoStuff();

The same code can perfectly work if we inject MyMegaSystem object via Bindito and don't deal with the static field Instance at all.

ebon sparrow
#

using statics is generaly bad, as then it is harder to control your dependencies

#

Dependency injection is a tool to solve this problem

#

so while you can use both alongside

#

from architecture point of view, and also from maintainability, it is a step backwards

#

probably also less buggy aproach, since Bindito ensures proper creation, initialization and destruction of objects

#

while with common pattern each time you need to solve it yourself

north hatch
#

@stone shoal does the specification system limit itself to the current mod or does it allow for cross mod compatibility?
Lets say i make a fluid specification in my mod but allow other modders to specify their own fluids, would that work? or do i need my own system for that?

severe solar
#

Crossmods

#

Thats why you need the .original, that defines its the first one

#

Other specifications that are the same, but do not have .original will add or overwrite the .original

north hatch
#

i see, thats poggers

severe solar
#

And it allows for your instance of other mods having those specifications

#

Thebloodeyes is very smurt ChillBar_smart

north hatch
stone shoal
calm copper
#

How expensive the DependencyContainer.GetInstance<T> call is? Do I need to bother to cache its return?

#

E.g. I can maintain a hash map of the instances that I've already requested. Is it worth it?

calm copper
stone shoal
#

Why could you not just do it with bindito binding ?

calm copper
#

One case, is a class that doesn't follow the bindito schema. E.g. it can be "simple class" that needs to do something with the game state. I saw some examples in the game. There, the injected instances are all passed in the constructor. My humble opinion is, it turns the code into disaster on the long run.

#

But getting back to the "abuse". Should I cache or should I not, being abusing the concept?

stone shoal
#

The concept is to only use it at patches, since you don't have access to bindito there

#

With a very very few exceptions that it would really not be possible due some ingame loading order you want to avoid

#

But to simply at your question: No idea both ways are less performant

#

The container has it also already cached I think

calm copper
#

I have a case where new MyClass() is the best way to go. However, the MyClass may want to access, for instance, EventBus. I can pass this instance through all the calling chain, making my code looking like an al dente spaghetti. Or, I may avoid it.

severe solar
severe solar
calm copper
#

And let me guess, this factory needs to be injected? And how would it handle the inherited classes case?

#

E.g. I have MayBase class and a dozen of descendants.

severe solar
#

Feels like you need to use bindito, without more context

stone shoal
#

How would a factory not be able to do that but your class do ThinkingIT, A factory is nothing else than the creation of thsoe classes ?

severe solar
#

You have a few options, and those are it i believe,

  1. Class on gameobject and use InjectDepencies
  2. Its a singelton
  3. Its a class created using a factory where the factory is used to creat the classes with some extra singletons.

A example of 3 is pathfollower inside walker. How i understand it, is that making it a basecomponent is not needed, but they do several other singeltons and therefore created a dedicated factory

#

And that is why i asked why you feel like that. As to me, it makes the most sense and more than whatever else you can do

calm copper
severe solar
#

No?

#

Use 1 of the three options, if you cant, big chance you are doing it wrong

#

If you want, i can come into a call sometime and explain it better

calm copper
severe solar
severe solar
#

Ofc you can, but i feel like it would be a shame of your time

calm copper
#

In fact, any API has its reasons. As long as DependencyContainer is publicly accessible, people will be using it.

severe solar
calm copper
#

In my specific case I believe, that access to the game state will be out of the common case. Thus, I lean towards to the first option: one class for the definition and behavior.

stone shoal
#

You can do whatever you want and I would not care really. But if you ask what's best, well not using it is. and tobbert stated the options better than I did.

calm copper
stone shoal
#

Than use a factory that does that for you, that's just as OOP as anything else

#

Or import the class that creates the new with bindito and acces it that way

#

Also just fine

#

But not importing the singleton in the head of the class because "it does not look good" is not a valid opinion in my eyes.

calm copper
#

Except I still don't have an idea if I should or should not be caching the instance from the DependencyContainer. I guess, I will be doing it just in case.

severe solar
#

Dont use it

#

Dont use it

#

Dont use it

#

Dont use it

calm copper
#

make it internal if I should not be using it.

severe solar
#

I dont understand why though? We twll you its wrong

stone shoal
severe solar
#

You ask for advice, we tell you how to do it and you ignore and still do it. Why ask for advice?

#

You give near to no example of why ot cannot be done how i said it should normally be done

calm copper
stone shoal
#

Disclamer: Tobbert is tobbert, and not me ohlsippyn

severe solar
#

I want to help you and tell you how to keep your code in line with everything else. I dont understand why you not listen or even try to listen....

calm copper
stone shoal
#

The only thing I heard is you wanting performance, so I adviced to that while also giving you a simple answer

calm copper
stone shoal
#

Btw that "feature" is just a cached instance of bindito 🙂

#

Therefore the reason of not knowing

calm copper
stone shoal
#

wrt?

calm copper
#

"with regard to"

stone shoal
#

Its a saved instance 🙂

calm copper
#

I guess, the final answer to my question (which is only important to me, but it's fine): do not cache injections, it's stupid.

severe solar
#

Using dependency container is worse peroformance to begin with, so not using it is better 🙂

calm copper
severe solar
north hatch
#

Don't worry about micro optimizations before you have a working system. Use the tools at your disposal and if those end up being too resource intensive you can look at optimizing them. But this feels like a case of "i dont wanna do that cuz i dont feel like it" rather than a solid reason

calm copper
north hatch
#

At what level are they created? Is it a singleton? Recreated each call?

#

Funnily enough the creation of an object is rather expensive compared to reusing a class.

calm copper
north hatch
#

So you'd DI the factory class but not the specific classes it creates from that factory class?

calm copper
#

DI?

north hatch
#

Dependency Inject

calm copper
#

Ah. As I explained above, it can be done. Except, I don't see a strong need for it. Factory is a good pattern, but as all patterns are - it's not good always.

north hatch
#

Well doesn't have to be a factory class ofcourse, could just be a service class that handles the logic, no big deal

calm copper
north hatch
#

The way i do it for my liquid logic is that i have a service class that creates the registered instances in a load call and put them in a map and get them when i need it

#

well you could have an interface which satisfies your needs for A, then create concrete classes based on name or properties

#

for fluids i just do it based on a string

#
namespace SteamWorks.Scripts
{
    public class LiquidServiceFactory
    {
        private Dictionary<string, ILiquidService> _services = new();

        public LiquidServiceFactory(LiquidService liquidService)
        {
            _services.Add("Water", liquidService);
        }

        public ILiquidService GetServiceFrom(Fluid fluid)
        {
            Debug.LogWarning($"GetServiceFrom {fluid}");
            if (!fluid.IsPhysical || fluid.Type is not FluidType.LIQUID)
            {
                Debug.LogWarning($"GetServiceFrom NOT OK");
                return null;
            }
            _services.TryGetValue(fluid.Name, out var liquidService);
            Debug.LogWarning($"LiquidService {liquidService.GetHashCode()}");
            return liquidService;
        }

        public void AddService(string fluidName, ILiquidService liquidService)
        {
            _services.Add(fluidName, liquidService);
        }
    }
}

i'm aware its not really a factory class but i couldnt find a better name

calm copper
severe solar
north hatch
#

well as i said, it doesnt have to be a factory

#

just use whatever method works, just make it generalized so you can easily get it using DI

calm copper
north hatch
#

Yeah interface or abstract classes

calm copper
#

Sorry I was being sarcastic. Of cousre I use it. There will be no this discussion without OOP inheritance in the first place.

north hatch
#

you do you, i'm just giving my 2 cents

calm copper
#

Btw, one reason I decided not to keep "dictionaries", is the reload case. Some entities may change between the reloads even if you think they are "singletons". For example, the tool buttons.

stone shoal
calm copper
stone shoal
#

And a bit annoying

#

Isnt true for nodded buildings tho since those are actually being unloaded and reloaded

#

Needed to change the specificationGeneration for that as well

ebon sparrow
calm copper
#

My reasonable expectation on reload would be that if any object, that is derived from Monobehavior, stays alive on realod is a usable object. I figured out, it's not the case at least in some cases. That is OK. I'm just making my code accordingly.

ebon sparrow
north hatch
#

it's futile tbh

ebon sparrow
#

yeah, I already know :)

calm copper
ebon sparrow
#

you asked "in general"

calm copper
#

My question was not about "can I do this?". It was about "when I do this, how slow it will be"?

ebon sparrow
#

I think the best answer is: do it both ways and compare

#

For me this is asking: how much more gas will I use when I turn my cars AC on

In most cases: more, but negligible. But maybe you live in north pole - and then exactly the same

#

couse it will never turn on ;)

severe solar
#

I ask thebloodeyes always something, but then he tells me why im doing what im doing in the first place. Most times hes right and im doing something wierd which i shouldnt. This is what i tried with you, but you are ignoring my advice and still do it in a unconventional way.

stone shoal
calm copper
severe solar
stone shoal
#

I actually think this chat isn't a good place for asking performance stats, since no one will know 😅

calm copper
calm copper
stone shoal
calm copper
#

In my life, I made dozens of services which performance I'm not aware as of today. Not a big deal. For me kek

stone shoal
#

I know around how much things of TimberAPi impact the game, at least where the places matter for me

#

But there are also quite a few things that are things Timberborn made and I only made it accessable

calm copper
stone shoal
#

It was a big summer side project

calm copper
vast otter
#

@stone shoal just so you know cameratweaker mod is updated for your u4 update 🙂

stone shoal
#

I know 🙂

vast otter
#

Hmm is it possible to have 2 mods to have the same Spec
want to use the same tab for both mods and if i use .Original it does crash if i have both mods installed and if i have .Replace and only have that mod it crashes because it is not loaded

#

or is i forced to have one mod as a dependency ThinkingIT

#

would it be possible to allow .Replace to load if no Original is found

vast otter
#

Then i keep them as dependent on the other

north hatch
vast otter
#

Not what i know of and my mods is codeless. And the problems i have is that i want both mods to be able to load a new tab without it crashing🤔

So my current approach is to have one mod req the other that has the tab

#

You can tell in mod.io and in mod.json that mod a req mod b

north hatch
stone shoal
stone shoal
#

We had 2 originals before and it worked tho ThinkingIT, maybe something in the bottom bar doesnt like it

vast otter
#

It say key already found ThinkingIT

north hatch
#

maybe skip it then and give a warning in the console?

#

Key with Id x already found, using that instead

#

realistically speaking there should be no accidental matches on those

severe solar
#

Better load the original, and have a soft dependency, so the first one is read first

north hatch
#

that would be the better option, but more work

severe solar
#

trueee xD

#

fair

stone shoal
#

maybe a .shared use at own risk KEKW

vast otter
#

Will give you the error code later today

vast otter
#

May be later before i can give an error message. Stomach hurting so time take it chill in bed

stone shoal
#

N0

#

Np

nova gale
#

When using AddPreset(factory => factory.Sliders().SliderIntCircle()

#

I get warning messages
Image not found for path: UI/Images/Core/scroll_bar
Image not found for path: UI/Images/Core/scroll_button

#

and the result is this

#

it probably is just a renaming issue to scroll-bar-nine-slice

stone shoal
nova gale
#

Sadge

vast otter
severe solar
#

it gathers all pngs

vast otter
#

so in a nutshell compile a list of all pngs and its location? ThinkingIT

#

can i view the current file used on github is the question, how it looks like currently

stone shoal
#

It generated a uss file and .cs file with all class names for the images

#

TimberApiStyle.cs lr something

vast otter
#

and the assetbundle has not changed since update 2 ich ?

stone shoal
#

Ye

#

Maybe even 1

vast otter
#

ok

nova gale
vast otter
#

Just have to understand how to open the asset bundle, but thats for next week

calm copper
#

Something weird is happening with Harmony in the game. According to the docs, if prefix returns false, then not original, nor any patches that are following in the chain will be called. However, what I observe, is calling both patches even when they both return false.

ChooChoo patches StatusSpriteLoader.LoadSprite so that the prefix always returns false. It should prevent calling any other prefixes that are down the stream in the chain. However, the prefix method on my patch on the same method is always called. Even with the Priority.Last.

Any ideas why?

stone shoal
#

Nope

#

Tobberts also last maybe?

median plinth
#

how's your patch look?

Prefix methods that return void and have no ref arguments are considered side effect free and are always run, regardless of their position.
returning false doesn't skip all the prefixes

calm copper
#

I tired both: last and first. In both cases both patches were executed.

median plinth
#

well that is indeed odd

calm copper
#

Btw, if I change priority to Last, then __result in my prefix comes non-null. Which implies the previous version has been called.

#
  [HarmonyPriority(Priority.First)]
  [HarmonyPatch(typeof(StatusSpriteLoader), nameof(StatusSpriteLoader.LoadSprite))]
  static bool Prefix(string spriteName, IResourceAssetLoader ____resourceAssetLoader, ref Sprite __result) {
    DebugEx.Warning("*** calling our version for: {0}", spriteName);
    __result = null;
    return false;
  }

This code must be crashing the game unconditionally. However, it doesn't. I get all the logs printed, but the sprite get successfully loaded by the next patch in the chain.

severe solar
#

Should i change my class?

#

If so, just say so!

calm copper
#

If you change it so that it fails back to the original code, it should fix the crashing issue, but it won't solve double calling of the method. Anway, please, change.

severe solar
#

Okay, will try that later

calm copper
calm copper
#

Well, looking at the IL code, It's obvious why the method is called twice: Harmony simply applies two prefixes! Goot quesiton why.

[Info   :  HarmonyX] Patching UnityEngine.Sprite Timberborn.StatusSystem.StatusSpriteLoader::LoadSprite(string spriteName) with 2 prefixes, 0 postfixes, 0 transpilers, 0 finalizers
2 prefixes:
* static bool ChooChoo.StatusSpriteLoaderPatch::Prefix(string spriteName, Timberborn.AssetSystem.IResourceAssetLoader ____resourceAssetLoader, UnityEngine.Sprite& __result)
* static bool Automation.Utils.StatusSpriteLoaderPatch::Prefix(string spriteName, Timberborn.AssetSystem.IResourceAssetLoader ____resourceAssetLoader, UnityEngine.Sprite& __result)
north hatch
#

however the nature of how timeberborn code is written makes it harder as most dont have return values you can just change

severe solar
#

And, the original will most of the time crash aswell

calm copper
severe solar
#

The problem with that is that i dont know how git works. So instead of making a pr (which i dont know how todo) i just make a quick fix

north hatch
#

well do you know how to commit and push?

severe solar
#

Sort off

#

In rider i click rhe select all and then click the arrow

#

And i have a timberapi project, but i dont know how to update it

#

Its still 0.4 or aomething

north hatch
#

easiest way is to fork the repo on github, then pull that into Rider, make a new branch, commit and push your changes on there, then on github it'll ask you if you want to create a pr to the orignal repo

#

i can show you how to do it after work (so around 6pm)

severe solar
#

YES PLEASE

#

Only reason i havent PRed anyone

calm copper
#

So, I found a way to avoid two prefixes executed: store my result into __state from my prefix, throw an exception, and handle it in the finalizer 😱 An absolutely weird way, but it's the best I have for now.

calm copper
#

So, whatever harmony docs say, it's not true about calling the prefixes. If you can read IL code, checkout HarmonyLib.Public.Patching.HarmonyManipulator.WritePrefixes method. It's the one that generates the actual patch code. It simply enumerates all prefixes on the method and calls them all. The bool results from the prefixes are joined via and and this is checked once to decide if the original method should be called. That being said, the original code won't get called if at least one prefix said "no", but ALL prefixes will be called anyway.

calm copper
calm copper
#

And here is the "vanilla harmony" code that handles prefixes: https://github.com/pardeike/Harmony/blob/master/Harmony/Internal/MethodPatcher.cs#L735. Indeed, it does cancel other prefixes calling if any one in the chain has returned false. So, it's a bug in HarmonyX. Or maybe an intentional change, but it contradicts the original behavior and the related documentation. 🤦‍♂️

So, just to sum up. Do not expect you can prevent other prefixes to override your values. The return result only affects the calling of the original method, not the other prefixes on the method.

median plinth
#

Huh, thats interesting ThinkingF good find

north hatch
#

looks like you can add a check for it though

#

but yeah a system in api to not having to patch common methods would be best

calm copper
#

Yup, the suggested way is verifying for __runOriginal, but for this to work well, all the mods must follow the rule.

vast otter
#

Or add the fix to timberapi 😉

stone shoal
calm copper
#

Or, make a patch at TAPI level for StatusSpriteLoader only. Just checking if the icon name starts from a known mod prefix would cover all the cases, and people won't need to patch this method.

calm copper
#

So, folks, do you think it's feasibel to resolve the icons thing via TAPI? If not, I'll create a mod. If yes, I can make a PR.

#

FYI, at the current momemnt my mod and Tobbert's mod are colliding badly (game crashes). Going forward this will only get worse. One way or another, but it has to be addressed.

severe solar
#

OOoh, inside TAPI is even better yes

stone shoal
#

Yes probably not gonna be something I need to maintain

#

Think im gonna make a specification for it that modders need to add strings to a list

#

To remove the games prefix

calm copper
stone shoal
#

Like Sprites/StatusIcons

calm copper
#

Got it.

lofty lark
#

I'm trying to add a reciepe to a vanilla building, but even taking example from the more snacks mod, it doesn't seem to work

vast otter
#

that is a known bug with U4

lofty lark
#

oh

#

well crap

vast otter
#

do your own prefab and link to base game meshyfile?

lofty lark
lofty lark
#

is there anything that has changed with the custom pivot property (in placable block object) ? it seems that the Z-value is entirely ignored

lofty lark
#

i have uploaded on mod.io (my WB faction) my custom water tower that i just can't get to be placed correctly

#

the legs are 3m long but the last 1 m is purely decorative. the ground should be two meters under the house.
it used to work i think by setting custom pivot Z=-2 but since V4 it seems to be broken, but now it doesn't

#

i tried to make it Z=-2; 0; -8, +8 etc but no bueno, they all result in the exact same thing, the pivot stays on the same level as i defined for the base Z (which i need to be 2 otherwise the game complain that there is no occupancy in the Z level that is the base.)

#

if you try to place it on a 2-tall platform, it places just fine though

#

(no matter which Z pivot is selected)

severe solar
#

Oke, i dont understand completely, but base-z changes the cursor location qswell, so you shouldnt have to change it. Have you looked at the qaterpump how its works there?

#

But isnt really timberapi related

full acorn
#

I think I have it figured out, but I'm assuming that you want the pivot to be at the same height as the floor, rather than the door?

full acorn
#

Ok, well it sorta works, but get this weird thing sometimes:

#

Which is definitely a me issue

#

But all in all, working as a prefab

vast otter
#

Hmm do you have collider and finished and unfinished state?

full acorn
#

Not sure if I have a collider, this was from an export of lapantouflemagic's which didn't have the dependencies so it's a bit kneecapped.

#

I'm assuming the construction site needs a collider?

vast otter
#

ya and meshes

full acorn
#

Hmm

#

Looks like the prefab that imported has a nested construction site; the parent has box colliders, the child has a meshy spec

vast otter
#

and there is a connection to unfinished state in components?

full acorn
#

Aye, unfinished and finished models are set

vast otter
#

no idea then 😦

full acorn
#

I'm at a bit of a loss too, but the block spec seems to work, hoping it's what lapantouflemagic was looking for

lofty lark
full acorn
#

Ahh right, I get you, hence the base level being the lodge

lofty lark
full acorn
#

So if there’s no occupancy for the base level, then there’s no navigable building site, which makes sense looking at the error

#

Aside from that error, it’s working all correctly

lofty lark
#

And the pivot (cursor binding) need to be at the floor level to be placable anywhere 😉

full acorn
#

And the cursor is always at the Z height set

#

I see the problem very clearly now

#

Though tbh I should think of this in the morning

#

Well, after sleep

lofty lark
#

GN 👍

#

And thanks for your effort 😉

#

@stone shoal so it doesn't seem TAPI related ? A few tiny things have changed in the update placing building upgrades is sometimes a bit more sketchy too

#

Like the cursor seem to follow occupancy more that just floors

stone shoal
#

Almost anything unity related has nothing to do with TimberApi

ebon sparrow
#

guys, here is a crash that is sent to us in higher quantity. Maybe you would like to do sth about it, maybe you don't - just FYI. If you need any more info about it just ping me

#

this one is 14% of all crashes we receive

v0.4.9.3-6c7fb02-sw
ModAssetNotLoadedException: Asset (tobbert_moreplatforms) it not loaded
TimberApi.AssetSystem.ModAssetBundle.Load[T] (System.String path) (at <af25edd371414b69b81d2d38ed5d2c5a>:0)
TimberApi.AssetSystem.AssetLoader.Load[T] (System.String prefix, System.String pathToFile, System.String name) (at <af25edd371414b69b81d2d38ed5d2c5a>:0)
TimberApi.AssetSystem.AssetLoader.Load[T] (System.String prefix, System.String path) (at <af25edd371414b69b81d2d38ed5d2c5a>:0)
TimberApi.AssetSystem.AssetLoader.Load[T] (System.String path) (at <af25edd371414b69b81d2d38ed5d2c5a>:0)
TimberApi.ResourceAssetSystem.ResourceAssetLoader.Load[T] (System.String path) (at <af25edd371414b69b81d2d38ed5d2c5a>:0)
Timberborn.ToolSystem.ToolGroupSpecificationDeserializer.Deserialize (Timberborn.Persistence.IObjectLoader objectLoader) (at <65c3f6de70ed4679aa5ac357e1ad3f02>:0)
Timberborn.Persistence.ObjectLoader.Deconvert[T] (Timberborn.WorldSerialization.ObjectSave objectSave, Timberborn.Persistence.IObjectSerializer`1[T] serializer, T& value) (at <5ee48de2acd640e68956ec64c3fc3e37>:0)
Timberborn.Persistence.ObjectLoader.GetObsoletable[T] (Timberborn.Persistence.PropertyKey`1[T] key, Timberborn.Persistence.IObjectSerializer`1[T] serializer, T& value) (at <5ee48de2acd640e68956ec64c3fc3e37>:0)
Timberborn.Persistence.ObjectLoader.Get[T] (Timberborn.Persistence.PropertyKey`1[T] key, Timberborn.Persistence.IObjectSerializer`1[T] serializer) (at <5ee48de2acd640e68956ec64c3fc3e37>:0)
TimberApi.SpecificationSystem.ApiSpecificationService+<GetSpecifications>d__6`1[T].MoveNext () (at <af25edd371414b69b81d2d38ed5d2c5a>:0)
#

it is not always tobbert_moreplatforms (but somehow in 80% of them it is 😅 )

severe solar
#

Ooooh

#

14% another chart im at the top at

#

Probably a dependency error?

vast otter
vast otter
stone shoal
#

Ye tru

stone shoal
#

x

ebon sparrow
#

y

vast otter
#

z

ebon sparrow
#

or xzy if you are in Unity space

severe solar
#

its just like the old usb, you try it once, doesnt work, you turn it around, also doesnt work, switch again and it goes in

lofty lark
blazing girder
austere tangle
#

I know about the error with editor, but, YET, unable to find the culpritt mod. I'm asking, but, in the same time I'm hopping that is not a combination of mods 😮

austere tangle
#

Nope, long time since I change the Scenes to All ...

full acorn
#

Question on the UI fragments - For the UI produced when selecting from the toolbar, is that UIPreview? Taking a look through the examples and trying to figure it out

calm copper
#

In case of you didn't know. When the language is changed in the game, it gets restarted without exiting. It results in re-applying all the Harmony patches made via [Configurator(SceneEntrypoint.MainMenu)]. As a result, there will be duplicated patches. The workaround is to do the check:

    if (Harmony.HasAnyPatches(HarmonyPatchId)) {
      DebugEx.Warning("Skip duplicated patches: {0}", HarmonyPatchId);
      return;
    }

Also, it may be an issue to be addressed at the TAPI level. Should the configurators for the main menu be re-executed at all? It seems people use this stage to do stuff that needs to be executed only once at the game start.

calm copper
#

Using IModEntrypoint is another way to workaround it, but it may be not an option if there are resources that are needed during the load.

calm copper
#

In year 2023, in a C# DLL that is built under Windows 11 for macOS and Windows, we still can find code that checks for running under DOS. And the only thing it does, is reporting:

This program cannot be run in DOS mode.
#

Better safe than sorry.

ebon sparrow
#

Yeah, .net team is crazy about backward compatibility afaik

ebon sparrow
calm copper
#

However, in my code I just added the check just in case. "Better safe than sorry" 🙂

calm copper
ebon sparrow
#

If you want sth to happen only once per session, there is BootstraperConfigurator

calm copper
#

containerDefinition.Install like this?

ebon sparrow
#

99% sure yes

calm copper
#

Thanks, will give it a look.

#

As of now I do:

    if (!Harmony.HasAnyPatches(patchId)) {
      Patch(patchId, patchTypes);
    }

Works fine and doesn't require setting up mod entry point which can be only one per mod.

stone shoal
acoustic eagle
warm cargo
#

Ok, I kept getting crashes so I disabled all my mods except BepInEx Pack and mod manager and some maps and it worked fine. The moment I enabled TimberAPI (I just added it and nothing else), it crashed. Obviously, big problem since every other mod basically needs it

#

Actually, after reading juf816 above and experimenting, I realized I’m in the same situation. Iron teeth works. Folk tails crashes

acoustic eagle
warm cargo
#

Can you start a new Folktail game?

acoustic eagle
#

Yes, downgrading TimberAPI to v0.5.5.6, starting the new game, naming your game, saving and exiting. Upgrading to v0.5.5.7 and loading that save worked for me.

vast otter
#

@stone shoal can you roll back for now

warm cargo
stone shoal
#

I guess I did remove the tutorial after all :/

#

Thought it was working, cleaned up something seems like it did not

unique zodiac
#

Sorry if this is pinned somewhere that I missed, but should the TimberAPI mod currently work with the normal release build (v0.4.9.3)? On mine if I add TimberAPI (even if it's the only mod) it crashes Timberborn.

unique zodiac
#

It was just the generic Timberborn crash screen; nothing mod specific. Good news is that before your reply I tried manually removing everything from the Timberborn folder and started clean and I seem to be getting farther now so I'll let you know if it crashes again. Thanks!

stone shoal
unique zodiac
#

Where can I find the log file? There was no console window open at the time.

stone shoal
unique zodiac
#

All working fine now, thanks! Probably user error--I don't know how many times I restarted Timberborn trying to sort that out but starting fresh was the key.

stone shoal
#

Hmm okay weird

#

But gj

austere tangle
#

Since TimberAPI 0.5.5.7, adding a new recipe to a buiding is not working again.

stone shoal
#

...

acoustic eagle
stone shoal
austere tangle
#

Guess is due to Dynamic specification, maybe will need to migrate to that mod.

stone shoal
#

Not sure why it would conflict

stone shoal
calm copper
calm copper
#

Folks, what's wrong with shades of gray in TAPI? I create the toggles like this:

    var builder = _builder.CreateFragmentBuilder()
        .AddComponent(_builder.Presets().Toggles().CheckmarkInverted(locKey: NeverStopThisGeneratorLocKey, color: Color.green))
        .AddComponent(_builder.Presets().Toggles().CheckmarkInverted(locKey: NeverStopThisGeneratorLocKey, color: Color.yellow))
        .AddComponent(_builder.Presets().Toggles().Checkmark(locKey: NeverStopThisGeneratorLocKey, color: new Color(0x0, 0xff, 0x0)))
        .AddComponent(_builder.Presets().Toggles().CheckmarkInverted(locKey: NeverStopThisGeneratorLocKey, color: new Color(0x50, 0x50, 0x50)))
        .AddComponent(_builder.Presets().Toggles().CheckmarkInverted(locKey: NeverStopThisGeneratorLocKey, color: new Color(0x70, 0x70, 0x70)))
        .AddComponent(_builder.Presets().Toggles().CheckmarkInverted(locKey: NeverStopThisGeneratorLocKey, color: new Color(0x90, 0x90, 0x90)));

And get THIS:

#

And here is a difference between new Color(0x0, 0x0, 0x0) and new Color(0x1, 0x1, 0x1). What do I miss?

median plinth
#

IIRC unity color takes the rgb values from 0 to 1, not from 0 to 255. Might be that it doesnt like when you give it values over 1

vast otter
#

float values?

calm copper
#

Thanks, guys. Of course, it's 1.0 range, not 0xff.

vast otter
#

looks like color32 is 0-255 or 0x00-0xff

calm copper
#

And I was fighting with this "issue" for 30 mins at least.

#
    Color normalColor;
    ColorUtility.TryParseHtmlString("#C6D1CB", out normalColor);
#

Sometimes it's hard to switch between the coding worlds.

vast otter
#

ya

calm copper
#

Now it looks cute:

#

I wonder if TAPI has something like "default panel color". It's definitely not Color.white. #C6D1CB is the most close that I could make.

#

If no color set, TAPI uses just white.

ebon sparrow
#

you mean default font color?

#

in game it is: rgb(204, 204, 204)

#

0.8, 0.8, 0.8 in float values ofc

stone shoal
#

@calm copper Everything sorted itself ?

calm copper
calm copper
crimson estuary
#

Just in case this isn't already known, it seems the cause of construction sites being drawn on top of water is dismissing the priority overlay by right-clicking instead of by clicking the button again

crimson estuary
#

all construction

stone shoal
#

No idea why then

#

You sure it also isn't in vanilla 🙂 ?

crimson estuary
#

it's not that the construction itself is drawn over the water, it's the priority overlay

#

but when it's neutral priority it looks like the normal structure

stone shoal
#

not sure how to fix that

#

Does that work in vanilla ?

calm copper
#

The slider is not shown properly. TAPI 0.5.5.8. Log shows:

230717T182600.932 [WARNING] [UnityEngine.UIElements.StyleSheets.StylePropertyReader.TryGetImageSourceFromValue] Image not found for path: UI/Images/Core/scroll_bar

Any workaround?

calm copper
#

So, I didn't find a quick way to patch it, so ended up with a workaround.

_chargeBatteriesSlider = _visualElementLoader.LoadVisualElement("Common/IntegerSlider").Q<Slider>("Slider");
lofty lark
#

not sure that's a timber api question, but how do you specify an effect in a need ? for a negative need i have plenty of examples, but for a positive one ? i assume just like "favorablewellbeing" triggers when you're >0 and "unfavorablewellbeing" triggers <0 there gotta be a positive equivalent to "Penalties".
I tried "Effect" but nopynope.

#

like in early game version potatoes used to buff carriying capacity or somethin

severe solar
#

Those were reworked and removed. Now only wellness influences beavers from needs. So its indirect. No way to add bonusses directly

lofty lark
#

so we can only add debuffs ? that's a shame.
i guess i can make the debuff negative but i'm not sure beaver behavior will make sense then

vast otter
#

What can be done is have boost per building(for workers) but thats it

calm copper
#

It seems that the TAPI stuff like [Configurator] is not being ran on the DLLs that are dependencies to the main mod DLL. What's the recommended way to deal with it? Obviously, I can make an init method in the dep DLL and have it called from the entry point. However, I'd prefer to just tell TAP to handle the whole DLL for the possible configurators in it.

stone shoal
#

I have no idea what you mean

calm copper
#

"EntryDll": "MyMod.dll". This DLL has a dependency to Dep.dll. I want configurators to be ran in both DLLs. Does it make sense now?

stone shoal
#

Yes no idea how ThinkingIT

#

Does C# have something that it knows it's referenced DLL's

calm copper
#

AppDomain.CurrentDomain.GetAssemblies() ?

stone shoal
#

Hmm

#

That are all from the whole application

calm copper
#

typeof(Configurator).Assembly.GetTypes()

#

It can be not all the types though...

#

On the other had, getting all assemblies and filtering out timberborn, unity and tapi libraries will give a pretty short list of the DLLs to patch.

stone shoal
#

What about all system ones

calm copper
#

Hmm, you're right.

stone shoal
#

I could add it to the mod.json

#

how many are there

#

or load everything in a sub file like, dependencies

#

or lib

calm copper
#

In my case it's just one for now. The use case: I make a component as a separate DLL and it's re-used in scope of water extension. Yes, I can provide soucre and have it compiled in scope of the main Water xtension DLL, but it complicates the process.

#

One way could be a call to TAPI to tell it processing a DLL. Like ConfiguratorRepository.AddRange, but less specific.

#

ConfigurationRepositorySeeder.AddConfiguratorsFromAssemblyToRepository - this!

stone shoal
#

If you reuse it isnt it just more a dpenende cy mod

calm copper
#

Indeed, it will be a dependency and the main DLL still needs to be modified. But this modification is just one liner. Changing mod.json would be a much more favorable way.

#

I just though. I can probably make a new mod instead, and ask water extension to depend on it.

#

Not too welcome to the users, but it it should work.

stone shoal
#

Most people use nod manager they would not even know

#

Else you get woth 2 mods 2 of the same dll and thats also quite a risk to take

calm copper
#

They will still be opening the main mods page to pick one they need. And there, they will see my dependency that cannot be used alone. Not a blocking issues, but just unnecessary wasting of user attention.

stone shoal
#

But om gonna sleep

calm copper
#

Tbh, the existing Mod.io UI is not too convenient even with the existing number of mods.

calm copper
stone shoal
#

Then fix it HappyIT

#

Make and external mod manager?

calm copper
stone shoal
#

Though it coile be improved but UI is all that needs to he done pretty much

full acorn
#

Does TimberAPI allow the use of Bottom Bar sections within a group?

full acorn
#

Fair 'nuf! Thank you 🙂

stone shoal
full acorn
#

Quick question on custom tools, in the docs it states to create a new tool using the normal method. Is there documentation for what this method is? Or is it literally creating a tool in Unity?

#

Or is this a class I need to create?

stone shoal
#

It states that it cannot be made with the normal way ThinkingIT

#

When creating a Tool the original method of Timberborn does not work!

#

and on the next sentence Follow the step to register your tool to TimberApi ToolSystem.

full acorn
#

But then it says Create a new Tool, this step has not changed. which is what I'm confused over

stone shoal
#

That is just general Timberborn 🙂

#

Look at their Tools for info

full acorn
#

Ah, ok! So just their way of creating tools base-game?

#

nice, thank you!

#

Sorry if I keep asking stupid questions 😅

stone shoal
full acorn
#

Gotcha, so it’s just the ‘putting the tool in the game’ thing that TAPI handles?

stone shoal
#

yes

full acorn
#

Running into an interesting quirk with the Button Preset Factory in TAPI's UI Builder. On hover, the text remains white rather than going black the same way the base game ones do.
I noticed that if no colour is provided, then it'll default the style to white. Would this be overriding any sort of effect the hover class will be adding?
(Line 369 of ButtonPresetFactory: https://github.com/Timberborn-Modding-Central/TimberAPI/blob/f23caf659cbd2c9f0597636da78efae374477bc7/Core/TimberApi/UiBuilderSystem/PresetSystem/ButtonPresetFactory.cs#L369C10-L369C10)

#

Is this something I'm doing wrong or is this expected behaviour?

stone shoal
#

But the UIBuilder cannot do hover effects

full acorn
stone shoal
full acorn
#

Thank you! 🙂

stone shoal
#

That should not be a problem with th UIBuilder I believe ThinkingIT

#

Goodluck HappyIT

full acorn
#

Last time I checked out UI Builder it wasn't great, but I probably just didn't understand it well enough ThinkingIT

stone shoal
#

It has quite some limitations I suppose specially with actions like :selector, :hover, :selected since that doesn't exists

full acorn
#

Yeah, I've found myself Doing some jank stuff for Flywheels (when I had even less of an idea of what I was doing) and I kept wanting some of the missing CSS type stuff

#

But hey, it works ShrugFT

stone shoal
#

Oh no need to wait for that, that probablt never going to happen 🙂

#

I believe it's possible, but not a single clue how

full acorn
#

Yeah I'm not going to wait for anything like that to change 😂

#

I believe I saw somewhere about some CSS transpiler to convert it to USS, but can't find it anymore

stone shoal
full acorn
#

Aww shame, well, USS it is then!

#

Because the hacky workaround I'm trying doesn't seem to make Unity too happy

stone shoal
#

Which is

full acorn
#

Uuuuh, rather than changing the background image of the button (which is acting like a toggle), instead have 2 buttons and show/hide the relevant button

stone shoal
#

Isn't that what toggles do

full acorn
#

Is it? Well maybe it ain't such a silly idea after all then

#

There's no way to view the base-game USS styles is there?

full acorn
#

Damnit, turns out that (VisualElement).style.backgroundImage does have a setter. Most of the other styles didn't

stone shoal
full acorn
#

I thought that there was a few I encountered that didn't, so I assumed none of them did, but now I think I might just be going insane thonk

#

because I'm trying them and they all seem to have setters ShrugFT

stone shoal
full acorn
severe solar
#

The uibuilder we have is already so good

full acorn
#

I think there's also a certain aspect of me not understanding it, to be honest

stone shoal
full acorn
stone shoal
full acorn
#

True, and that's where I spent most of my time looking, though there were a few niche things that were missing that I looked through

#

though none of those things have made it into this version which is working now

#

(I.E. I was barking up the wrong tree)

ebon sparrow
full acorn
stone shoal
full acorn
#

Yeah, I imagine I probably did something like that, and then got confused when Rider shouted at me

stone shoal
full acorn
#

Gotta misconfigure it every so often dogekekcry

ebon sparrow
#

I don't think it is Rider, that is screaming

#

It is Roslyn, C# compiler

full acorn
rigid fable
#

found a strange interaction between your mod and simply floodgate triggers, when timber api and sft are both enabled and you use the priority tool for buildings, after you exit the priority tool it leaves color splotches behind under buildings and other things effect by the priority tool

#

not sure if there is anything to be done, just wanted to let you know, all mods still work, so there is no problem there

stone shoal
#

What if you only do TimberAPi

#

The leaving priority could be indeed my problem, weird no one said something about it yet

rigid fable
#

tried it with nothing but timber api, mod manager, bepin and simple floodgate, havent tried it without simple flood gate, gimme a sec

#

just tried it with only timber api, mod manager, and bepin and the colors are still showing up

stone shoal
#

What if you open another tab and close that one

rigid fable
#

no change

stone shoal
#

Do you close it with esc or just clicking ot it?

rigid fable
#

just tried placing something, and newly placed items dont have the splotch

stone shoal
#

because normal doesn't have an splosh

rigid fable
#

and anything with neutral priority has no splotch

#

okay

stone shoal
#

And you have the newest API version (6.0.0) ?

rigid fable
#

just tried closing the tab with escape, right clicking, and clicking back on the tab itself

#

yes

stone shoal
#

Then ill look into it why it's not closing anymore

rigid fable
#

i actually tried dropping a version to see if that fixed it

#

no change

#

just found something, if you select neutral and then exit the priority tab the splotches dissapear

#

to clarify ^, if you select any other priority tab over the items you want at that priority and then select neutral and then close the priority tab it removes all the splotches

stone shoal
#

But you don't drag the neutral over the buildings ?>

rigid fable
#

no

stone shoal
#

Hmm okay

#

Makes it very weird

rigid fable
#

also i just tried clicking on the priority tab itself to close it, cause i realized i hadnt tried that for some reason, it works. so it seems to be a problem with using escape or right clicking to close the priority tab that leaves the splotches

stone shoal
#

Tooo many weird actions tbh

#

if manually closing works means something other method works which is the same as clickign away

full acorn
#

Is there an example for the usage of the Shader System?

stone shoal
#

Shader system ?

severe solar
#

IShaderApllier

severe solar
full acorn
#

And do I apply this script to the game object that has the shader?

severe solar
#

No, it just exists

#

It then gets loaded by TAPI

full acorn
#

Oh! That’s… very straightforward

#

Thank you!

full acorn
#

So I assume from the example given there, I'd need to load the prefab from the asset bundle or something?

stone shoal
full acorn
#

aye

#

two, actually

stone shoal
#

I don't think this would do anything than since it is to set on all things

#

I thought you could just add your shader to the asset bundle and it works, if the shader works in general for the game which might be harder

full acorn
#

you can't apply them on a material-by-material basis?

stone shoal
#

materials have the shaders on them so yes it's material by material ThinkingIT ?

full acorn
#

Sorry, I didn't phrase that very well

#

I was referring to the "ShouldApplyShader" function in the shader loader

stone shoal
#

That determens if the the method apply should run

full acorn
#

I don't think it's even loading at all, I've put a debug log into the load method but not seeing anything in the console

stone shoal
#

Did you add it to the configurator

full acorn
#

Ah, didn;t realise that was needed to - of course it is hidethepain

stone shoal
#

just containerDefinition.MultiBind<IShaderApplier>().To<PathShaderApplier>().AsSingleton(); this part tho

#

but than with your class

full acorn
#

Hmm, no joy with that, but that's a step in the right direction at least!

#

Out of curiosity, if ShaderService is internal, and so is throwing an 'inaccessible' error, is that something to deal with?

#

apologies for what I imagine is a dumb question

#

wait

#

I'm an idiot

#

ignore me

#

or maybe not? urgh sorry, brain is too fried

calm copper
#

Should "DevMode": true be working for a group that is not dev? It always shows to me.

#

Hmm. It seems to not work even for the root level.

calm copper
stone shoal
calm copper
#
{
  "Id": "Automation.DebugPickTool",
  "GroupId": "AutomationToolGroupId",
  "Type": "Automation.Tools.DebugPickTool",
  "Order": -1,
  "Icon": "igorz.automation/ui_icons/bug-tracker",
  "DevMode": true,
  "NameLocKey": "IgorZ.Automation.DebugPickTool.Title",
  "DescriptionLocKey": "IgorZ.Automation.DebugPickTool.Description"
}
stone shoal
#

Your own tool?

#

Did you set the devmode in the factory?

#

Tools have a property that needs to he set iic

calm copper
stone shoal
#

No, might be able to do it maybee but not sure

calm copper
#

https://timberapi.com/tools/ doesn't say the factory should deal with the dev mode. I was getting my knowledge from this page.

#

It's not a big issue, though. My mod is in WIP mode anyway. I just hoped to not reveal too much stuff to the early testers.

stone shoal
#

The example does it too though

#

I can take a quick look if I might be able to do it automatically

#

You can always use hidr

#

Then its never visible

calm copper
#

It's a good idea. I will use it for the releases.

stone shoal
#

public virtual bool DevModeTool => false; I cannot set this even when it's made public

#

Hmm, would also not quite work for already existing Tools thonkeyes

stone shoal
#

Another work around for you is just by them in like a WIP group and make that dev only

stone shoal
#

@rigid fable It is fixed in version 0.6.0.1 could you and maybe @austere tangle check if everything works correctly, made some changed with closing groups

austere tangle
austere tangle
#

I find more useful to see all time for building site the color for altered priorities , but, Important is that the bug is fixed. Can, anytime to activate the priorities group to see the priorities ...

stone shoal
#

Ah ye i suppose some people might found it useful

#

Maybe someone could make a mod that affs a small ui to toggle the modes

austere tangle
#

Was that kind of bugs that was , quite useful 🐸

stone shoal
#

@calm copper Maybe you don't need to string check things anymore for that one mod

#

But I send the exittingToolEvent twice so might also have broken it 🙂

calm copper
stone shoal
calm copper
#

I can only override the tool. When it's already created, the property is readonly.

rigid fable
#

thanks for the fix, seems to be working great

calm copper
#

I'm, not saying it's TAPI issue. I just think that those who are on this channel are the most relevant people to hear it (or prove me wrong).

It seems (I wish to be wrong) that when components are being created in runtime via the BaseInstantiator, the order of methods calls is different. In nutshell, Awake on BaseComponent gets called before InjectDependencies.

#

Maybe I'm just missing the point, and it was always working this way.

In my case I had to move all the stuff to the Start method.

ebon sparrow
#

It was always like this - awake is only for self initialization. You shouldn't call methods or properties on other components

#

Neither use singletons, since they are not yet injected

calm copper
#

It's my fault then. All the way till this moment I thought the injections happens before anything.

severe solar
#

Awake -> injection -> load -> start

calm copper
#

"The more you learn, the more you realize how little you know."

calm copper
# ebon sparrow It was always like this - awake is only for self initialization. You shouldn't c...

I'm looking at Timberborn.BuilderHubSystem.BuilderJobReachabilityStatus. Here is its Awake method:

    public void Awake()
    {
        _builderUnreachable = GetComponentFast<IBuilderUnreachable>();
        _unreachableStatus = StatusToggle.CreateNormalStatus("UnreachableObject", _loc.T(UnreachableBuilderJobLocKey));
        base.enabled = false;
    }

The _loc member is injected from InjectDependencies. How does it work if the Awake method is get called before the injection? Or is it a difference between components created via templates and those that are created in runtime?

ebon sparrow
lofty lark
#

Asking just in case something can be done in TAPI side : I'm having this issue where I have two variants of the same plant (grape vine North-South and East-West orientation) that produces the same thing.

At first I had a crash when clicking on the planter's prioritize button because they had the same lockkey, which is fair enough, do I changed that.

But now I have the same issue again with the harvester, which crash when you try to prioritize one resource, because it looks it up by resource name and not by which plants make it, and find two things that respond "grape"

I don't suppose the Devs will encounter that issue anytime soon so my other solution is to just make both grape trees produce different things

No "oh that's a trivial patch" by any chance ?

vast otter
#

hmm feels more like it should be a component so you can have 2 prefabs in one item
do player need to be able to select ThinkingIT or should it be like walls auto connect to other ThinkingIT

lofty lark
#

Well it crashes when you try to unfold the list. But ideally played should be able to prioritize "grapes" and pick from either variant indifferently

rustic grail
#

can some one help me install this mod i feel like im doing it right but i dont know

stone shoal
#

Just the same as any other mod

rustic grail
#

as in

stone shoal
nova gale
#

will there be a version for U5 preview or are we waiting for release?

median plinth
#

there's this for now #🤖mod-creators message

#

but thats not fully updated for u5 I think

nova gale
#

gonna see if my mods work tomorrow

median plinth
#

rotating sun works with that version of timber api HappyF

stone shoal
#

Most things "work"

#

But all faction specifications need to be changed from "CommonBuildings" to "Buildings"

median plinth
#

well that should be an easy change for the building modders

stone shoal
#

True

#

Buit knatte's extended floodgates also not work

#

No idea if they ever did but yea

#

PlaceableToolObject thing is fixed

median plinth
#

:o nice!

#

with that I think my mods should work after I make the needed changes for new gamelibs

stone shoal
#

yeah screw the console

median plinth
#

also Timber API nearly at 50k downloads 🎉

stone shoal
#

That's more than thunderstore

median plinth
#

true

#

how much was there, 15k?

stone shoal
#

nvm

#

It is 50K

median plinth
#

lmao

median plinth
#

do you have a zip for that?

stone shoal
#

I do now

median plinth
#

thx

#

quick test and seems to work, I'll check the PR

stone shoal
#

aight

naive hinge
#

bro have an error with timberborn api

#

on experimental brench

stone shoal
#

Did you update to latest version.
Did you have other mods running.

calm copper
# stone shoal

With this version I cannot even create new game.

[Error  : Unity Log] TypeLoadException: Could not resolve type with token 010000b0 from typeref (expected class 'Timberborn.WorldSerialization.ObjectSave' in assembly 'Timberborn.WorldSerialization, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null')
Stack trace:
TimberApi.ToolSystem.ToolService.LateLoad () (at <c9a22965d93b4016bd7e8ebb46ff668d>:0)
TimberApi.Core.SingletonSystem.SingletonSystemPatcher+<>c.<LoadSingletonsPostfix>b__5_0 (TimberApi.Common.SingletonSystem.ILateLoadableSingleton singleton) (at <7f7c42a93b3746089ad6e03614457366>:0)
TimberApi.Core.SingletonSystem.SingletonSystemPatcher.LoadSingleton[T] (System.Collections.Generic.IEnumerable`1[T] singletons, System.Action`1[T] action) (at <7f7c42a93b3746089ad6e03614457366>:0)
TimberApi.Core.SingletonSystem.SingletonSystemPatcher.LoadSingletonsPostfix (Timberborn.SingletonSystem.ISingletonRepository ____singletonRepository) (at <7f7c42a93b3746089ad6e03614457366>:0)
(wrapper dynamic-method) Timberborn.SingletonSystem.SingletonLifecycleService.DMD<Timberborn.SingletonSystem.SingletonLifecycleService::LoadSingletons>(Timberborn.SingletonSystem.SingletonLifecycleService)
(wrapper dynamic-method) Timberborn.SingletonSystem.SingletonLifecycleService.DMD<Timberborn.SingletonSystem.SingletonLifecycleService::LoadAll>(Timberborn.SingletonSystem.SingletonLifecycleService)
Timberborn.SingletonSystem.SingletonLifecycleAdapter.Start () (at <a38ce14644da437795019583808b06f8>:0)
nova gale
#

install it via mod manager

#

version 0.6.2

#

and what is your mod list with version?

calm copper
#

nm, figured it crashes only with some mods installed. No problems with no mods.

#

However, the place of the crash is quite surprising.

naive hinge
austere tangle
naive hinge
#

i decided to install update 4.0 but thanks for all

dark quest
#

Anyone else having issues with in-game content mod buttons not loading? I get no errors in the BepInEx window and it correctly nests the unmodded objects but doesn't load the buttons for the modded content so I can't actually use it. The screenshot was taken with just the staircase mod and the dependencies installed (API, Mod Manager and BepInEx), assuming TimberAPI issue because it's true for any in-game content mod (also tried extended floodgates and path extention) and they all seem to be loading correcting according to BepInEx window.

dark quest
#

Yes sorry, U5 using TimberAPI 6.2

severe solar
#

aaah, no, not TAPI problem, its specific mod problem, sortof. A name was changed in the specifications so all mods need to update that name. You can do it manually by going to all FactionSpecifications and changing the CommonBuildings array key to Buildings.

#

if you dont know what that means, you will need to wait for all mods to update it.

vast otter
#

also verify that you do use correct mod version from the google sheet in #🚀mod-users

dark quest
#

On the limit of my knowledge of coding but fixed now, thank you!

vast otter
#

offen it will be a newer version than standard version select mod and chose a newer version

dark quest
#

Ah so when I'd reinstalled the U5 mods I forgot to manually change the version too 🤦‍♂️

acoustic eagle
#

Just recognized the way linebreaks in lockeys used to work is broken in Update 5.
The change from BepInEx 5.4.21.2 to 5.4.22 is not the culprit, tested that. Something changed from TimberAPI 0.6.1 to 0.6.2 that could cause this? Or is this a change in the game?

acoustic eagle
#

Yes from Knattes Dam Decoration mod.

#

And I forced the linebreaks for better readability.

acoustic eagle
#

Tested some more and \u000D\u000A instead of \r\n is working in Update 5 for forcing linebreaks in lockeys. @vast otter
So I'm going to change that in my translation files.

vast otter
#

Hmm wonder how basegame does line break🤔

#

Some one has asset ripped u5 loc files and can check?

acoustic eagle
#

This is copied from the german loc file.


Experimentelle Speicherstände werden separat abgespeichert, da es sehr wahrscheinlich ist, dass die Speicherstände nach Updates nicht mehr kompatibel sind.

In diesem experimentellen Modus <RedHighlight>sind viele Teile des Spiels nicht übersetzt und nur auf Englisch verfügbar</RedHighlight>, ganz unabhängig von deiner Spracheinstellung. Dadurch können wir neue Inhalte hinzufügen und schnelle Änderungen vornehmen, ohne auf zeitintensive Übersetzungen warten zu müssen.

Wir empfehlen dir, unserem offiziellen Discord-Server beizutreten und an den Diskussionen zu den neuen Inhalten teilzunehmen.",Welcome text that is shown to players of the experimental versions of the game.```
Thought the lockey must be in one line.
stone shoal
acoustic eagle
acoustic eagle
#

This works, double quotes required.

doppelte Höhe",-```
vast otter
#

Nice so a simple enter and "" around text 👍

acoustic eagle
vast otter
#

if you can do it and send a zip when done it would be great 🙂

nova gale
#

are we geting a new TAPI version for todays update?

vast otter
#

was something broken in TAPI?

austere tangle
#

As I see, nothing

nova gale
#

TAPI has a dependency to Timberborn.Gamelibs that publicizes the game and coders use

stone shoal
nova gale
#

yeah, what I need is the updated gamelibs

#

btw where does it go? because this returns 404

stone shoal
#

Not to there

#

Baget

median plinth
#

I'll upload new gamelibs in 2 hopefully

stone shoal
austere tangle
#

hours or days ?

median plinth
#

whoops, gonna change that to soon, something goes wrong with the publizicing

stone shoal
#

really ?

median plinth
#

ye, had this same thing happen with 0.5.0, but can't remember how I fixed it

stone shoal
#

Just everything from Timberborn.* and bepinex.*

median plinth
#

Timberborn.* and Bindito.*

nova gale
median plinth
#

check the "show prereleaes" checkbox

nova gale
#

that is it

stone shoal
median plinth
stone shoal
median plinth
#

well tell how it went, I have my own package ready to upload too :D

stone shoal
#

works just fine ThinkingIT

nova gale
#

will you update only gamelibs and I set the version or the API too?

stone shoal
nova gale
#

ok

stone shoal
#

Maybe hytone will

#

You can also just add it yourself

nova gale
#

yes, I did <PackageReference Include="Timberborn.GameLibs" Version="0.5.2-r.0" />

median plinth
#

if it doesn't break stuff, I should be able to update timber api too

nova gale
#

there is no rush, just need to tell people that they need to set the gamelibs version

stone shoal
#

Most modders do it on unity which has no effect

nova gale
#

yeah

median plinth
#

Uploaded TimberAPI 0.6.2.1 to mod.io and nuget which has gamelibs updated to v0.5.2.0

#

unless doing code mods with TimberAPI, there shouldn't be any difference with 0.6.2 and 0.6.2.1 tho

vast otter
#

@stone shoal you talked about having ability to load stuff if an other mod is loaded it is possible to to a revers 2 if mod loaded do not load x

vast otter
stone shoal
vast otter
#

To disable part of mod that breaks if a mod that affect it is installed. Example disable irrigation towers if water absorption is installed

stone shoal
vast otter
#

Well its better then crash was my thought 😜

nova gale
#

besides irrigation towers being gone, is it a real example? and if so do you know why it crashed?

#

I thought my mod worked with any irrigator

#

mods could talk to each other using a MessageBus like the game has one, but probably only will work on PostLoad

calm copper
# stone shoal No

Not loading the mod can have tricky output, but why not at least throw a log? E.g. if I know my mod doesn't work/crashes with another mod installed, I can put it into the package as a "negative dependency". This may help troubleshooting the issues.

    "Dependencies": [
      {
          "UniqueId": "igorz.timbercommons",
          "MinimumVersion": "0.1.0"
      },
      {
          "UniqueId": "!water.absorbtion",
      }
    ]

Yeah, looks awkward, but the syntax can be better.

nova gale
#

I think that if what TAPI is gonna do is just not load mod X if mod Y is present than the best is to crash

#

what could be useful is a load priority for mods.
Make X and Y have different priorities so that X always loads prior to Y.
When Y loads it sees that X is present and it disables only what is incompatible with mod X, instead of the entire Y mod

calm copper
#

That's exactly what gives "tricky output". Some logging if the condition is met is much simplier.

nova gale
#

then the user may not see the log and not realise the mod did not load

vast otter
#

We need interface message with a list with warnings

vast otter
#

A message at the corner with a ! That show info/warning from timerapi

stone shoal
#

You mean the red box when TimberApi is not compatible with the game ?

vast otter
#

No when for example 1 mod is disabled because its missing a dependency

stone shoal
#

I guess that's what Igor said

vast otter
#

Well they miss the warning in the log....

stone shoal
#

Then they come, My screen is red how do I fix KEKW

#

So I think I will check for just a warning message

#

If it crashes in your case they come here show error log, and can delete the mod

#

For the people that actually read it don't come here and delete the mod

nova gale
#

yeah, but not everybody has 2 monitors to see the console with the message

stone shoal
nova gale
#

yeah, but this is y I think letting is crash is better

stone shoal
nova gale
#

so do a beautiful log and crash

crude shuttle
#

As some who try not to bug you people making all these neat things, everything you can put in the logs to help me understand what's broken or not loading or whatnot; is less I gotta bug you. If ppl don't read, you can't really help that lol. If an error isn't clear, that can be helped/fixed.

Ty all for the time you spend on the struggle bus for this API

languid ermine
#

Whelp, looks like the latest experimental update (2023-11-13 v0.5.3.0) broke timberapi ... got this error:
[Warning: HarmonyX] AccessTools.Method: Could not find method for type Timberborn.ToolSystem.ToolButton and name OnButtonClicked and parameters
[Error : TimberAPI] Patcher TimberApi.ToolButton failed.

ShrugFT

unique lodge
#

Confirmed ^

lofty lark
#

He's working on it

severe solar
#

@median plinth i heard you were doing things, maybe you could quickly include the following:

        public PrefixNotFoundException(string prefix) : base($"Prefix '{prefix}' not found")
        {
        }```

The change here is the apostrophe or another way that it is clear when an empty string is the reason that it is a empty string and not just a message saying "Prefix not found". This reads like its just a statement instead of having the empty string in between. 

https://github.com/TobbyTheBobby/TimberAPI/blob/7a39214b7830f27fcc173a363ac42b76e06b2f84/Core/TimberApi/AssetSystem/Exceptions/PrefixNotFoundException.cs#L7
median plinth
severe solar
#

I believe i dont have access and i dont want TheBloodEyes being angry at me for screwing something up

#

(big chance)

#

Thank you for your repsons. Will try it myself 🙂 thanks for the work yesterday LoveIT

stone shoal
burnt wasp
stone shoal
#

oh right you still got the error after removing TimberApi dep ?

severe solar
burnt wasp
#

I don't know anymore, I don't have it open, but I replaced all dependencies with the last one and I got errors with the us prefix, there will be a screen somewhere, I'll find it

#

This error with prefix

stone shoal
#

probably had to do with asset not being loaded than (wrong location or name) and if you have TimberApi also installed it falls back to that

#

and throws an error

#

And then modmanager probably just try catches it and shows the message in the label

#

99% sure

burnt wasp
#

But I didn't have TimberApi loaded

stone shoal
#

(╯°□°)╯︵ ┻━┻

#

Still probably asset not loaded

#

which is also not possible

#

No idea then, no matter. It worked on my PC KEKW

#

Will try removing TimberApi dep when experimental get's to stable

burnt wasp
#

I don't know, well, of course if I use the old dependencies it works, but in this case there was nothing in the console, so it's hard to say where the problem was

#

The only thing I did was to use the latest dependencies directly on the game and harmony, so you can reproduce the error

stone shoal
#

New update of TimberApi will be live in a few minutes

  • Control scrolling is still semi bugged
  • Code requires to be checked again after it hit stable
wispy crypt
#

Yay! vanilla is so confusing 🤣 need my mods

lofty lark
#

i can't seem to get custom yield removing ressource groups (for example a lumberjack that harvests only one special tree) It used to work before though. before i resort to poking pmduda, any chance that could be a TAPI thing ?

stone shoal
lofty lark
#

get it to work sorry

#

it gives me this error as soon as i hover on top of the icon:

#

but if i set the tree as a regular "cuttable" it works just fine

#

ie : to be cut by regular lumberjacks and not the custom one

stone shoal
#

could you try to say it in bullet points what you want to achieve my brain is mush

lofty lark
#
  • make a custom tree
  • in its (cuttable) yielder specification set "ressource group" to "Custom"
  • make a custom lumberjack flag
  • in its "yield removing building" script set "ressource group" to "Custom"

now the custom tree is set to be cut by the custom lumberjack.

or should be, it crashes because somehow the "custom" ressource group is not created or something, but it used to work

stone shoal
#

What is a reousrce group ?, what's in the original

lofty lark
#

the originals are "cuttable" for all trees and such, "Farmhouse" and "AquaticFarmhouse" for their respective crops, "Gatherable" for gatherable stuff (berries, chestnuts, coffee) and lastly "Ruin" for the scavenger but this one might be a bit special.

note that it has never been super clear to me how they are defined. i assumed they are created whenever something claims to be part of a groups (it's not defined by the yield removing script because you can have different buildings cut the same things)

and on the other hand, there is something different but with similar naming which are planter groups (forester, Farmhouse AquaticFarmhouse) for who plants what. and my understanding is that the planter group is only created by the "planter building" script but it is entirely separate from the other property. typically berries are planted by the forester but gatherable, crops can be planted by the farmhouse but haversted by the aquatic one etc.

anyway there is no issue with the planter group, it's just so that you don't get confused if you ctrl-H in the game scrips.

vast otter
#

Tried this: ?

done a clean import with tunderkit?

  • remove package\timberborn
  • import Timberborn

Compared with latest plants maybe removed some script and now you add it your self to ThinkingIT

#

my thought was that some time before they moved from a component was added in prefab to be added by script if an other component was added

lofty lark
#

i didn't do a 'clean' import but i ripped the latest version, removed the troublesome folders (audio mixer controller +editor + plugin) and tossed the rest in unity

#

then i ran thunderkit to exctract stuff from the game until it stopped crashing

#

but i didn't erase existing stuff

stone shoal
vast otter
#

well then you can have an old script still in your files but does not exist ingame

lofty lark
lofty lark
#

i'll keep poking at stuff but i might need some more advanced help

#

for the time being i'll revert those plants to the generic groups

lofty lark
#

pretty sure not

#

letme double chek

#

nah, they are exactly identical

vast otter
#

😦 then im not sure what is happening

ebon sparrow
#

@lofty lark it is somehow related to new tree cutting

#

It is failing on GetRemoveTreeStrategy

#

so there is an interfeca IRemoveYieldStrategy that need to be on prefab ThinkingIT

#

I'm on mobile so hard to check what is implementing this interface

#

But maybe later or tomorrow I can check

#

Looks like you are just missing sth

lofty lark
#

my suspicion was that the missing element was linked to cuttable yielder - Cuttable group

#

no hurry, i'd be happy enought to have help whenever that works for you 🙂

ebon sparrow
#

as I said - there is a component missing that implements IRemoveYieldStrategy - but on mobile I can't check which components implements it

vast otter
#

so compare tree prefabs

ebon sparrow
#

Maybe in trees there is sth? ThinkingIT

lofty lark
#

okay, my other custom plants work just fine though 🤔

ebon sparrow
#

probably they use some default implementation of that interface that is auto decorated?

#

But for trees must be added manually?

#

In which module is TreeComponent located? Forestry?

lofty lark
#

custom trees also work

#

yeah they have tree component

#

it only crashes when i change the yielder specification group from "cuttable" to "custom"

ebon sparrow
#

ah... now I get it

lofty lark
#

can't see any new scripts on the mangrove nor birch

#

ah ?

#

i don't 😅

ebon sparrow
#

TreeRemoveYieldStrategy is for trees

#

But they are for Cuttables

#

so, when you change cuttable to custom, there is none RYS that is matching

lofty lark
#

hmm

ebon sparrow
#

so you either need to add a new RYS

#

for custom

lofty lark
#

is that difficult to do ?

ebon sparrow
#

or patch TRYS to work also for custom

#

dunno, you probably need a copy of TRYS? With one field changed

#

I did nothing with that system so not really aure how it works internally

lofty lark
#

any chance someone at machinistry could rework a couple of line so it works with all treecomponents no matter whether is cuttable or custom ? 🙏😇

lofty lark
#

oh sorry for the ping

ebon sparrow
lofty lark
#

i think @full acorn is not super available lately, but i'll flag him so that he can take a look when he can

lofty lark
#

wait is there also cutting strategies for cuttable- Farmhouse etc ?

#

to be fair having a custom cuttable group is not really vital

#

but the default lumberjack can store 20, which is fine for logs, but storing 20 entire sequoias... 😅

#

anyway, thanks for your help ! gotta go to bed soon

#

and by that i mean 10minutes ago

full acorn
#

Ah, just catching up on the chat, @lofty lark let me know if I can help at all, goodnight!

burnt wasp
#
[Error  : Unity Log] NullReferenceException: Object reference not set to an instance of an object
Stack trace:
Bindito.Core.Internal.ContainerDefinition.Install (Bindito.Core.IConfigurator configurator) (at <77aeff39aa1a4904bcb9a4557d4d140e>:0)
TimberApi.Core.BootstrapSystem.BootstrapPatcher.BootstrapperConfiguratorPatch (Bindito.Core.IContainerDefinition containerDefinition) (at <15e036bce62e4b13926bdb86cd247af2>:0)
(wrapper dynamic-method) Timberborn.Bootstrapper.BootstrapperConfigurator.DMD<Timberborn.Bootstrapper.BootstrapperConfigurator::Configure>(Timberborn.Bootstrapper.BootstrapperConfigurator,Bindito.Core.IContainerDefinition)
Bindito.Unity.ProjectConfigurator.Bindito.Core.IConfigurator.Configure (Bindito.Core.IContainerDefinition containerDefinition) (at <b6703cff75744c15a6c94fd47a3c1ca4>:0)
Bindito.Core.Internal.ConfiguratorRunner.RunConfigurators (System.Collections.Generic.IEnumerable`1[T] configurators) (at <77aeff39aa1a4904bcb9a4557d4d140e>:0)
Bindito.Core.Internal.ContainerCreator.ConfigureContainer (Bindito.Core.IContainer container, System.Collections.Generic.IEnumerable`1[T] configurators, Bindito.Core.Internal.IBinder binder, Bindito.Core.Internal.IProvisionListenerNotifier provisionListenerNotifier, Bindito.Core.Internal.IInjectionListenerNotifier injectionListenerNotifier) (at <77aeff39aa1a4904bcb9a4557d4d140e>:0)
Bindito.Core.Internal.ContainerCreator.CreateContainer (System.Collections.Generic.IEnumerable`1[T] configurators) (at <77aeff39aa1a4904bcb9a4557d4d140e>:0)
Bindito.Unity.ProjectConfigurator.Awake () (at <b6703cff75744c15a6c94fd47a3c1ca4>:0)
UnityEngine.Object:Instantiate(ProjectConfigurator)
Bindito.Unity.Internal.ProjectContainerProvider:GetProjectContainer(ProjectConfigurator)
Bindito.Unity.SceneConfigurator:CreateSceneContainer()
Bindito.Unity.SceneConfigurator:Awake()

@stone shoal , @median plinth
Can be fixed?

#

I don't know if it's possible to fix it on the TAPI side, I'm rather asking, but it's NPE

[Error  : Unity Log] NullReferenceException: Object reference not set to an instance of an object
Stack trace:
Bindito.Unity.SceneConfigurator.CreateSceneContainer () (at <b6703cff75744c15a6c94fd47a3c1ca4>:0)
Bindito.Unity.SceneConfigurator.Awake () (at <b6703cff75744c15a6c94fd47a3c1ca4>:0)
severe solar
burnt wasp
#

I need to get out the tapi version from TBMPL without loading the library into the domain. It throws NPE, so it would be enough to treat it in TAPI in
TimberApi.Core.BootstrapSystem.BootstrapPatcher.BootstrapperConfiguratorPatch

severe solar
#

idk, sounds like you problem

burnt wasp
#

in the log, you have written NPE from the TAPI source, so it can't be my problem 😉

severe solar
#

well, i never experienced any issues with TAPI

#

so means something you did which makes it crash

#

what is NPE btw?

burnt wasp
#

null pointer exception

severe solar
#

whats that? NullReferenceException?

burnt wasp
#

yep, probably configurator is null

severe solar
#

one you are trying to add?

#

again, what is it you are trying todo that makes it crash?

burnt wasp
#

no, it happens automatically because bepIn tries to load all the dlls and even if I load it without a domain, it calls Awake (which it shouldn't) so something falls to null

severe solar
burnt wasp
#

like that it works when I load it normally into the domain but this time I need it without it and this problem occurs because BepIn calls Awake on something that is not linked to other libraries

#

and of course I need to load the dll to find out the version, just omg situation..

stone shoal
#

What did you do to cause it

burnt wasp
#

to cut it short, it loaded the tapi without game dependencies... just need to find out the version, that's all

burnt wasp
#

I do this before loading bepinex

stone shoal
#

Decompile the DLL in runetime and read it out of the cs script

burnt wasp
#

I would also need a GUID

stone shoal
#

Same answer

burnt wasp
#

I can't decompile it, this option fails because I can't get the Assembly

stone shoal
#

How would you I be able to give you the version if the code may not even be loaded

burnt wasp
#

There is no need to load the code for the version, I have already figured out how to solve that, I have a bigger problem with the GUID, which is only in one place and that is probably not possible without Asm

stone shoal
#

it's inside the loader

#

it's just as anything else a bepinex mod

burnt wasp
#

no, it does something completely different than what I needed, but I already solved it, but thx

calm copper
#

Out of curiosity, what did you need? I though, it's the assembly version.

burnt wasp
#

I needed to get an Assembly instance for another plugin, but not to add it to the unity domain. The problem was that it behaves a little differently than in the case of a normal application, because here a different plugin is loaded and not the game (application) itself

calm copper
#

Hmm. A pretty unusual usecase. Indeed, it would be tricky.

burnt wasp
#

yep, that's all when patching a game that doesn't (yet) have official mod support. Nothing can be done easily

austere tangle
stone shoal
#

Wait they changed the versioning thonkeyes

ebon sparrow
#

we added a struct GameVersion

#

that is now returned by that method

stone shoal
#

Should be easy

#

If that's is going to be the only issue

median plinth
#

Cant be, they have more coders now so gonna expect more stuff to break

stone shoal
#

Ikr, and we just ask all of it to the new one MomijiHype

ebon sparrow
stone shoal
austere tangle
#

Sure is more, TAPI don't crash the game, but neither get loaded

dapper crown
#

@ebon sparrow I request a "Mechanistry devs broke modding again" stiker 😄

stone shoal
#

Well if we could drag one more dev in modding scene wouldn't be too bad I suppose, but not everyone is such a holesome workaholic

stone shoal
austere tangle
#

And, Mod Manager do not have that check ? Mod Manager is working ThinkingIT

stone shoal
#

Mod manager does not care about the version, like most mods don't if they would not use TimberApi

austere tangle
#

Yep, that's why mimic's mods are working ❓

stone shoal
#

¯_(ツ)_/¯

#

TimberApi has way more features and so more chance to break

#

Doubt that error will be all

austere tangle
#

U5 was 👹 for TAPI, second time it get a hard hit 😬

stone shoal
dapper crown
ebon sparrow
#

now better :)

stone shoal
#

😄

dapper crown
#

Yeah, love it!

stone shoal
#

Now everyone can spam that sticker on a update

ebon sparrow
austere tangle
#

I know, and is using it's own way to check version

orchid sage
#

Application.Version still works though right? (I use this).

burnt wasp
#

yes, that should be used, I don't know what Tapi uses to detect the version

burnt wasp
burnt wasp
#

Why doesn't Unity use code to detect the version? 🤔 It won't break on update

stone shoal
#

Probably won't change another time 🙂

#

else unlucky

burnt wasp
#

just that TAPI wouldn't have to break every time anything changes 🙂

stone shoal
burnt wasp
#

I was just thinking about finding out the version of the game

stone shoal
#

Just because it's this time because of the version won't change that it break on other stuff tho

#

Might even better that it broke on it, else it could have crashed on the other problem which might needed a manuall uninstall

#

Maybe I could add something specially for experimental that it requires the specific version else won't load

#

Downside it will always need to be reuploaded every update, but launchers can't crash due of it

#

Anyway...

#

TimberApi 0.6.3.1 is released, working for latest experimental version.
https://mod.io/g/timberborn/m/timberapi

  • Warning: new scrolling feature of Timberborn might crash your game, unknown if this was already a problem in previous version.
    • Will not be solved/checked until it hits stable.
burnt wasp
#

I found a bug

#

it's missing when I use TAPI, why is tapi editing the panel?

severe solar
#

did you create a custom tool?

#

Tapi reworked the Toolbar

burnt wasp
#

no, I don't have any tool or none of my mods reach this panel.. i will try it with tapi only but as soon as i added tapi it disappeared

severe solar
#

what is that, thats base game?

burnt wasp
#

yes... tapi removed water tool 😭

severe solar
#

Yea, needs to be added as tool via Tapi

burnt wasp
#

yep, that's why I'm writing this here to fix it when tapi is already updated to 5.4.0 😉

severe solar
#

I just answered your question 😉

burnt wasp
#

Well, that will be fixed in the tapi 🙂

#

So explain one more time. I guess we don't understand each other now
Yea, needs to be added as a tool via Tapi <-- Did you mean by this that it will be fixed or?
The point is that TAPI broke the original behavior in the game so I expect them to fix it. I actually use the water tool sometimes and I really miss its absence

stone shoal
#

Yea its possible that a new tool is added

#

Tho its the unspoken mode, could you make a issue for it on github? Will be fixed in stable release.

#

Was probably already missing last update ThinkingIT

burnt wasp
#

yep, it was already missing in the previous update, maybe since version 5, but I don't know for sure

#

I don't have github, so I'm writing it here for someone to look at 🙃

lofty lark
#

is timber api broken with the new update ?

median plinth
austere tangle
#

TAPI is working ... Only mods that are broken (that I was used) are Smart power and Rotating Sun 😭

burnt wasp
#

ehm... what? merge bug?
0.6.3.1+25d5e6c8bea7651b095b79625414659e6b8821e2

#

Can you fix it? I wanted to show the TAPI version, but there is a redundant hash

median plinth
#

how do you get it?