#KRPG Enchantment

1856 messages · Page 3 of 2

dawn kernel
#

Maybe they patched it in already and I didn't realize

elfin wren
#

I dont think you can enchant the handle?

#

YK I should try that lol

dawn kernel
elfin wren
#

If everything I sent works and it gets published to the mod then a ping about the update would be awsome.

dawn kernel
elfin wren
elfin wren
#

This is all I see on the pull request btw

dawn kernel
#

You don't see these?

elfin wren
dawn kernel
# elfin wren

Sorry, I'm probably doing something wrong. It's pretty late for me

#

I totally replied to the other one too lol

elfin wren
#

Your all good. I'll try to fix the Modsystem part.

I dont know how to explicitly reference the method I made. Everything I tried threw an error.

dawn kernel
#

Ah there we go. I had to submit the comments

elfin wren
#

I see them now LOL

dawn kernel
#

oopsie, but now I know

elfin wren
#

@dawn kernel Everything you left comments on should be fixed now.

#

oops. I accidently pressed a button that said unassign me? I hope that wasn't important LOL.

#

I wonder what that functionally does?

#

Its 11:40PM for me. I'm going to get some sleep. If there is anything else I need to change feel free to put it in the pull requests comments and I'll look at it when I can.

#

Thanks for all the help with this! Your much cooler about this kind of thing than some other mod devs I've talked to for other games.

dawn kernel
elfin wren
dawn kernel
elfin wren
dawn kernel
#

yeah, its a bit diff based on if you need explicitly sided API access

#

Then there are several ways to get that sided API

#

like the EnchantAccessor has different controls based on which API you address its interface from

elfin wren
#

Is there a place where the thing you mentioned in the your comment is done that I can use as reference?

dawn kernel
#

LightningEnchant does something similar

#

oh, maybe I put it in the constructor

elfin wren
#

KRPGEnchantment doesn't appear to be valid?

#

Changing that to the ToolmithSystem class name doesn't work either

dawn kernel
#

Initialize is definitely the right spot to do it. I guess I need to update Lightning

dawn kernel
elfin wren
#

ah

#

That makes more since actualy

dawn kernel
elfin wren
#

Ya, I've learned about how to use base. If I'm not mistaken it lets you override a method and by using base you can make it also use the original method just with your additions.

dawn kernel
#

Exactly

elfin wren
#

Ok, I think I got it "working".

Under ProcessReversion where I was calling a static ToolsmithReversion from the ToolsmithSystem itself I now have it pointing to the ToolsmithSysServer in the KRPGEnchantmentSystem which lets me access my now non-static ToolsmithReversion method

public class TrversionEnchantment : Enchantment
{
  //...
  ToolsmithSystem ToolsmithSystem;
  //...}

public override void Initialize(EnchantmentProperties properties)
{
  //Other Initialize stuff
  ToolsmithSystem = Api.ModLoader.GetModSystem<KRPGEnchantmentSystem>()?.ToolsmithSysServer;
}
//...
private void ProcessReversion(ItemSlot slot, int power)
{
  //ProcessReversion Logic
  ToolsmithSystem.ToolsmithReversion(slot, amount);
}
#

Now I just need to check that it still makes the items repair correctly. And Assuming I did it the way you were telling me about it will hopefully be good?

#

Yep the tool is repairing itself still

dawn kernel
#

Yep, that's it exactly!
I would make sure to null-safe all your stuff, but that's basically the KRPGEnchantment "right way" of doing things

elfin wren
#

I'm probably going to get suplexed for this question but how do you make it null safe in this context. Was it that ? part? If so I think I can do that

dawn kernel
#

It's sort of a process of checking that everything you don't necessarily have control over doesn't return null in a way that would crash any later code

#

adding a ? after something in a get method will check if the object is null before continuing

elfin wren
#

AHH I DID IT!

dawn kernel
#

Ex:
Api?.ModLoader?.GetModSystem<KRPGEnchantmentSystem>()?.ToolsmithSysServer
Will allow you to 1-line a complex set of checks while getting the ToolsmithSysServer

#

We don't need to store KRPGEnchantmentSystem itself, just the ultimate endpoint of ToolsmithSysServer

elfin wren
#

I get why we use the ?.ToolsmithSysServer but why do we do that to the Api?.Modloader?.GetModSystem<KRPGEnchantmentSystem>()

dawn kernel
#

Then, when you go to

private void ProcessReversion(ItemSlot slot, int power)
{
  if (toolsmithSysServer == null)
  {
     Api.Logger.Error("[KRPGEnchantment] Toolsmith compatibility system null during Reversion check!");
     return;
  }
  // Other logic
  toolsmithSysServer.ToolsmithReversion(slot, amount);
}
elfin wren
#

I figure that Modloader and GetModSystem would always be present so would just checking for ToolsmithSysServer work?

#

Assuming the ? applies to the part after itself

dawn kernel
#

they should be present

elfin wren
#

Oh, I see

dawn kernel
#

the difference is getting an error about it or crashing the server

elfin wren
#

Fair enough

elfin wren
#

Ok, I did something wrong because in testing I got.
[KRPGEnchantment] Toolsmith compatibility system null during Reversion check!

dawn kernel
#

heheh

elfin wren
#

You obviously know something that I don't đŸ€”

dawn kernel
#

That's why we're checking

elfin wren
#
private void ProcessReversion(ItemSlot slot, int power)
        {
            if (slot.Empty == true) return;
            int amount = power * PowerMultiplier;
            int remDur = slot.Itemstack.Collectible.GetRemainingDurability(slot.Itemstack);
            int maxDur = slot.Itemstack.Collectible.GetMaxDurability(slot.Itemstack);
            if (remDur < maxDur)
            {
                remDur += amount;
                remDur = Math.Min(remDur, maxDur);
                slot.Itemstack.Attributes.SetInt("durability", remDur);
                if (EnchantingConfigLoader.Config?.Debug == true) { Api.Logger.Event("[KRPGEnchantment] Restoring {0} durability.", amount); }
            }
            if (ToolsmithSystem == null)
            {
                Api.Logger.Error("[KRPGEnchantment] Toolsmith compatibility system null during Reversion check!");
                return;
            }
            else if(EnchantingConfigLoader.Config?.Debug == true)
            {
                Api.Logger.Event("[KRPGEnchantment] Toolsmith compatibility system is active.");
            }
            ToolsmithSystem.ToolsmithReversion(slot, amount);
        }
dawn kernel
#

I may have to look at it in context if you wanna commit to your repo

elfin wren
#

Ya give me a sec

dawn kernel
#

The idea is that we need to determine if the ToolsmithSysServer actually loaded or not, then choose to run the custom logic or not based on if it's null or !null

elfin wren
#

Its updated now

#

Note that there are 2 branches. Working changes are pushed to you through the "clean" branch. And my latest stuff is on main with a bunch of other files that may not be relevant because it was auto generated or change by my IDE

dawn kernel
#

okay, so master is the right branch?

elfin wren
#

Master is all the stuff I was just working on rn.

dawn kernel
#

does Toolsmith affect weapons as well as tools?

elfin wren
#

No

#

Just tools

#

There is an addon I think that makes it affect weapons

dawn kernel
#

So we need 1 more thing to determine if it's a Toolsmith enabled tool

elfin wren
#

Thats done in the ToolsmithReversion method

#

slot.Itemstack.GetToolhandleForData() != null
Checks if it has a toolsmith handle and this is also done seperatly for the binding

dawn kernel
#
        private void ProcessReversion(ItemSlot slot, int power)
        {
            if (slot.Empty == true) return;
            int amount = power * PowerMultiplier;
            
            if (IsTSTool && ToolsmithSystem != null)
            {
                ToolsmithSystem.ToolsmithReversion(slot, amount);
                return;
            }
            
            int remDur = slot.Itemstack.Collectible.GetRemainingDurability(slot.Itemstack);
            int maxDur = slot.Itemstack.Collectible.GetMaxDurability(slot.Itemstack);
            if (remDur < maxDur)
            {
                remDur += amount;
                remDur = Math.Min(remDur, maxDur);
                slot.Itemstack.Attributes.SetInt("durability", remDur);
                if (EnchantingConfigLoader.Config?.Debug == true) { Api.Logger.Event("[KRPGEnchantment] Restoring {0} durability.", amount); }
            }
        }
#

This way we only skip default logic if ToolsmithSystem does exist AND the tool is a Toolsmith enabled tool

elfin wren
#

Because the tool head uses the base vanilla durability of the tool your preexisting repair logic only fixes the tool head. The ToolsmithReversion method checks if the held item with reversion has a tool handle or binding and if it does then it repairs it.

#

So we only need to have a check to make sure Toolsmith is installed to prevent the game from stopping when trying to call ToolsmithReversion if it isn't present

#

Shears dont have a handle or binding so I use them for testing

dawn kernel
#

Ok, so it would just go to something like this then?

        private void ProcessReversion(ItemSlot slot, int power)
        {
            if (slot.Empty == true) return;
            int amount = power * PowerMultiplier;
            int remDur = slot.Itemstack.Collectible.GetRemainingDurability(slot.Itemstack);
            int maxDur = slot.Itemstack.Collectible.GetMaxDurability(slot.Itemstack);
            if (remDur < maxDur)
            {
                remDur += amount;
                remDur = Math.Min(remDur, maxDur);
                slot.Itemstack.Attributes.SetInt("durability", remDur);
                if (EnchantingConfigLoader.Config?.Debug == true) { Api.Logger.Event("[KRPGEnchantment] Restoring {0} durability.", amount); }
            }
            if (ToolsmithSystem != null)
            {
                ToolsmithSystem.ToolsmithReversion(slot, amount);
            }
        }
#

or I guess it would be inside the remDur<MaxDur condition

elfin wren
#

No

#

If its in the RemDur condition it will prevent the handle and tool binding from repairing unless the tool head it damaged

#

There is a separate remDur for the handle and binding

dawn kernel
#

Okay, then we just needed to simplify the null checks

elfin wren
#

Sounds about right

dawn kernel
#

Awesome, sounds like we might be near the finish line eyes_shake

elfin wren
#

LOL, thats what I said yesterday

dawn kernel
#

Needs testing in SP and MP, with and without Toolsmith

elfin wren
#

The issue I'm running into is that the ToolsmithSystem check is always returning null

#
            if (ToolsmithSystem == null && EnchantingConfigLoader.Config?.Debug == true)
            {
                Api.Logger.Error("[KRPGEnchantment] Toolsmith compatibility system null during Reversion check!");
                return;
            }
            else if (ToolsmithSystem == null)
            {
                return;
            }
            else if (EnchantingConfigLoader.Config?.Debug == true)
            {
                Api.Logger.Event("[KRPGEnchantment] Toolsmith compatibility system is active.");
                ToolsmithSystem.ToolsmithReversion(slot, amount);
            }
            else
            {
                ToolsmithSystem.ToolsmithReversion(slot, amount);
            }
#

There is probably a simpler way to do that if stuff but this is just expanded form

dawn kernel
elfin wren
#

Ya

#

The other stuff is just conditions for logging

#

WAIT

#

OOPS

dawn kernel
#

If you want to put an else for just logging, then you need to identify what is null. Perhaps using the wrong sided API?

elfin wren
#

oh nvm brain what?

elfin wren
#

That might tell us why its returning null

#

KRPGLib.Enchantment.KRPGEnchantmentSystem.ToolsmithSysServer.get returned null.

#

Ah, yes. My IDE is obviously a genius. I could never have figured that out on my own 🙄

#

Its returning null because we were using .ToolsmithSysServer after GetModSystem

dawn kernel
#

Is that for a Client sided null check?

elfin wren
#

It shouldn't even touch the client side one if I'm not mistaken because its using ToolsmithSysServer

dawn kernel
#

Initialize will run on either side, so you should maybe API.Side check before assigning server

elfin wren
#

Like checking that its using the sApi instead of just Api because Api can also be cApi?

dawn kernel
#

so something more like

        public override void Initialize(EnchantmentProperties properties)
        {
            base.Initialize(properties);
            tempStabilitySys = Api.ModLoader.GetModSystem<SystemTemporalStability>();
            riftSys = Api.ModLoader.GetModSystem<ModSystemRifts>();
            if (Api is ICoreServerAPI sapi)
            {
                ToolsmithSystem = sapi.ModLoader.GetModSystem<KRPGEnchantmentSystem>()?.ToolsmithSysServer;
            }
        }
elfin wren
#

Ok perfect because I was actually just looking at and looking up how it worked on google

        public void StartServerSide(ICoreAPI api)
        {
            if (!(api is ICoreServerAPI sapi)) return;
        }
dawn kernel
#

Yeah, we're gonna do a positive check vs a negative check because we may have other logic to run

#

negative check like that would be if the method must only run on a certain side

#

but Initialize will run on both client and server side, so we just need to only grab the ToolsmithSysServer on the Server side, and we can grab the client sided version if we need it for some other reason by just changing over the side of the statement

elfin wren
#

And because durability is handled server side regardless of multiplayer or single player we just need to worry about using server side.

dawn kernel
#

Right. Now, if we wanted to say trigger particles, or do something else client sided, we will have to build it out for that specifically

elfin wren
#

Ya

dawn kernel
#

(There are some things which just happen client side in VS that will catch you off guard)

elfin wren
#

Meaning someone could possibly make a mod to allow for the player to teleport around thats client only.

#

Assuming they dont have server side safe guards for that.

#

I suppose that the server could allow it though if it was due to packet loss or overload or something like that.

dawn kernel
#

There are some safeguards for position changing. I know they changed some of that in 1.22, but there was specifically server-sided positioning you had to use over client-sided to avoid that stuff

#

mining values is also affected by this

#

Talk about a nightmare getting that to respect the server's Enchantment configs blobsweat

elfin wren
#

I remember that during a period of high server lag I was fighting but then ran into a house and 3 minutes later got downed (in a room without mobs) and saw a trail of blood slowly creep under my door.

#

So the server thought that my player was killed outside and crawled inside when on the client I had walked normally into the house while being alive.

#

It was kind funny

#

I got a screenshot of it. I titled it "The lag is killing me"

#

15.10.2026 11:11:40 [Server Event] [KRPGEnchantment] Api is ICoreServerAPI sapi
15.10.2026 11:12:09 [Client Event] [KRPGEnchantment] Api is not ICoreServerAPI sapi
@dawn kernel

#

I can place a ? on ToolsmithSystemServer to stop it from throwing the exception but that doen't make it work.

#

I think that the API side is already correct.

#

The issue is probably somewhere else

#

Here is what google thinks

#

If ToolsmithSystemServer is a property with a custom setter, or if there is an implicit type conversion happening on the assignment side, the compiler can sometimes struggle to evaluate the null-propagation chain correctly.
By pulling it out into a standalone var statement, you force the compiler to strongly type the returned KRPGEnchantmentSystem object before you attempt to read fields or properties from it.

#

Its failing at the ToolsmithSysServer

#

Initialize() is being called before StartServerSide()
@dawn kernel

#

Its the right information at the wrong time kind of thing.

dawn kernel
elfin wren
#

lol

dawn kernel
#

It's possible something is out of order

elfin wren
#

I'm testing an idea that might fix it

#

Did it

#
private ModSystemRifts riftSys;
private SystemTemporalStability tempStabilitySys;
private KRPGEnchantmentSystem EnchantSysCore;
private ToolsmithSystem ToolsmithSystemServer => EnchantSysCore?.ToolsmithSysServer;
public override void Initialize(EnchantmentProperties properties)
{
    base.Initialize(properties);
    tempStabilitySys = Api.ModLoader.GetModSystem<SystemTemporalStability>();
    riftSys = Api.ModLoader.GetModSystem<ModSystemRifts>();
    if (Api is ICoreServerAPI sapi) { EnchantSysCore = sapi?.ModLoader?.GetModSystem<KRPGEnchantmentSystem>(); }
}
#
private ToolsmithSystem ToolsmithSystemServer => EnchantSysCore?.ToolsmithSysServer; //This fixes the issue by pointing to a varable that gets filled out at a later time (I think)
#

To to make sure that it doesn't break if it fails once we can use

ToolsmithSystemServer?.ToolsmithReversion(slot, amount);
#

The ? should prevent it from crashing by checking if ToolsmithSystemServer is != null right?

#

@dawn kernel I've update my github master branch with the fixed null checks

dawn kernel
#

Awesome, sorry for lack of input. Had some work calls

elfin wren
#

Your all good. I'm the no life here. (Man I need a job)

#

lol

dawn kernel
#

It's probably good enough for me to take over if you got it working reliably on your end, though

elfin wren
#

I think soo too. I've pushed the change from the main branch I had to the clean one and so the pull request should be fully up to date other than one missing dependency.

#

I've added the reference to the krpgenchantment.csproj file
I use $(VINTAGE_STORY_DATA) on my pc but I've made it match your directory setup. (Aka the one I saw in your github)

Yours:

<Reference Include="toolsmith">
    <HintPath>../../../Examples/toolsmith_1.2.19/Toolsmith.dll</HintPath>
    <Private>false</Private>
</Reference>

Mine:

<Reference Include="toolsmith">
    <HintPath>$(VINTAGE_STORY_DATA)/Mods/toolsmith_1.2.19/Toolsmith.dll</HintPath>
    <Private>false</Private>
</Reference>
dawn kernel
#

Awesome, tysm

dawn kernel
elfin wren
#

Before the fix it was only the tool head

dawn kernel
#

I see you added it, but in my testing it wasn't working for binding

#

Handle yes, binding no

elfin wren
#

That's odd. The method for the binding and handle should be the same other than the key word binding and handle.

dawn kernel
#

I just grabbed a random tool from Creative menu, so idk if it's just the way I did it

elfin wren
#

I'll test my end rq

dawn kernel
#

I see no reason why it shouldn't work

elfin wren
#

Oh then it doesn't have a actual binding I think

#

Hmmm

#

I didn't think about that.

#

To explain...

burnt rune
#

The “binding” durability of a bindless tool is set to something in particular

#

But it doesn’t exist so

elfin wren
#

When crafting a tool you don't need to provide a binding. But because it needs something to define if the head is attached to the handle it must generate a "Empty" binding as a place holder.

burnt rune
#

Might not be able to be ‘reverted’

elfin wren
#

I don't know off the top of my head how the binding durability function deals with an empty binding slot.

#

But if a tool is crafted with a binding it should work.

burnt rune
#

Would glue work as a reversion target ? Or is it only like actual binding such as rope, twine, nails, metal parts

elfin wren
#

Anything that the Toolsmith mod uses as a binding in the tool assembly table to my knolage.

dawn kernel
#

Is it possible to make a tool without binding in survival? Like is this only a creative problem?

elfin wren
#

The empty tool bind appears to be the only acception.

burnt rune
#

No it’s possible in survival

elfin wren
#

To add binding you can hold binding in off hand and the partialy assembled tool in main hand and hold right click to compleate it

#

But you can hold rightclick without a binding on the unfinished tool rod and head to finish without binding

dawn kernel
#

Hmmm, okay.
I was going through and adding some extra like configurable Reversion multipliers for Handle and Binding, so be sure to pull from my latest commit if you go to try more testing.
I also put in a variable in the csproj for those references to make it easier to swapsy

elfin wren
#

Thankyou that saves so much time.

elfin wren
#

Here's our reason lol

dawn kernel
#

So we just run it null

#

it feels greasey

elfin wren
#

HasToolbindingCurrentDurability

#

Returns a bool for if there is durability instead of if there is a tool binding. I'll implement and test.

#

I'll change the one for the tool handle as well just in case of special instances where a tool might not have a tool handle but still have a handle durability.

#

My change works

#

I'll get it committed and let you know when I'm done.

dawn kernel
#

Awesome, good work hunting that down.
Thanks again for your hard work on this. I've been so tied up with work and some other health problems making it hard to use the computer lately and I haven't been able to give the mod as much attention as I'd like to

elfin wren
dawn kernel
elfin wren
#

I think they look fine.

#

Tool bindings generally have less total durability I think so the half restore speed should work fine.

dawn kernel
#

I honestly think handle could also go 1/2 as well. 1/3 just doesn't fit into a scale of 1-5 well

elfin wren
#

Could make it restore as a % of total instead with a floor value.

#

This would make it more of a repair rate instead of a repair value amount

#

And if it doesn't already exist you could make a template for people to customize the repair rate / max enchant lvl / per lever repair scale of individual items.

#

So mods that would become unbalanced due to the enchant can make their mod add the custom item enchant values to the configs and so server owners could fix it if the mod author doesn't implement it themselves.

dawn kernel
#

That sounds like another balance patch. We'll put a pin in that and push Toolsmith compat to start

elfin wren
#

Sounds good

dawn kernel
#

Release 1.5.5

elfin wren
#

WOOOOOOOOO

#

The real test to see if it works will with be with an actual server. I'll let someone I know that runs a server about the update because they use the mod and we should find out if there are any bugs if players report issues while enchanting.

burnt rune
#

Hello I have a big question bout all of this very impressive stuff, does this apply to Toolsmith CO weapons ?

dawn kernel
elfin wren
burnt rune
#

Report: It works!

#

Thanks a bunch people

digital falcon
#

heh, got Light on my Night Vision Mask