#plugins-dev-chat
1 messages Β· Page 28 of 1
Any chance at us getting profilers for servers?
what situation is servers TPS dropping for you
Large player count
Would need to be able to profile a server to find out where the problem lies
even on lower counts, the fact we can't profile servers and plugins makes it harder
Wouldn't it be fun to put a kill log here?
its very likely the FPC distributer, atm it recalculates the relative position for every player cobo each tick, so if theres 30 players its creating 900 relative positions. creating new relative positions are not cheap as to make one it needs to check the distance to every waypoint on the map. i have not tried this but you could try caching the relative position per player and use a patch to use the cached relative position in the distributer. so at most you only recalculate the relative position per player so 30 times a tick for 30 players
That is good to know ty, I'll try and patch that
oop
yeah found the code that does it
ouch
While it is a performance boost, it's pretty minor so far
3 TPS boost with 100 (dummy) players
will have to test with actual players
but on a 32/48 player server i feel like it won't be very noticeable
i see'
actually
7 TPS on a more intensive server
and players moving around don't share the same cached relative position (spawning 100 dummies has some of them within each other)
so not a bad optimization at all
sure
(when I get out of bed)
just poke me whenever you're ready and i'll implement it
@unique crane 
hah
I need help.
So I remove the item when the InventoryExtensions.OnItemRemoved called.
But PlayerUsedItemEventArgs run AFTER the item being destroyed so
fair hah
well the relative positioning caching does work so it could be a nice thing to have in SL natively
Huh?
this one
π π
does IWeaponModifierPlayerEffect not work for custom modded effects
ah yes NICE the item being removed the exact same time as the OnUsedEvent run
π
Yeah it has to be both on client and server
no custom effect for anyone
maybe
in 2095
Cant promise anything
fair
bummer though had a pretty fun idea with it
guess i'll just pump the player full of 1853 in the meantime
But rather than custom effects it will be on the firearms themself
that works as well
That would be easier to do
wanted to give the player pinpoint hipfire accuracy
You can do that by modifying the weapon's stats
Won't reflect the values on the client but that's not a big deal
yeah i wanted it to be reflected
Laser
wasn't the only thing, although I'll have to check but you can't change the double action speed on the revolver atm right
stuff like that
figured
where are those?
Where I should place subconfigs for main config in project?
Maybe some Configs path?
if you have multiple configs that arenβt just basic config and translation, then configs folder yea
if i change the ammoType in server side what would happen
Hi! For the raycast what layer/mask is the text on or is it possible to detect it with raycast?
try it and see
You can do a raycast that ignores layers with the second param
QueryTriggerInteraction.Collide
But probably easier to get the GO's layers and add to the list of layers
Okay thanks
If you mean config entries in the main configuration, just create instances of classes in it
Probably better to separate them though, use this.LoadConfig<ConfigType>("filename.yml") in the enable method
Wait, arent LoadConfig requires the type to be TConfig, which is the config class defined at class level? Or am thinking something else/ this was changed
Oh im orange now instead of green 
it is just must be a class that can be created with just new();
so uh how can I throw an item?
ClientDropItem
or UserCode_CmdDropItem__UInt16__Boolean? or what
TConfig can be any class
It's on the extension method not in the plugin
Yeah the Plugin<TConfig> type exists but the extension takes a Plugin iirc
Player.Host!.CurrentItem!.DropItem()
ignore the errors im ignoring
thats just cuz
server host
and null item
NullReferenceException: β¦
there is no BUTT
idk
look at how item throwing works and just borrow the code 
just drop the item and give its rigidbody a nudge
thank u exiled
oh yuck
yea
wizard of what
idk but writing a transpiler that works is awesome
got a 5-7 TPS boost on high player count servers
^
added caching to this
what if u try the transpiler for Vector3 math
also yea Vector3 is apparently #1 issue in sl
really
or one of the bigger ones
what's the transpiler look like
I guess
π
u can just do prefix , dont forget the bool to do not run the normal func
yes
I tried that today
aren't transpilers a tad bit more performant though
and
the patch makes it slower
xdd
π
Like the reflection itself or whatever does harmony do
how was your patch
is slow
oh
so basically
But the logic for the optimalization is correct
replace harmony with a custrom version
that's why im saying transpiler would be better
errrr
try it
Hmmm
since you just overwrite the IL that way no
mayhaps
try and seee
pff thanks automod
i forgot
public static bool Prefix(Vector3 a, Vector3 b, ref Vector3 __result)
{
Vector3 res;
res.x = a.x - b.x;
res.y = a.y - b.y;
res.z = a.z - b.z;
__result = res;
return false;
}
Here is the optimized version
oh yeah it has to be ref
If you can do it via IL
wdym
Oh
whats ur purpose here
no one currently
I get more from hoobert
a lot
System numerics?
π
I dont have unity stuff in the website
but should be similar
ITS A WEBSITE
i don't get how this is slow though
The new()
hmmm
No its just the constructor call
This will create a struct in memory but wont call the constructor
Yea
π
its just the method call
thats crazy
Still results in struct copying
I did it like this
its just a method is it not
[HarmonyPatch]
public static class Vector3SubtractionPatch
{
public static MethodBase TargetMethod()
{
return typeof(Vector3).GetMethod(
"op_Subtraction",
BindingFlags.Public | BindingFlags.Static,
null,
new[] { typeof(Vector3), typeof(Vector3) },
null
);
}
[HarmonyPrefix]
public static bool Prefix(Vector3 a, Vector3 b, ref Vector3 __result)
{
Vector3 res;
res.x = a.x - b.x;
res.y = a.y - b.y;
res.z = a.z - b.z;
__result = res;
return false;
}
}
Yea
Its a method
sweet
could just "op_Subtraction"
He dumb
the cheat code is just writing it and copying the IL from Rider
True
Find every usage of the subtraction operator and patch 

but its not the subtraction :3
you doing the exact same thing bruh
as in untiy
since you allocate a new struct too
Then what
If you subtract two vectors
It calls the overloaded subtraction operator
Which then invokes the constructor
I had some nasty problems doing harmony patches like that for some reason
I had to use the ILSpy version which was working.
Do you encountered this or I just had skill issues?
we'll see in a second
### Patch: static UnityEngine.Vector3 UnityEngine.Vector3::op_Subtraction(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
### Replacement: static UnityEngine.Vector3 UnityEngine.Vector3::UnityEngine.Vector3.op_Subtraction_Patch0(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
### Patch: static UnityEngine.Vector3 UnityEngine.Vector3::op_Subtraction(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
### Replacement: static UnityEngine.Vector3 UnityEngine.Vector3::UnityEngine.Vector3.op_Subtraction_Patch0(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
IL_0000: Local var 0: UnityEngine.Vector3
IL_0000: Local var 1: UnityEngine.Vector3
IL_0000: // start original
IL_0000: ldloca.s 1 (UnityEngine.Vector3)
IL_0002: ldloc.0
IL_0003: ldfld System.Single UnityEngine.Vector3::x
IL_0008: ldloc.1
IL_0009: ldfld System.Single UnityEngine.Vector3::x
IL_000E: sub
IL_000F: stfld System.Single UnityEngine.Vector3::x
IL_0014: ldloca.s 1 (UnityEngine.Vector3)
IL_0016: ldloc.0
IL_0017: ldfld System.Single UnityEngine.Vector3::y
IL_001C: ldloc.1
IL_001D: ldfld System.Single UnityEngine.Vector3::y
IL_0022: sub
IL_0023: stfld System.Single UnityEngine.Vector3::y
IL_0028: ldloca.s 1 (UnityEngine.Vector3)
IL_002A: ldloc.0
IL_002B: ldfld System.Single UnityEngine.Vector3::z
IL_0030: ldloc.1
IL_0031: ldfld System.Single UnityEngine.Vector3::z
IL_0036: sub
IL_0037: stfld System.Single UnityEngine.Vector3::z
IL_003C: ldloc.0
IL_003D: stloc.1
IL_003E: ldloc.1
IL_003F: // end original
IL_003F: ret
DONE
huh wha
i think my transpiler's broken
ye
just a little bit
falling through the world was funny at least
doesn't work
huh what not work
black screen
guessing stuck in 0 0 0
sec
### Patch: static UnityEngine.Vector3 UnityEngine.Vector3::op_Subtraction(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
### Replacement: static UnityEngine.Vector3 UnityEngine.Vector3::UnityEngine.Vector3.op_Subtraction_Patch0(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
IL_0000: Local var 0: UnityEngine.Vector3
IL_0000: Local var 1: UnityEngine.Vector3
IL_0000: // start original
IL_0000: ldloca.s 1 (UnityEngine.Vector3)
IL_0002: ldloc.0
IL_0003: ldfld System.Single UnityEngine.Vector3::x
IL_0008: ldloc.1
IL_0009: ldfld System.Single UnityEngine.Vector3::x
IL_000E: sub
IL_000F: stfld System.Single UnityEngine.Vector3::x
IL_0014: ldloca.s 1 (UnityEngine.Vector3)
IL_0016: ldloc.0
IL_0017: ldfld System.Single UnityEngine.Vector3::y
IL_001C: ldloc.1
IL_001D: ldfld System.Single UnityEngine.Vector3::y
IL_0022: sub
IL_0023: stfld System.Single UnityEngine.Vector3::y
IL_0028: ldloca.s 1 (UnityEngine.Vector3)
IL_002A: ldloc.0
IL_002B: ldfld System.Single UnityEngine.Vector3::z
IL_0030: ldloc.1
IL_0031: ldfld System.Single UnityEngine.Vector3::z
IL_0036: sub
IL_0037: stfld System.Single UnityEngine.Vector3::z
IL_003C: ldloca.s 1 (UnityEngine.Vector3)
IL_003E: // end original
IL_003E: ret
DONE
fixed
gonna do the same for add
and then we'll check the performance diff ig
what the fuck is ldloca_s 1 when I didnt even write that code
nah that was mine
perfectly written transpiler
u prob have to patch many of the op_
UnaryNegation is doing new, multipy too
division too
== and != doesnt need patch
i love broken transpilers
So the rider IL is broken 
a little too verbose for no reason yeah
### Patch: static UnityEngine.Vector3 UnityEngine.Vector3::op_Subtraction(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
### Replacement: static UnityEngine.Vector3 UnityEngine.Vector3::UnityEngine.Vector3.op_Subtraction_Patch0(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
IL_0000: Local var 0: UnityEngine.Vector3
IL_0000: Local var 1: UnityEngine.Vector3
IL_0000: // start original
IL_0000: ldloca.s 1 (UnityEngine.Vector3)
IL_0002: ldloc.0
IL_0003: ldfld System.Single UnityEngine.Vector3::x
IL_0008: ldloc.1
IL_0009: ldfld System.Single UnityEngine.Vector3::x
IL_000E: sub
IL_000F: stfld System.Single UnityEngine.Vector3::x
IL_0014: ldloca.s 1 (UnityEngine.Vector3)
IL_0016: ldloc.0
IL_0017: ldfld System.Single UnityEngine.Vector3::y
IL_001C: ldloc.1
IL_001D: ldfld System.Single UnityEngine.Vector3::y
IL_0022: sub
IL_0023: stfld System.Single UnityEngine.Vector3::y
IL_0028: ldloca.s 1 (UnityEngine.Vector3)
IL_002A: ldloc.0
IL_002B: ldfld System.Single UnityEngine.Vector3::z
IL_0030: ldloc.1
IL_0031: ldfld System.Single UnityEngine.Vector3::z
IL_0036: sub
IL_0037: stfld System.Single UnityEngine.Vector3::z
IL_003C: ldloca.s 1 (UnityEngine.Vector3)
IL_003E: // end original
IL_003E: ret
DONE
this is the working one
Iy gives so strange code idk why
wtf
it just randomly stopped working
Reason: Invalid IL code in (wrapper dynamic-method) UnityEngine.Vector3:UnityEngine.Vector3.op_Subtraction_Patch0 (UnityEngine.Vector3,UnityEngine.Vector3): IL_003e: ret
that or I just... didn't notice it being wrong?
oh
it was lmao
### Patch: static UnityEngine.Vector3 UnityEngine.Vector3::op_Subtraction(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
### Replacement: static UnityEngine.Vector3 UnityEngine.Vector3::UnityEngine.Vector3.op_Subtraction_Patch0(UnityEngine.Vector3 a, UnityEngine.Vector3 b)
IL_0000: Local var 0: UnityEngine.Vector3
IL_0000: Local var 1: UnityEngine.Vector3
IL_0000: // start original
IL_0000: ldloca.s 1 (UnityEngine.Vector3)
IL_0002: ldloc.0
IL_0003: ldfld System.Single UnityEngine.Vector3::x
IL_0008: ldloc.1
IL_0009: ldfld System.Single UnityEngine.Vector3::x
IL_000E: sub
IL_000F: stfld System.Single UnityEngine.Vector3::x
IL_0014: ldloca.s 1 (UnityEngine.Vector3)
IL_0016: ldloc.0
IL_0017: ldfld System.Single UnityEngine.Vector3::y
IL_001C: ldloc.1
IL_001D: ldfld System.Single UnityEngine.Vector3::y
IL_0022: sub
IL_0023: stfld System.Single UnityEngine.Vector3::y
IL_0028: ldloca.s 1 (UnityEngine.Vector3)
IL_002A: ldloc.0
IL_002B: ldfld System.Single UnityEngine.Vector3::z
IL_0030: ldloc.1
IL_0031: ldfld System.Single UnityEngine.Vector3::z
IL_0036: sub
IL_0037: stfld System.Single UnityEngine.Vector3::z
IL_003C: ldloc.0
IL_003D: // end original
IL_003D: ret
DONE
the real working one
hopefuly
nvm i fall through the map
this is what u do in IL
I wonder if it requires some sort of configuration or parameters to not be fucked
just dont use rider 
Cause using two tools jist for patcges are inconvinient
I rather have no IL than fucked up IL
Visual Studio arent better either 
atleast i dont use to create false IL
I mean you can you dnspy or ilspy, just really inconvinient not to use the built in
Invalid IL code in (wrapper dynamic-method) UnityEngine.Vector3:UnityEngine.Vector3.op_Subtraction_Patch0 (UnityEngine.Vector3,UnityEngine.Vector3): IL_000f: stfld 0x00000005
also easier to seach stuff in there
skill issue
i've got work and it's not worth the hassle
other performance tweaks got us good results so we don't need it atm
[log] ArgumentException: An item with the same key has already been added. Key: ReferenceHub (Name='Player [connId=33]', NetID='19766', PlayerID='46')
[log] at System.Collections.Generic.Dictionary`2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) [0x0015a] in <069d7b80a3914a08b6825aa362b07f5e>:0
[log] at System.Collections.Generic.Dictionary`2[TKey,TValue].Add (TKey key, TValue value) [0x00000] in <069d7b80a3914a08b6825aa362b07f5e>:0
[log] at LabApi.Features.Wrappers.Player..ctor (ReferenceHub referenceHub) [0x0000b] in <bea7f403b90e4786abd99fa819db9853>:0
[log] at LabApi.Features.Wrappers.Player.AddPlayer (ReferenceHub referenceHub) [0x00008] in <bea7f403b90e4786abd99fa819db9853>:0
[log] at (wrapper delegate-invoke) System.Action`1[ReferenceHub].invoke_void_T(ReferenceHub)
[log] at ReferenceHub.Start () [0x00009] in <8db1ca0fe9a6484084cda320b139932c>:0
is this getting fixed or is it a me issue?
didnt seen this issue
happens all the time for me
Can report that this happens to us as well
For us when players are connecting and got auth accepted
i dont see it
It is in LocalAdminLogs, usually it happens 3-4 times per round
I wonder if something setup in plugin causes that
Do you use CustomDataStore?
nop
Oh. @grand flower do you use CustomDataStore? If yes, do you access it in OnPlayerJoined?
Possibly yes
I can check
Although data stores are pissing me off since they seem to carry over rounds and even disconnects sometimes (?)
I wonder if fetching the datastore causes it. Cause the GetPlayer creates it if it doesnt exists
Had so many bugs due to that
GetPlayer creating if it doesnt exist is a bad decision
IIRC someone at NW said they knew about it though so hopefully it gets fixed soon
We just use that for persistent data. For per round we reimplemented the PluginAPI update loop custom object handling cause we needed the loop 
I just made a TransientDataStore subclass that gets nuked on round restart or when the player leaves
Made it easier
Also have an IRoleLifetime interface that marks a data store as only being valid for the duration of one role
Little helpers like that are useful
Same man, same.
the answer is 7
you're welcome
I was going over my keyboard with a wet wipe, sorry
oh then the answer is 32
I decided to write all my math homework here
fast and accurate
Someone knows a way to make primitives glow?
because i tried
new Vector4(primitive.NetworkColor.r, primitive.NetworkColor.g,
primitive.NetworkColor.b, Glowing);
But it doesn't work
create a lightsource on them
that sucks
Is there even a glow shader in SL?
with MER you can make them glow
but i don't quite understand, when i asked there alot of time ago they told me this
Look at MER source then
ig if you set each color (r, g, b) to some big number > 1 it will glow
the light is shitting itself
oh my god
the game is dying lol
lights around the facility are dying
Bro is going into 4th dimension
fr
Thats lore accurate
its an anomaly
New scp
ok i found out something strange
lol
the cubes create lights
but becomes like in a bug state
Lmao
where it reflects its own shadow
Self reflecting cubes
IT looks cool
but its not WHAT i wanted lol
OH WAIT
NEGATIVE
its a transparent cube
but with reflecting abilities
Yeah its RGBA...
You wanna check out in vc?
im fixing it rn
to be more stable
Sadly im not at home so I cany
sad
I would have liked to
tell me a number
how did u do it
Eww going outside
.
like this
got told alot of time ago it worked
didn't belive it
until i tested it myself
and it works
im really surprised
it didn't work
because i've made a mistake the first time lol
now it should always work
i meant the values
oh the value was -200
and second one -20
this is how you see it on the editor
i think i've made a mistake?
show me your Attribute on the color
OH WAIT
[ColorRGBA] or smth
IT WASN'T THE CUBE
it will not work with it
am i stupid?
yes
i've found it
if its negative
it works
it becomes the death cube of blackness with blue aura
WAIT
THIS IS SO COOL
I created lens
huh
aintnoway
Make one flat plane with that material and parent it in front of a player
how to get high 101
I wanna do tho the primitive glowing
not negative glowing
lol
*-1f it
I did
and only make it visible for that one player
Theeen I dont know
fake sync my beloved
david!!!
eve!!
whats ur actual job
nameless you are mean ;(
outside SL
None
still studying
so ur poor?
No
can zero pay me
who r u again
your worst nightmare
u stink
u poopy
No
i didn't know you could smell your nightmares
I don't pay none
"you may not rest now, there are monsters nearby"
white monster and pink one are the best
me who drink monster and having less energy
THSI SI SO COOL
Ive got a gif for that
want it?
This idea is crazy
btw i got an idea
IF i multiply all of the numbers
what happens
Im probably going to put this like under a section called Unsafe
because its probably unsafe lol
people can become blind
got it in dms
i saw it
lol
Im going to test rn
if the game crashes is going to be funny
i don't think im supposed to do this
i always wondered who was the first one to commit to SL source code primitives
was Hubert?
I can look in a few mins
scrolling tru 4000 commits
fr
WHAT HAPPENED
THE CUBE NOW REFLECT LIGHT
but is blank
like idk how to explain it
WHAT
THIS IS CRAZY
blank cube but you can shine it and it becomes a color
THIS COULD BE COOL FOR ALOT OF STUFF
yep i found the way to do them
OH MY GOD THIS IS LAGGY
lol
i've created the cubes that eats light
congrat
so you just made a venta black box or what? π
idk wtf is this
but if you do
-340282300000000000000000000000000000000 it creates light
340282300000000000000000000000000000000 it eats light
thats what it does if you multiply all of the numbers and A channel
tf are you doing
venta black is the darkest black
now im testing with only A channel
so yea
that what this thing does
lol
even light around
i don't fucking know what i created
it creats light
but reflect its own light
and its invisible
and depending where you see it, it changes color
i think im destroying unity HDPR pipeline
Wait
its normal that the cube reflects like metal?
because i've never seen this effect
like in this way
Very lightly
New material for map developer on aftermath
Lets see how fast before they make something crazy
With this new technique
I donβt think its even possible to do crazy strats
is there a way to debug the plugin with visual studio debugger?
patch
π
@grand flower Delegates are not executed randomly (event) as far as I know
U sure you cant just load one plugin before another to keep the order you want?
Or perhaps.. combine them?
not always possible
and afaik C# delegates aren't guaranteed to run in the order they're bound
example is adding/removing a handler on effect enable/disable
there's plenty of times where i'd do that but i'd still want them to run before idk CustomEventHandlers
I could make my own priority system but it'd be nice to have it natively within LabAPI
I did somewhat have one made but like, it made everything super dirty
handlers could prevent other handlers from firing which was cool but it was a mess
ended up scrapping it all and just using the static events
i keep getting stuck
Severity Code Description Project File Line Suppression State Details
Error (active) CS1503 Argument 1: cannot convert from 'LabApi.Features.Wrappers.Generator' to 'LabApi.Scp079Generator' NoKeycardHold C:\Users\Admin\source\repos\NoKeycardHold\EventsHandler.cs 34
send code
public static bool HasKeycardPermissionD(Door door, Player player) =>
HasPlayerPermission(player, door.Base);
public static bool HasKeycardPermissionL(LabApi.Features.Wrappers.LockerChamber chamber, Player player) =>
HasPlayerPermission(player, chamber.Base);
public static bool HasKeycardPermissionG(Scp079Generator generator, Player player) =>
HasPlayerPermission(player, generator)
public override void OnPlayerInteractingGenerator(PlayerInteractingGeneratorEventArgs ev)
{
var Generator = ev.Generator;
var player = ev.Player;
var requiredPermission = PluginFunctions.HasKeycardPermissionG(Generator, player);
}
both are in different btw
Generator.Base
Btw
Whats ur HasPlayerPermission code
i stole it cause im too tired to make my own π
public static bool HasPlayerPermission(Player player, IDoorPermissionRequester requester)
{
DoorPermissionFlags flags = DoorPermissionFlags.None;
if (player.IsBypassEnabled)
return true;
if (player.RoleBase is IDoorPermissionProvider doorPermissionProvider)
flags |= doorPermissionProvider.GetPermissions(requester);
foreach (Item item in player.Items)
if (item is KeycardItem keycardItem)
flags |= keycardItem.Base.GetPermissions(requester);
return requester.PermissionsPolicy.CheckPermissions(flags);
}
yea but where
Oh
Did you use my code
Looks like it
I updated it btw
wait
Uses enum now to decide what to check
What purpose do u need it for btw
also how should i even trigger the door to open and close π
im new to C# and LabAPI
π
door.Open() i believe
working on a server
I dont rememeber
ok
to see if they have right permission
so they dont have to hold thier card
/ remotecard
nope ):
just making sure ur not checking for all items if ur only meaning to check the held one
lol
Remote card makes sense
yeah
okay
isopen dosent exist
tf
Oh irs
IsOpened
do not use basegame stuff
Ye
If there is wrapper
ok
door.IsOpened = !door.IsOpened; π€
Tip number zero:
Learn c#
Tip numero uno:
IDE help you VS22, Rider use it to your advantage
on generator its isopen
im using vs
im stupid when you try to open a door when holding a keycard or a door without keycard it will intercept π
so it will stay closed

how to detect if your holding a keycard?
Player::CurrentItem is KeycardItem
^
i suck
if (player.CurrentItem.Category == LabApi.Features.Wrappers.KeycardItem);
π
Severity Code Description Project File Line Suppression State Details
Error (active) CS0119 'KeycardItem' is a type, which is not valid in the given context NoKeycardHold C:\Users\Admin\source\repos\NoKeycardHold\EventsHandler.cs 39
There is no category
You see here a category?
No
If you want to check category you equal to Category.Keycards
Or something
still same error ):
yay if (player.CurrentItem.Category == ItemCategory.Keycard);
):
[2025-05-25 01:35:14.784 +02:00] [ERROR] [LabApi] 'NullReferenceException' occured while invoking 'OnPlayerInteractingDoor' on 'NoKeycardHold.EventsHandler': 'Object reference not set to an instance of an object', stack trace:
at NoKeycardHold.EventsHandler.OnPlayerInteractingDoor (LabApi.Events.Arguments.PlayerEvents.PlayerInteractingDoorEventArgs ev) [0x00029] in <fd2d828c4ed349f6b1500b5827f600a1>:0
at LabApi.Events.EventManager.InvokeEvent[TEventArgs] (LabApi.Events.LabEventHandler`1[TEventArgs] eventHandler, TEventArgs args) [0x0001d] in <bea7f403b90e4786abd99fa819db9853>:0
if (player.CurrentItem is {IsDestroyed: false, Category: ItemCategory.Keycard})
if (player.CurrentItem != null && yourstuffhere
Not sure it has IsDestroyed, if not remove that part
if (hasPermission)
{
if (player.CurrentItem.Category != ItemCategory.Keycard)
{
if (!player.IsBypassEnabled)
{
door.IsOpened = !door.IsOpened;
}
}
}
}
right now
i have this for the door
Severity Code Description Project File Line Suppression State Details
Error (active) CS0019 Operator '&&' cannot be applied to operands of type 'bool' and 'ItemCategory' NoKeycardHold C:\Users\Admin\source\repos\NoKeycardHold\EventsHandler.cs 42
oh
wait
cant use && on bool
if (player.CurrentItem.Category != ItemCategory.None && ItemCategory.Keycard)
if (hasPermission)
{
if (player is { CurrentItem: { IsDestroyed: false, Category: not ItemCategory.Keycard }, IsBypassEnabled: false })
{
door.CanOpen = true;
}
}
oh
if i hold a card nothing happends when i interact
and if i dont hold a card it wont open
I feel like theres a better way of this
how so
bruhhh
wdym how so
ev.CanOpen = !ev.CanOpen?
Assuming ur using this event...
namespace NoKeycardHold;
using Interactables.Interobjects.DoorUtils;
using LabApi.Events.Arguments.PlayerEvents;
using LabApi.Events.CustomHandlers;
using LabApi.Features.Console;
using LabApi.Features.Wrappers;
using LiteNetLib;
using System.Net;
public class EventsHandler : CustomEventsHandler
{
public override void OnPlayerInteractingDoor(PlayerInteractingDoorEventArgs ev)
{
var door = ev.Door;
var player = ev.Player;
var requiredPermissions = door.Base.RequiredPermissions;
bool hasPermission = PluginFunctions.HasKeycardPermissionD(door, player);
if (hasPermission)
{
if (player is { CurrentItem: { IsDestroyed: false, Category: ItemCategory.Keycard }, IsBypassEnabled: false })
{
ev.CanOpen = !ev.CanOpen;
}
}
}
public override void OnPlayerInteractingGenerator(PlayerInteractingGeneratorEventArgs ev)
{
var Generator = ev.Generator;
var player = ev.Player;
bool hasPermission = PluginFunctions.HasKeycardPermissionG(Generator.Base, player);
if (hasPermission)
{
if (player is { CurrentItem: { IsDestroyed: false, Category: ItemCategory.Keycard }, IsBypassEnabled: false })
{
Generator.Base.IsOpen = !Generator.Base.IsOpen;
}
}
}
}
what
no
if (haspermission)
set to true
I mean it's pretty simple and clean
so this on door ev.CanOpen = true; and generator?
generator try
IsAllowed = true
what about if your holdin the correct card to open?
ur setting it allowed to open regardless
what are you trying to do
remote card
code is wrong
i updated it
ok
#1375972975182086255 message anyone know?
Errr
CanOpen should be used
Instead of opening door manually
that shouldnt even be necessary if you set CanOpen 
ev.CanOpen = true yes
but it wont work
It should
public override void OnPlayerInteractingDoor(PlayerInteractingDoorEventArgs ev)
{
var door = ev.Door;
var player = ev.Player;
var requiredPermissions = door.Base.RequiredPermissions;
bool hasPermission = PluginFunctions.HasKeycardPermissionD(door, player);
if (hasPermission)
{
if (player is { CurrentItem: { IsDestroyed: false, Category: not ItemCategory.Keycard }, IsBypassEnabled: false })
{
ev.CanOpen = true;
}
}
}
public static bool HasKeycardPermissionD(Door door, Player player) =>
HasPlayerPermission(player, door.Base);
public static bool HasKeycardPermissionL(LabApi.Features.Wrappers.LockerChamber chamber, Player player) =>
HasPlayerPermission(player, chamber.Base);
public static bool HasKeycardPermissionG(Scp079Generator generator, Player player) =>
HasPlayerPermission(player, generator);
public static bool HasPlayerPermission(Player player, IDoorPermissionRequester requester)
{
DoorPermissionFlags flags = DoorPermissionFlags.None;
if (player.IsBypassEnabled)
return true;
if (player.RoleBase is IDoorPermissionProvider doorPermissionProvider)
flags |= doorPermissionProvider.GetPermissions(requester);
foreach (Item item in player.Items)
if (item is KeycardItem keycardItem)
flags |= keycardItem.Base.GetPermissions(requester);
return requester.PermissionsPolicy.CheckPermissions(flags);
}
just do
(if hasPermission)
{
ev.CanOpen = true;
}
same on gen? but isallowed
Probably?
Idk how gen works and im only doing door based on the naming of it
restarting the server rn
ok
YESSSSSSSSSSSSSSSS
finnaly
it works
generator dosent work sadly
also is those like lockers with that needs keycards is it lockers or something else in coding?
Pedestal or smth
should i do like generator.isunlocked = true?
Idk
I think Server.PlayerCount exists, if not then Player.List.Count
Give them MovementBoost or Slowness effect
ok
only door works but generator or chamber wont work..
public override void OnPlayerUnlockingGenerator(PlayerUnlockingGeneratorEventArgs ev)
{
var Generator = ev.Generator;
var player = ev.Player;
bool hasPermission = PluginFunctions.HasKeycardPermissionG(Generator.Base, player);
if (hasPermission)
{
ev.Generator.Base.IsUnlocked = true;
}
}
public override void OnPlayerInteractedLocker(PlayerInteractedLockerEventArgs ev)
{
var Locker = ev.Chamber;
var player = ev.Player;
bool hasPermission = PluginFunctions.HasKeycardPermissionL(Locker, player);
if (hasPermission)
{
ev.Chamber.IsOpen = !ev.Chamber.IsOpen;
}
}
oh
chamber i understand now π
but not generator
chamber wont work either
I NEED A HERO
also
maybe make a security policy https://github.com/northwood-studios/LabAPI/security
It's secure
(probably)
well u need people to be able to report if its not
how do I change what players/teams a player can damage?
PlayerHurting event
IsAllowed
How should I go about properly handling an internal personal library for shared functions?
im worried about if i implement it incorrectly or something
if I make one, wil people be deterred from using my plugin because theres more files?
what if I make multiple modules of the library?
if its internal and personal wouldnt u not want people using it?
its a dll, i need some way to distribute it
and the source is public, i dont care.
its just not designed for others to develop with.
oh
then just put everything in one dll
u dont want people to have to install 18 things just to get betterelevatordoors working
yeah thats what i wanted to do, but it would end up dragging several double-dependencies with it. like I have an audio module for my library, but i dont want to add it to the main dll because some of my plugins dont use audio
just make sure the audio parts don't activate if there's not a plugin using it
like the patches
i guarantee u the average server owner does not care about how big a plugin is
can't you just put it as dependencies instead of a plugin
If i wanted to access an object of a type that is in an assembly that i dont want to hard reference, would it be acceptable to create a wrapper that is essentially identical but just uses reflection to access their properties?
For the most part i just use reflection to avoid requiring dependencies on assemblies.
bad
just reference them
if someone wants your plugin they'll drag the handful of dependencies into the dependencies folder
they won't care
its a soft dependency on another plugin i dont want to force the user to install, for instance UCR
UCR is known to break things sometimes and I dont want that to be a requirement.
what u can do is reference it but be very careful to avoid actually using anything that would reference that assembl
y
don't references crash the dll before it can even load if its not present
or does that only come up when its actually referenced
maybe with labapi it does but i believe it only occurs when u use something that references it
since c# is jit
so if theres a method that uses something from that assembly and you run it, even if the code referencing the assembly isnt ran itll still crash if u dont have the assembly
Okay
actually idk if it would crash u might be able to try catch it
so if I basically just avoid using any type or method from the assembly in certain parts of my code, there won't be an issue until I run a part of my code that does
i think i did something like that for ruei
yea
its kinda finicky obv
does that also include a method simply containing a type from another assembly
this is interesting, i cant believe i never realized this lol
yeah
probably
basically if the runtime ever tries to find a type and goes "hey wait a second this isnt here"
error
does the runtime search a method fully or just when it executes
because I think I can just hide code behind an if-else to prevent errors from throwing
when the method executes for the first time
it has to be in a different method
Thats what i was thinking
but it should work yes?
if (x) {
ForeignType.Method();
}
vs
if (x) {
OtherMethod();
}
OtherMethod:
ForeignType.Method();
yea
probably
idk if labapi fucks it up
i can also check if the assembly is loaded using the reflection i think...
but yeah this is good
u can yea
How can I get players which player muted or does he enable mute alives players and etc.?
i feel kinda stupid for not realizing this
mute is client side
this is the length i went to to avoid my users absolutely needing to install UCR
and it was probably for nothing LOL
its really just a byproduct of how c# works. i don't think they want u to do it
well, i guess if it works it works, and this isnt super important what i'm doing
unfortunate
is there any "official" way to do soft-dependencies?
besides reflection which is what i was doing.
other than referencing it and never using it if its not loaded not really
what do I do to change this specifically?
Not possible base-game
is it possible at all?
youll need to do Player::InfoArea &= ~(PlayerInfoArea.Role | PlayerInfoArea.Nickname); // add all other things you need to hide
and then Player::CustomInfo = "{badge}\n{custominfo}\n{name}\n{roletext}"
I wrote a whole system to manage this, it was super painful, but for most cases this should be enough
oh that sounds like fun
oh yeah you also need to hide the nickname and badge etc
yea i assumed so
okay good
I might have to write my own system to manage it
how do I see what info segments are enabled so I can make it look identical to base game
nvm its bitwise operations
sorry new to c#
How do I get the values for each of those things individually so I can rebuild the string? badge, role, nickname, unit name, power status (i have no idea what badge and power status even mean lol)
Badge: The meta-role you have is the best way i can explain (Patreon supporter, admin, etc)
Power Status: Whether to follow or give orders (i think its only visible to NTF and guards but its broken and seems to show on d class and scientists too sometimes)
power status seems pointless so i'll just ignore that
badge idk how to get, role i know how to get, nickname i know how to get, unit name i dont know how to get
Nickname: Player::Nickname
Unit name: NamingRulesManager.ClientFetchReceived(Player::Team, Player::UnitId);
nvm unit name i can get thru the role type id
uh
what ab badge
thats the last one
you should probably keep the badge visible
if it always appears at the top then i'll do that
it stays on top all the time anyways i think
Does Unity provide a high-resolution time? I need something that'll update during a method call
- you don't have to add it to custom info
- since it's independent it can change (showtag/hidetag)
Stopwatch.GetTimestamp()
https://github.com/icedchai/omni-plugins-pub/blob/d602e8deed3cc2d8b281fcdcae3df332db7ddba2/Omni-Utils/extensions/PlayerExtensions.cs#L128
here is my system, its for exiled but...
I just needed to share it because i fucking hated working on it
@buoyant oyster you probably dont need to show the UnitName manually
ty
just leave it in the InfoArea
if we were in .NET 7 you could use GetElapsedTime but you have to do some math to calculate it unfortunately
does UnitName apply only to human roles?
Man I fucking hate programming I dont know why I ever got into this shitshow in the first place
yes sir
in fact it only applies to MTF and Guards, but its still a human universal trait
(Foreshadowing for CI Unitnames??)
sourceof.net to the rescue
what about the chaos roles?
one day itll get better though i trust that
chaos repressor n whatever
/// <summary>Gets the elapsed time since the <paramref name="startingTimestamp"/> value retrieved using <see cref="GetTimestamp"/>.</summary>
/// <param name="startingTimestamp">The timestamp marking the beginning of the time period.</param>
/// <returns>A <see cref="TimeSpan"/> for the elapsed time between the starting timestamp and the time of this call.</returns>
public static TimeSpan GetElapsedTime(long startingTimestamp) =>
GetElapsedTime(startingTimestamp, GetTimestamp());
/// <summary>Gets the elapsed time between two timestamps retrieved using <see cref="GetTimestamp"/>.</summary>
/// <param name="startingTimestamp">The timestamp marking the beginning of the time period.</param>
/// <param name="endingTimestamp">The timestamp marking the end of the time period.</param>
/// <returns>A <see cref="TimeSpan"/> for the elapsed time between the starting and ending timestamps.</returns>
public static TimeSpan GetElapsedTime(long startingTimestamp, long endingTimestamp) =>
new((long)((endingTimestamp - startingTimestamp) * s_tickFrequency));
easy peasy
Every human role has a UnitName dude, its just most of the time null
or empty string
not every human class does i don't think
roles have an UsesUnitNames property or similar
why it gotta be so complicated
wait
You can also just leave PlayerInfoArea.UnitName enabled :3
for 99% of cases it literally doesnt matter and will only serve to make your headache worse :3
good to know
right, ClientFetchReceived returns an empty string if it couldn't befound
but
labapi returns -1 if there is no unit so you'd get an ArgumentOutOfRangeException
only difference
with it disabled and you add your own way to fetch it :
Name
RoleName (UNIT-NAME)```
with it enabled:
Name
Rolename
(UNIT-NAME)```
i think it returns -1 if its not a human role?
hold on
yeah the argument out of range exception is true though
so... since LabPlayer wrapper just doesnt have UnitName property (which EXILED has and has protections for), and managing it would be a god-damned PAIN anyways
Just dont bother with it
Coming from one Rolename replacer to another
yeah it's a bit funky but not too bad
if somebody complains
they should not complain
i was also lazy to include unit names in the info because there isn't much point
like they will have to have a side-by-side to even realize there's a difference
you never know if that one person will
true
so to clarify rq the only two that i really need to disable and build a new string for are Nickname and Role?
that one person is a plugin programmer and understands why he didnt do it
basically
and ensure CustomInfo is enabled
@upper vapor Chaos Theory (for a while) has used EXILED.CustomRoles for their custom roles, and a lot of them are military classes, and the MTF ones have this same issue with the Unitname being below the rolename instead of after
and I bet if I asked 100 players about it, only one would even say anything approaching "oh yeah, i noticed that"
in fact, im fairly certain 99% of players wont even realize if the RoleName is above or below your username. It is definitely way more jarring, but it took even me a long time to explicitly notice that (some customrole implementations use CustomInfo directly instead of rebuilding the InfoArea from scratch)
eh, yeah
Question, can plugins use Unity's RuntimeInitializeOnLoadMethod
no they cannot, dunno why I didn't just test it
how i can create custom receipt in 914?
Scp914ProcessingInventoryItemEventArgs dont have next item or something
Oof I've been tinkering with that
I'll hop on my PC in a sec
Look into the Scp914 class, I think that's where to start looking
probably recipe but autocorrected
I must be really blind if thats true because I couldn't find it -v-
What I've found is that theres the IScp914ItemProcessor interface under LabApi, and you can create custom processors for items
and then in the plugin enable (or maybe map generated, havent tested that far yet) you can set the item processor to an instance of your class
but someone let me know if I'm doing it a bad way cus its 90% working but I'm not sure whats wrong with the 10%
taking a look again
I guess you could set the pickup, say the event is not allowed, and manually move it under Scp914ProcessingPickupEventArgs
and can manually change the items in the players inventories under Scp914ProcessingPlayerEventArgs
@unique crane do you can review pr? 
has anyone used a custom 914 processor before?




l

