#Getting KeycardLevels from Pickup

1 messages · Page 1 of 1 (latest)

copper basalt
#

im trying to get the levels of a custom keycard for 914, but all i have is the Pickup and i dont know how to get from Pickup to KeycardItem

i did this mess:

Log.Warn(1);
Pickup result = Pickup.Create(ItemType.KeycardCustomManagement, pickup.Position + Scp914Controller.MoveVector, pickup.Rotation, pickup.Transform.localScale);
Log.Warn(2);
LabApi.Features.Wrappers.KeycardItem newresult = (LabApi.Features.Wrappers.KeycardItem) LabApi.Features.Wrappers.KeycardItem.Get(LabApi.Features.Wrappers.Item.Get(pickup.Serial).Base);
Log.Warn("Card levels: " + newresult.Levels.Containment.ToString() + newresult.Levels.Armory.ToString() + ", " + newresult.Levels.Admin.ToString());

the console gets flooded with 1s and 2s but never gets to the "Card levels: ..." part and 914 never opens
i dont know why it gets flooded but pretend it errors on the line where "newresult" is assigned

loud wyvern
#

That's because the pickup doesn't register as an item

#

Items and pickups are entirely separate

#

I'm not sure how other people do it but I had to do something pretty jank to check levels

#

There's two schools of thought

#

One is you can give the keycard pickup to Player.Host to check it in its item state, and then put it back, or

#

Do something like

public class WarheadPermissions : IDoorPermissionRequester
{
  public DoorPermissionsPolicy PermissionsPolicy => new (DoorPermissionFlags.AlphaWarhead);
  public string RequesterLogSignature => "WarheadPermissions";
}
#

Then check it like this

if (keycardPickup.Base.Info.ItemId.TryGetTemplate(out InventorySystem.Items.Keycards.KeycardItem keycardItem) && keycardItem is IDoorPermissionProvider provider)
{
  WarheadPermissions warheadPermissions = new();
  if (warheadPermissions.CheckPermissions(provider, out _)) return;
}
#

Though I'm not sure if that system works for custom keycards because it requires grabbing the ItemId and getting the KeycardItem template

loud wyvern
#

KeycardPickup::ProcessCollision

loud wyvern
copper basalt
#

i see

loud wyvern
#

In your case, you're checking if a pickup is able to open 914

copper basalt
#

i am not

loud wyvern
#

Oh nevermind then

#

I read "... and 914 never opens" and assumed

copper basalt
#

im trying to make custom keycards upgradable in 914

#

oh yeah i didnt explain on that

#

when the card gets processed in 914 the input and output doors never gets opened

loud wyvern
#

I suspect it's at Item.Get(pickup.Serial)
There is no item with that serial, only a pickup, so it returns null
You're then trying to access Item::Base on a null object, which throws an error while pickups are being processed, meaning the code never completes and 914 never opens

copper basalt
#

this is most likely true

loud wyvern
#

If your goal is to generally check the level of any custom keycard you put in, the best method is probably just giving it to the host

copper basalt
#

i dont have access to the host

#

if the host means the player who put the card in

copper basalt
#

oh i see now

loud wyvern
#
public KeycardPickup ProcessKeycard(KeycardPickup keycardPickup)
{
  (Vector3 pos, Quaternion rot) data = (keycardPickup.Position, keycardPickup.Rotation);
  Player host = Player.Host!;
  var keycardItem = (KeycardItem)host.AddItem(keycardPickup)!;
  keycardPickup.Destroy();
  Logger.Info(keycardItem.Levels.Admin);
  Logger.Info(keycardItem.Levels.Armory);
  Logger.Info(keycardItem.Levels.Containment);
  var newPickup = (KeycardPickup)host.DropItem(keycardItem);
  newPickup.Position = data.pos;
  newPickup.Rotation = data.rot;
  return newPickup;
}
#

Something a bit like that prob

#

Oh wait

#

I'm stupid

#

There's a better way I think

#

Huge

#

Lemme test something

copper basalt
#

oh damn

loud wyvern
copper basalt
#

ill continue making what i was making until you send the better version

loud wyvern
#
extension(KeycardPickup keycardPickup)
{
  public KeycardLevels Levels => new(((IDoorPermissionProvider)keycardPickup.Base.Info.ItemId.GetTemplate()).GetPermissions(null));
}

A billion times easier and better

#

This probably works

copper basalt
#

i have no clue where i would use this

#

i may have a clue hold on

loud wyvern
#

It's the same thing as KeycardItem::Levels

copper basalt
loud wyvern
#
public static class KeycardPickupExtension
{
  extension(KeycardPickup keycardPickup)
  {
    public KeycardLevels Levels => new(((IDoorPermissionProvider)keycardPickup.Base.Info.ItemId.GetTemplate()).GetPermissions(null));
  }
}
#

Do that

#

And then whenever you have a KeycardPickup keycardPickup you can just do keycardPickup.Levels just like the item

#

The only iffy part is that you have to get the template from the item ID, but that's how the base-game does it so it should work?

#

It just concerns me that that's how the base-game does it because it could mean that it doesn't actually have a way to check permissions on the keycard pickup if this method doesn't work

copper basalt
#

which namespace is KeycardPickup in

#

InventorySystem.Items.Keycards or LabApi.Features.Wrappers?

copper basalt
loud wyvern
loud wyvern
#

I mean if you want you could add it to InventorySystem.Items.Keycards

#

That would just be one part removed

#
public static class KeycardPickupExtension
{
  extension(KeycardPickup keycardPickup)
  {
    public KeycardLevels Levels => new(((IDoorPermissionProvider)keycardPickup.Info.ItemId.GetTemplate()).GetPermissions(null));
  }
}
copper basalt
#

is there a specific version for the language i should be using?

loud wyvern
copper basalt
#

oh yeah that was the issue

#

i may be dumb

#

i dont know how to get the keycardpickup from the original pickup

#

and another question

#

is there a way to get the permission color?

#

this is how i set the levels and colors
i only want to set the level but keep the color the same

if (!result.Type.TryGetTemplate<InventorySystem.Items.Keycards.KeycardItem>(out var newitem))
{
    throw new ArgumentException("Template for itemType not found");
}

DetailBase[] resultdetails = newitem.Details;
if (resultdetails.OfType<CustomPermsDetail>().FirstOrDefault() != null)
{
    CustomPermsDetail s = resultdetails.OfType<CustomPermsDetail>().FirstOrDefault();
    KeycardLevels l = GetUpgradedPermissions(setting, hostcard.Levels);
    s.SetArguments(new object[] { l, new Color32(0, 0, 0, 255) });
}
tranquil sun
#

iirc server dosent know the color unless you save it when you set it

copper basalt
#

oh

tranquil sun
#

something like

public readonly Dictionary<ushort, Color32> PermissionColors = [];
copper basalt
#

another little problem

#

the cards details get updated to the latest made custom card

dark heron
copper basalt
#

i think i tried that already but i can try it again

loud wyvern
#

There's the inventorysystem one and the labapi wrapper one

dark heron
#

if (myPickup is KeycardPickup kcp)

loud wyvern
dark heron
#

You can also get the raw data from the syncstore

loud wyvern
#

Also

#

ICustomizableDetail.CommandArguments

#

@copper basalt ^

copper basalt
#

i dont understand any of that

#

please explain

copper basalt
#
LabApi.Features.Wrappers.KeycardPickup oldKPickup = (LabApi.Features.Wrappers.KeycardPickup) pickup;

...

KeycardLevels l = GetUpgradedPermissions(setting, oldKPickup.Levels);

oldKPickup.Levels has no permissions even though it has all values as 1

loud wyvern
copper basalt
#

are they supposed to hold the detail data when the card was made? because this just returns the default data

if (resultdetails.OfType<CustomItemNameDetail>().FirstOrDefault() != null)
{
    CustomItemNameDetail s = resultdetails.OfType<CustomItemNameDetail>().FirstOrDefault();
    s.ParseArguments(hostcard.Base.Details.OfType<CustomItemNameDetail>().FirstOrDefault().CommandArguments);
}
#

this is done for detailbase

copper basalt
#

the code to set the data of the details

loud wyvern
#

No

loud wyvern
#

Like in the base-game code that shows that they use ICustomizableDetail

copper basalt
#

im pretty sure customitemnamedetail inherits that

#

i dont remember

loud wyvern
#

All squares are rectangles but not all rectangles are squares

#

It's the same way with inheritance

#

All CustomItemNameDetails are ICustomizableDetails but not all ICustomizableDetails are CustomItemNameDetails

copper basalt
#

i understand that

loud wyvern
loud wyvern
#

Which most certainly should work

#

Because that's what the base game does

copper basalt
#

i think i get it now

#

thanks

loud wyvern
#

Just hoping I can help guide you to the right answer cause you always learn more that way

copper basalt
#

great yes

#

i already learned a lot

river beacon
#

Also Exiled has a CustomKeycardItem / CustomKeycardPickup API if you wanna use that to track stats of custom keycards, if you don’t use that, you’re gonna need to patch every syncable details write methods (unless your keycards are static and can’t change after creation, then you can just patch whatever created the keycards, but Exileds API lets you change them dynamically)

river beacon
river beacon
floral zenith
river beacon
#

Mfw that’s if you copy their source code???

floral zenith
#

which you recommended

river beacon
#

No, I want them to use the API 😭
Copying the entire CustomKeycardItem / CustomKeycardPickup wrapper is crazy bruh 🙏

#

Anyways, you could literally just copy paste it and nobody would care, the license is really only there for stuff like Querre I imagine

floral zenith
river beacon
#

So is not using syncvars for custom keycards

#

¯_(ツ)_/¯

floral zenith
#

if all of it was dealt with inside Exiled.API then yeah that would be cool, but it cant be because it's a dependency

floral zenith
river beacon
#

Yeah there’s like 8 patches of custom keycards in Exiled.Events

river beacon
copper basalt
#

i already have exiled as a dependency

river beacon
#

Then I’d advise using the CustomKeycardPickup (don’t confuse it with CustomKeycard from custom items) wrapper for your events, if you have any issues, @ me, I was the one that wrote all the custom keycard stuff

loud wyvern
#

Or is that a NW issue

river beacon
#

Already exists in bug tracker

loud wyvern
river beacon
#

I even made Exiled fix it Trolley

#

The link exists in the fix patch, so I guess lemme pull it up cuz I’m on my phone

loud wyvern
dark heron
#

Well not really labapi bug but basegame

river beacon
#

Was “bug tracker” the wrong use of words?

dark heron
#

No

dark heron
#

Or as i did previous i just seen one link instead of two

river beacon
#

I don’t think it’s been reported via LabAPI GitHub

river beacon
#

Bug is technically base game, as the template of a custom keycard returning no perms makes sense

dark heron
#

Since it does not check for if it's a customizable one ye

loud wyvern
# river beacon This

Oh I'm just blind
I read the beginning of the "exiled" link and thought that the embed was for that 💀

#

Sometimes I can be very dense

river beacon
#

No worries

loud wyvern
#

Are we deadass right now

river beacon
#

NW moment Trolley

loud wyvern
#

I don't think they realize that the problem is that you can't get keycard levels from a custom keycards pickup at all because of this issue

river beacon
#

They’d likely have to do something like what I did too (check if keycard is custom, then use custom DoorPermissionsProvider)

river beacon
#

CustomPermsDetail has a dictionary of all perms?

loud wyvern
#

Lemme check out the exiled patch

river beacon
#

Problem is that keycard pickups collide with scanners by getting the item template and using its permissions provider Kek

#

So I had to make my own created from an actual permissions value

loud wyvern
river beacon
#

Weird

#

Well I saw that dictionary after all the hell with synced details I’ve spent

dark heron
#

🤔

loud wyvern
#

Interesting

#

I'll take a look at it later

#

I wanna write a solution and post it here for people who don't wanna install EXILED

dark heron
#

I mean you can set the permission for it while in the floor and stuff but I didn't even through about getting it back

loud wyvern
#

For now I'm laying in bed

river beacon
#

It’s just transpiler + custom class, feel free to copy paste it as a plugin

loud wyvern
#

I <3 CodeMatcher

#

My beloved

river beacon
#

It’ll be an interesting task then as you gotta mess with labels a bit

loud wyvern
#

Well

#

Depending

#

On how much you mess with it

#

I've messed with labels but not like messed with labels

dark heron
#

Can't wait for the "messed up the labels"

loud wyvern
dark heron
#

What and whereFear

loud wyvern
#

I've had a transpiler patch for actually months

#

Just check if timeoverride is set to less than zero and don't set remaining time if so

dark heron
#

Should be easy

#

timeOverride < 0 ? timeOverride : 0

#

Or is it > i always get confused by it

loud wyvern
#

If you do that then the issue will not be resolved because the default timeOverride is -1

#

Just if(timeOverride >= 0) grenadeProjectile.RemainingTime = timeOverride;

#

Don't set RemainingTime if timeOverride < 0

#

At all

#

Don't touch it

copper basalt
#

oh my days i forgot to say that i made it work

loud wyvern
#

Ez pz

#
extension(KeycardPickup keycardPickup)
{
    public KeycardLevels Levels =>
        CustomPermsDetail.CustomPermissions.TryGetValue(keycardPickup.Serial, out DoorPermissionFlags doorPermissionFlags)
            ? new KeycardLevels(doorPermissionFlags)
            : new KeycardLevels(((IDoorPermissionProvider)keycardPickup.Base.Info.ItemId.GetTemplate()).GetPermissions(null));
}
river beacon
#

you can use that to check perms, but doors want IPermissionsProvider

#

so you need your own class for that

loud wyvern
loud wyvern
loud wyvern
#

The original question needed to get Levels from a KeycardPickup in order to process in 914

#

Keycard collisions were a separate topic brought up in this forum

loud wyvern
#

I just confirmed