#plugins-dev-chat
1 messages ยท Page 21 of 1
so uhh idk what I did but I broke the formatting in the text toy lol
can't even get any black squares :(
only {0} seems to register
what event is equivalent to playercheckreservedslot? I cannot find it
I feel like all of these half Mirror issues how it works
and also Mirror makes this work, like AdminToys
I just wish for a RA customization like SSS
I made my own RA panel with SSS :P
I do not wish to delegate admin work into an inferior solution lol
(im not saying yours is inferior, I'm assuming if I were to do it, it would be jank)
I tried to replace ban templating with a custom predefined punisment system and I saw how ban templates were actually handled and was like "yup nope, fuck that"
Why does the fog overlap the text
add
span {
z-index: 100;
}
wait this is not webdev
but pretty sure you can add some z-indexing somewhere
lowkey this would be nice just because there are plugins that want this and have to create jank solutions themselves
also i never understood why unit names were fixed
will we ever see a way to change the fire rate of guns?
127 yes other guns idk
please
you can do it nw i know you can
just one networked byte thats all it takes to change lives
byte
ew
icl i dnt even know how the fire rate is stored
so i assume a byte is good enough.
I assume it would be in RPM which is typically more than 500
So a byte would definitely not do
float's fine for that
I don't get the fixation on prematurely optimizing the bandwidth in SL
annoying when it starts limiting you
Im just used to using byte for everything
If you dont need more than a byte sure
I dont know if the system would support decimal fire rates so an unsigned short would probably be the lowest thing you can use
Unless you want negative fire rates 
it fires in reverse, you would've shot your gun 3 seconds ago
Waypoints have a max range of 128 so you need to spawn multiple doors if you want a bigger area
There are any ways to change holders name on giving keycard at the start?
I know how do it by manually editing the module
I have no clue how to do it on the LabApi wrapper however
NametagDetail nametagDetail = ParentKeycard.Details.OfType<NametagDetail>().FirstOrDefault();
if (nametagDetail != null)
{
try
{
object[] args = { value.Replace("%name%", ParentKeycard.Owner.nicknameSync.MyNick) };
ArraySegment<object> arguments = new(args);
nametagDetail.SetArguments(arguments);
}
catch (Exception ex)
{
LogManager.Error($"Error processing CustomItemNameDetail: {ex.Message}\nStack Trace: {ex.StackTrace}");
}
}
else
LogManager.Error($"{nameof(CustomKeycard)}: This keycard {ParentKeycard.ItemTypeId} doesn't have a NameTag section.");
U gave me info where it contains so I can patch it rn. thanks
If anyone was curious this is the patch you would have to do to edit 127s firerate
[HarmonyPatch(typeof(Scp127ActionModule), nameof(Scp127ActionModule.BaseFireRate), MethodType.Getter)]
public static class FireRatePatch
{
public static void Postfix(Scp127ActionModule __instance, ref float __result)
{
try
{
__result = Scp127TierManagerModule.GetTierForItem(__instance.Item) switch
{
Scp127Tier.Tier1 => 1,
Scp127Tier.Tier2 => 1,
Scp127Tier.Tier3 => 1,
_ => __result
};
}
catch (Exception ex)
{
LabApi.Features.Console.Logger.Error($"{nameof(FireRatePatch)}: {ex.Message}\n{ex.StackTrace}");
}
}
}
Hello, this is not synced
And will cause desync
Or at least I doubt its synced?
public static void Shoot(PlayerHurtEventArgs ev)
{
if (ev.DamageHandler is not FirearmDamageHandler handler)
return;
if (handler.Hitbox != HitboxType.Headshot)
return;
AudioPlayer audioPlayer = AudioPlayer.CreateOrGet($"Player {ev.Player.Nickname}", onIntialCreation: (p) =>
{
// This created speaker will be in 2D space ( audio will be always playing directly on you not from specific location ) but make sure that max distance is set to some higher value.
Speaker speaker = p.AddSpeaker("Main", isSpatial: false, maxDistance: 5000f);
},
condition: hub =>
{
if (hub.IsHost)
return false;
if (hub.authManager.InstanceMode == ClientInstanceMode.Unverified && !hub.nicknameSync.NickSet)
return false;
if (hub.authManager.syncMode == (SyncMode)ClientInstanceMode.DedicatedServer)
return false;
Logger.Info(ev.Attacker.ReferenceHub.nicknameSync.Network_myNickSync + $" IsAllowed: {ev.Attacker.ReferenceHub == hub} Shooter: {ev.Attacker.ReferenceHub.nicknameSync.Network_myNickSync}");
return ev.Attacker.ReferenceHub == hub;
});
audioPlayer.AddClip("headshot");
}
Honestly im confused someone knows why ev.Attacker is always the first referencehub that joined, do i use another event and even if i can take the hitbox that it hit i tried Hurted and Hurting both give the same result
its 3 days that im confused on why its happening
is this a dink sound
is there a shotevent btw that way you avoid needing to check the damage handler
does it work or is there a problem
the shot event doesn't give me the Hitbox
im tired so i cant parse your question properly
thats weird
Ev.Attacker is always the first hub
the exiled one does i think
yes
what does this mean
Host
i just think i will patch it myself and fix it?
because like it gets the first player who joined or Host
transpilers aren't hard so

do you have a fixation on transpilers
they are fun
i think youre just about the only person ive seen talk about transpilers
exiled is run by transpilers
there's no event with Hitbox so the only that
hold my water
transpilers are amazing
transpilers are peak
there we go
transpiler enthusiasts are everywhere
-# maybe not everywhere but you might not know if someone is
i just think the best way is that
but still i don't understand why its that the case
i will study transpilers sometime then
i think the value gets reset, after getting deleted, how can i save it and store it?
i think like a var?
i guess you could store handler.Attacker.Hub instead
also store the hub outside the lambda so you don't box the whole attacker struct
What is a OpenHallway?
why it works so low level code?
there is no wrapper for it yet sadly
if you want to spawn more than one texttoy you might want to consider caching the prefab
ofc
so you want to play dink sound for the attacker when he hits someone's head with a gun right?
that's what the code does rn
Are doors the only nodes which does this?
Can you replace them with something else so it doesn't take up a lot of resources?
i think the only other reasonable option are lockers
how big of a space do you need, you can only have 254 waypoints and about 100 of them are already used up by the game itself
That 100 is fine, cause I do not generate anything so I have 254
but I do not want to spawn doors just to have moving space
you can spawn lockers apparently
Yeah, but was thinking if I could replicate the waypoint system on Primitives
i think lockers dont get culled tho
by doing correct component init
doors would probably be better for performance
Huh, I would assume a simple object would work better, but I guess toys have too many attachments?
im confused about what you want todo
A weird one, not sure if I actually want or need this, but currently I want to make a grid system where it spawns a cube every 128 and it acts like a waypoint
I can do it with doors sure, but not sure if that is a good way to do it
sort of think of gmod flatgrass or minecraft superflat world ๐
What was the reasoning behind the relative positioning system
That is fine, temporarily during development it can be doors and later when it is implemented can be changed
That much pain just for elevators? :/
(if the system is required by then)
Bika my beloved
hewo Quincy

yes but for some reason the attacker is the first player who joined the server and not the attacker
you're logging the ev.Attacker's nickname twice
for me it works
Oh yea i changed that when i was testing
For me it just says the first player
ill take a look at the base game code that calls the event
for example
PlayerA has connected before PlayerB and PlayerB shoots at someone PlayerA will hear it but not PlayerB
in the console it will log
PlayerA isAllowed: false Shooter: PlayerB
PlayerB isAllowed: true Shooter: PlayerB
even if PlayerA shot them
I don't know if its just me or a bug
No issues here
base game code looks fine
I don't have any other plugin other than mine so
there's an ev.IsAllowed for the hurt but i don't think thats the issue
what happens if you print out ((AttackerDamageHandler)ev.DamageHandler).Attacker.Hub instead
Same
I tried both of them
i rewrote the code so it's a bit more optimal, can you try it out and see if the problem persists?
public static void Shoot(PlayerHurtEventArgs ev)
{
if (ev.Attacker is null || ev.Attacker.IsHost || ev.Attacker.IsDummy)
return;
if (ev.DamageHandler is not FirearmDamageHandler handler)
return;
if (handler.Hitbox is not HitboxType.Headshot)
return;
AudioPlayer audioPlayer = AudioPlayer.CreateOrGet($"Player {ev.Attacker.Nickname}", sendSoundGlobally: false, owners: [ev.Attacker.ReferenceHub], onIntialCreation: (p) =>
{
// This created speaker will be in 2D space ( audio will be always playing directly on you not from specific location ) but make sure that max distance is set to some higher value.
p.AddSpeaker("Main", 5f, isSpatial: false, maxDistance: 5000f);
});
audioPlayer.AddClip("headshot");
}
yeah ill try it out in a sec
I just cannot try it now
im like half asleep, ill try it out tmr
obv and you need to compile the plugin
Peak
it does that sometimes
Exception thrown during death?
Actually generally when that happens I stay alive at 0 hp

i guess it happened because i died and immedietly after respawned in a wave
forceclass fixes it
I'll be honest the dedicated server player getting kicked should close the server
Cause if you dont notice it you're left wondering why things just stop breaking
honestly a dedicated server doesnt need a host player in the first place
Can't reload/unload a gun, and sometimes you can't see players move but you still see them shoot from where they actually are
Yeah the dedi should just never be accessible
I have no idea why it is
I just patched NetworkServer to not disconnect the dedi on failure
Because there's zero reason for it to be impacted that bad
yeah that works, although not in all cases
My cases were accidentally sending the dedi a network message
Because it's in Player.List

The worst part is the failures it causes can be pretty unnoticeable
i recommend you use Player.ReadyList or Player.AuthenticatedList anyway
Yeah I use ReadyList now
But I patched it anyway since the dedi not handling a message really isn't fatal heh
for sending network messages Player.AuthenticatedList is a better fit
If someone else on the team makes that mistake they won't have to go through the same amount of pain as I did
Noted ๐
OnPlayerJoined is fired for authenticated players right?
yep
Makes sense, will switch tomorrow
God that whole dedi disconnect issue got me sweating bullets
Thought I wouldn't find the source before 14.1
@celest thorn just tested it and hurt is working as expected on my end
how get frames from a video ?
Yeah hurt works fine here got about a hundred different handlers
Oh ok
Thank you both of you guys
I like LabAPI using nullable too, cleaner code. Although I have to report OnPlayerDroppedPickup's pickup shouldn't be not null
btw are you still using exiled?
It can be null if the player starts dropping 1344, since the pickup drop is delayed
no
i just switched everything it took me the entire night
but i did it
hmmm
yeah thats abit anoying
IMO I would call Dropping for 1344 but not Dropped until the animation is finished and the drop actually happens
@terse bone do you know?
Are you trying to translate a video into TextToy frames
i used ffmpeg
do you can send the code?
i converted it manually with commands
// Scale it down horizontally
.\ffmpeg.exe -i file.mp4 -vf scale=100:-2,setsar=1:1 -c:a copy file2.mp4
// Take 10 frames from every second of video
.\ffmpeg.exe -i file2.mp4 -r 1/0.1 "%02d.bmp"
then i used my program to convert these images to text files compatible with TMP
And in a plugin i have a command that reads all the text files generated from a selected directory (directory's name is the name of the gif), spawns a texttoy and sets the text to the subsequent contents of the files containing gif frames in a coroutine.
it's not realtime
is there any exception in LocalAdminLogs?
ame server has not sent a heartbeat in 31 seconds. Restarting the server in 9 seconds! Type "hbc" command to abort!
can you show the full code?
// Spawn TextToy
GameObject prefab = NetworkClient.prefabs.Select(x => x.Value).First(x =>
{
return x.TryGetComponent(out AdminToyBase toyBase) && toyBase.CommandName is "Text";
});
GameObject obj = UnityEngine.Object.Instantiate(prefab);
AdminToyBase toyBase = obj.GetComponent<AdminToyBase>();
//toyBase.SpawnerFootprint = new(Server.Host.ReferenceHub);
NetworkServer.Spawn(toyBase.gameObject);
TextToy toy = toyBase as TextToy;
toy.transform.SetPositionAndRotation(pl.Position, Quaternion.identity);
toy.NetworkIsStatic = false;
toy.DisplaySize = new(2000f, 4000f);
for (int i = 0; i < 20000; i++)
{
toy.TextFormat += $"{i}{(i % 100 == 0 ? "\n" : string.Empty)}";
}
string imagePath = Path.Combine(Path.Combine(LabApi.Loader.ConfigurationLoader.GetConfigDirectory(Plugin.Instance, true).FullName), "test.png");
Bitmap bitmap = new(imagePath);
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
System.Drawing.Color pixel = bitmap.GetPixel(x, y);
string hex = $"#{pixel.R:X2}{pixel.G:X2}{pixel.B:X2}";
toy.Arguments.Add($"<color=#{hex}>โ</color>");
}
}
[LabAPI INTERNAL WARN] Backing up to the default AdminToy constructor. Missing constructor handler for type AdminToys.TextToy
now it works but it doesn't show up
this is wrong
it should be $"{{{i}}}{(i % 100 == 0 ? "\n" : string.Empty)}";
What the fuck
you need to escape the { and } chars
oh
but
if it had worked, it would have shown something even like this
yep, there should have been numbers
but it doesnt
and written it
why
..
that's normal
also nothing show up
// Spawn TextToy
GameObject prefab = NetworkClient.prefabs.Select(x => x.Value).First(x =>
{
return x.TryGetComponent(out AdminToyBase toyBase) && toyBase.CommandName is "Text";
});
GameObject obj = UnityEngine.Object.Instantiate(prefab);
AdminToyBase toyBase = obj.GetComponent<AdminToyBase>();
//toyBase.SpawnerFootprint = new(Server.Host.ReferenceHub);
NetworkServer.Spawn(toyBase.gameObject);
TextToy toy = toyBase as TextToy;
toy.transform.SetPositionAndRotation(pl.Position, Quaternion.identity);
toy.NetworkIsStatic = false;
toy.DisplaySize = new(2000f, 4000f);
for (int i = 0; i < 20000; i++)
{
toy.TextFormat += $"{{{i}}}{(i % 100 == 0 ? "\n" : string.Empty)}";
}
string imagePath = Path.Combine(Path.Combine(LabApi.Loader.ConfigurationLoader.GetConfigDirectory(Plugin.Instance, true).FullName), "test.png");
Bitmap bitmap = new(imagePath);
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
System.Drawing.Color pixel = bitmap.GetPixel(x, y);
string hex = $"#{pixel.R:X2}{pixel.G:X2}{pixel.B:X2}";
toy.Arguments.Add($"<color=#{hex}>โ</color>");
}
}
hmm
which max size you can make?
You dont need to add the closing color tag btw
<color=#FF0000>A<color=#00FF00>B will work just fine
we dont trust nw
k
lol
How taxing is updating text toys like that for images
they dont wanna add image toy
Can't really profile much without downloading Unity and setting it all up, wondering if someone checked that out already
so we use text toy
Alsoooo I would suggest not adding each "pixel" to arguments
I would batch them together as much as possible
Since then you have to replace X * Y arguments
which yea..
takes a bit
You can easily do it like per line
yea you want to use as least amount of chars and make as least Arguments as possible
yup
{{ is just escaped { so you need to add one more that is not escaped
-# Escaped meaning it has no special function, regular char
uh
so I assume no server side textures either
@terse bone do you know what the problem?
<line-height={0.9f * fontSize}><cspace=-{0.17f * fontSize}><size={fontSize}>
pretty good
use โฌ
lol
if <size=1> then?
just normally
you can set it, say 1f, 2f, 0.3f, depending on the size you want to display
i used first char i found โ for that
nice
how many fps?
๐

Static text doesn't impact performance much, unless there is fog/void behind it
The only thing that you will feel is a stutter caused by the need to sync all that text data
I wonder how bad it will be for people with overall bad internet connection
?
isnt pl.ReferenceHub.connectionToClient.observing just a hashset?
you probably have to call something higher up if you want to destroy it, or just destroy it yourself
btw the code your using is from mirror not SL
no
player.Connection.Send(new ObjectDestroyMessage { netid = toy.netid });
^
Maybe Netid with uppercase
Idk
Oh
Yea
Removing from observers list shouldn't destroy the object, because you just stop observing changes, object still exists
wasnt even a nw change
removing stuff from certain clients in not supported by SL in anyway, thats something Mirror allows you todo dont get that confused
teleporting them out of culling distance would of increased fps iirc, although its better if you send a destroy message
EffectChanged event or smth i forgot
doesnt exists
effect updated
you can set their scale to 0

Still has the problem that I have to spawn doors so ppl can move
Cause I can spawn them and just remove them clientside
or just spawn below
remove them client-side

Am i going crazy or PlayerValidatedVisibilityEventArgs is like the weirdest event because it flags randomly, like sometimes it does and 99% it doesn't
do you mean it flags as invisible randomly?
If the two players aren't within distance then IsVisible will be false by default
(Most of the time) you're not in range of all other players
i mean the event does flag on some random moments
or in an instance not even run
I have a code that makes people invisible and sometimes it works and fires the event if i update it then it doesn't
like idk what could be the issue but the event is not firing
what is playervalidatedvisibility

happens after the visibility check is made, right before sending player positions to observers
you should be able to override the visibility in the event to make players invisible/or visible to eachother
Like i can even show you in vc
like the event exist but never fires
alright
observing as in loading a player in?
Im in some deep cursed rabbithole 
its done every frame for every player combo
yeah everytime it checks
Im gonna make a plugin for powers

what kind of super powers wohld you like to see in scp sl
what is so hype in that livestream
kinda hard to implement and also not rlly practical since 90% of SL takes place indoors
What is the maximum length of TextToy supported by the client? (use Arguments and {n}
it seems to be between 1587600 strings and 1597696 strings
strings?
or char? I don't know what to call that๐
HczStraightPipeRoom maybe?
the gameobject's name is HCZ_Straight_PipeRoom
not sure if the roomname enum actually exists
These are the roomnames
public enum RoomName
{
Unnamed,
LczClassDSpawn,
LczComputerRoom,
LczCheckpointA,
LczCheckpointB,
LczToilets,
LczArmory,
Lcz173,
LczGlassroom,
Lcz330,
Lcz914,
LczGreenhouse,
LczAirlock,
HczCheckpointToEntranceZone,
HczCheckpointA,
HczCheckpointB,
HczWarhead,
Hcz049,
Hcz079,
Hcz096,
Hcz106,
Hcz939,
HczMicroHID,
HczArmory,
HczServers,
HczTesla,
EzCollapsedTunnel,
EzGateA,
EzGateB,
EzRedroom,
EzEvacShelter,
EzIntercom,
EzOfficeStoried,
EzOfficeLarge,
EzOfficeSmall,
Outside,
Pocket,
HczTestroom,
Hcz127
}
damn it doesn't exist yet
does that mean it won't be inside of RoomIdentifier.OnAdded then or nah?
or will i just have to use it's string name for now?
IsInvisible is a patch
you can use the event tho
PlayerValidatingVisibilityEventArgs
iirc
save the player to local hashset and check inside this event
public override void OnPlayerValidatedVisibility(PlayerValidatedVisibilityEventArgs ev)
{
ev.IsVisible = !hashset.Contains(ev.Player);
}
idk, this is the only event for that
I wouldn't assign IsVisible directly like that
if another plugin tries to change the value you're overriding it
lemme find it
shit wrong project
fuck
How can I turn off LabAPI's Debug?
Do ya'all want this pinned?
The Logger.Debug one?
It can input a bool parameter after string
You can definitely a IsDebug in your config (or somewhere else) and you can just do
Logger.Debug("meow", Main.Instance.Config.IsDebug);
Not really can be found inside labapi src
Also would have to be updated every time the enum changes
Yup that too
Okay, just figured best to ask because I have seen it pop up a few times already
IDE is usually show these, even the associated tags
i dont believe so
Yeah I misread the source
But we're getting heavy server performance impact with a large amount of ragdolls so I started digging
Seems like they keep updating on the server? A little confusing
Kinda thought it'd be a one off or something
Hi. If I am hosting multiple different servers, is it possible to put them in the same place on the verified server list?
my guess is the server still simulates them the same way client does?
just isnt synced
seems synced, just didn't think they'd go this far
I get that SL needs it for stuff like 3114 disguises, 049 reviving and zombies eating corpses
buuut it's tanking our perfs a little too much so I'll probs start patching it left and right if I have to
i thought only the starting position and velocity of ragdolls were synced
idk...
because you cant cancel the event
What does MinDistance/MaxDistance in SpeakerToy do?
it controls the audio level based on how far the player is
up to mindistance the volume is at max (that you specify)
and gradually fades out until you reach maxdistance, where it's completely silent
not sure which rolloff is used in the game (linear, logarithmic or custom)
I can take a look but I feel like its logarithmic
yeah that would be the ideal one
yep
If i destroy a door, will i reclaim a Waypoint?
yeah
Soo in theory, i can replace all the doors in the facility and relative positioning wouldn't break right?
maybe
But for the LabAPI because it's Logging every event
Ah, well idk I not even using that version since it came out when I was going to sleep
how i can inverse it?
You cannot change that
You can only make it change the Min/max distance
Is that handled clientside or is that a serialized value?
MinMax is syncvar
Then the algo itself isn't i assume
nop
Time to find an arbitrary mirror packet that can change non syncvar values on client 
I was actually wondering if someone made an attempt to make a melee only weapon
copying 939 ability or somethign
and how would you copy it?
jailbird without charge

Question, is there anything that will go wrong if I patch Player.List as to not include the host player
just use Player.ReadyList
I know about ReadyList, I want to know if patching List is gonna cause issues
youd have to check all your plugins 
The fact you can even get the dedicated player is pretty annoying
I managed to kill it by applying an effect to it
No idea why that's a thing
not sure why you need to use Player.List in that case
Mostly wanna avoid user error
That is a good question actually. I would need to look into how the attavk works
Because when said error makes the server implode in sometimes pretty sneaky ways it sucks
Though jailbird is easier yes
Like I noticed it happened because I couldn't pull the hammer of my revolver back
if we remove host its still user error
Everything worked fine except that
I mean, what usecases are there for having the host player accessible
i recomend they use Player.GetAll() instead it doesnt have any of the issues that Player.List does
i would say for them to read the docs, but atm they are not available until the nuget is ready
its client sided
Ended up patching a handful so that the server doesn't kill itself, just logs errors and continues
yeah thats good, its not good to use player.list without filtering in any case
Yeah because of unauthenticated/non ready players
yeah, people often dont realise that
I've been moving to ReadyList whenever I see List, just a loooot of things to tweak
Porting from 14.0 to 14.1 was hell and it was my first time modding for SL, pretty cool to see the end result though
glad it worked out
Ay
LabAPI was definitely a good call from you all
And also related to something I did today but SpeakerToy is sweet
I like the fact multiple speakers can be sync'd through the same controller id
I was worried about potential desync between speakers when I started
yeah its a great idea, you can thank killer0992 for that
10/10
he needed it for his audioplayer 
having radio in inv as it's still being used yes
The Dev build being on release is unintentional though
ye i know
i forgot about it having a battery
Oh yeah, the revolver can shoot bullets and buckshot
Is there a way to make it fire buckshot without changing the cylinder module?
Lets say idk I wanna shoot a bullet and then buckshot, alternating every shot
@stuck peak sry for ping but
is it intentional that the current early-server-build has 1.0.0 of labapi
i thought it was another beta release
also this is bugged
known
awesome
Yes
Yet we dont see any new stuff in #labapi-logs
lmao
beryl forgot to push to the public repo 
What would happen if I didn't say it 
itd be pushed when someone notices it
Just use EXILED 
in 14.2
yea player doesnt yet
As before, modifying GameObject.transform.localScale and SendSpawnMessage in the previous way results in:
Use Player.ReadyList

public static void SetScale(this Player player, Vector3 scale)
{
player.ReferenceHub.transform.localScale = scale;
foreach (Player target in Player.ReadyList)
NetworkServer.SendSpawnMessage(player.ReferenceHub.networkIdentity, target.Connection);
}
works for me
0 issues
Remove Player.List ๐ฃ๏ธ
It's accessible through the dictionary anyway
i recommend authenticated list, for network messages, readyList contains dummies
ah nice to know
you mean?
๐
oh the PR wasnt merged?
it seems no
dont think any pr merged outside of x3rt and prob internal ones
yeah its not in yet
๐
you can use Player.GetAll(PlayerSearchFlags.AuthenticatedPlayers) instead
always use ReadyList, use AuthenticatedList if need for network sending, right?
ReadyList contains all players that are authenticated and all npcs that are dummies, and authenticatedList will contain only authenticated players
Why is LabAPI built in debug on early-server-build? It makes players to be disconnected because it tries to log PlayerSendingVoiceMessage event which contain a ref property and causes a NotSupportedException on propertyInfo.GetValue(args);
You can replace the dll to the release in the server files for now, sorry. Hopefully it will be resolved soon.
why does everything use StringBuilderPool and not just new StringBuilder()?
creating new things fast can be expensive
ive not seen anyone use new StringBuilder() other than me
really? that expensive?
because of garbage it creates
hm
they create objects
which get cleaned up at the end of scope, but if you are creating more than the GC can cleanup intime
you get a memory leak
or, the GC will do a longer cleanup which can also impact performance as itl pause the program for X time to cleanup
ok, ty
StringBuilder is especially expensive as it creates array to store the characters in it too
Or maybe its lazy loaded, not sure
me when spans
but i can't get harmony to work in .net standard 
Aw
But CylinderAmmoModule uses ReadonlySpan
Ik
yeah SL can use spans but the plugins (as far as my testing goes) can't have spans and harmony patches in one assembly
i have them
how
in .net framework?
and project is just net48
works for me
oh well
not that big of a deal
well actually nvm
so
when pl.Scale?
if i go into the implementation then it's there somehow
@unique crane ?
works for me
hes worked on other things
yea, for me too
but it easy for him just add it
10-20 minutes work
you can also pr it urself!
you gotta specify the t-shirt size
idk how
he's smarter than me
base-game PR 
/// <summary>
/// Gets a player's scale.
/// </summary>
/// <param name="player">The player of which to get the scale of.</param>
/// <returns>The scale found.</returns>
public static Vector3 GetScale(this Player player) => player.ReferenceHub.transform.localScale;
/// <summary>
/// Sets a player's scale.
/// </summary>
/// <param name="player">The player to set scale of.</param>
/// <param name="scale">The scale to set.</param>
public static void SetScale(this Player player, Vector3 scale)
{
player.ReferenceHub.transform.localScale = scale;
foreach (Player target in Player.GetAll(PlayerSearchFlags.AuthenticatedPlayers))
NetworkServer.SendSpawnMessage(player.ReferenceHub.networkIdentity, target.Connection);
}
really simple
First of all thats is a really bad imagination of how it works
even tho i dont think SL should have that
It looks like a crutch
how many story points do you think it would be?
you can just add property
If I were to do it, I would implement it base game xd
i know
its for logic
Like ofc I can do this, but then like...
"why you didnt implement it base game"
"wah wah"
real
average sl player, dev and host
the average person with high self-esteem 
errrrrr
no
average entitled person
?
but labapi it part of the game
or how
kind of
its included with it
but not part of Assembly-CSharp
Scaling requires base game impl to be properly handled no?
The one always posted is like a crude hack that breaks easily
Atleast it always breaks for me and make you unable to move after a while 
thats a u issue tbh
@royal mica
this has never failed me
make sure you dont send to server host tho
(aka dedi etc)
Strange
player.transform.localScale = random ? new Vector3(Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f)) : scale;
foreach (var toSendTo in Player.GetPlayers())
{
SendSpawnMessage.Invoke(null, [player.networkIdentity, toSendTo.Connection]);
}
whats GetPlayers()
NwAPI probably
does it include host or anything
nope
hm
well it contains unauthenticated players, but thats "ok" for mirror messages
Oh I pulled the code from wrong branch oops
Same code, just Players.List
Judging from previous discussion regard different enumerators in Player, I assume this can break horribly when used at the wrong time causing the issues
thats ur issue
no its 24/7 it will break
use GetAll() or ReadyList
Funny, cause it works and only breaks much later

it breaks firearm animations instantly, not just later
but yeah, there can be side effects that only manifest some time after changing size
I find it very strange how sending it to the host player breaks so much
I patched it out because it makes no sense
The host just doesn't have the handlers for it so it not doing anything about the message pretty much changes nothing
I'll send the patch in a few
I'm planing on creating an Extension function instead and just hard filter it out
and use that everywhere
Isn't GetAll enumerates every player and returns then as a List?
Ah it just creates a yield return
public static IEnumerable<Player> GetAll(PlayerSearchFlags flags = PlayerSearchFlags.AuthenticatedAndDummy)
{
bool authenticated = (flags & PlayerSearchFlags.AuthenticatedPlayers) > PlayerSearchFlags.None;
bool flag1 = (flags & PlayerSearchFlags.UnauthenticatedPlayers) > PlayerSearchFlags.None;
bool dummyNpcs = (flags & PlayerSearchFlags.DummyNpcs) > PlayerSearchFlags.None;
bool flag2 = (flags & PlayerSearchFlags.RegularNpcs) > PlayerSearchFlags.None;
bool host = (flags & PlayerSearchFlags.Host) > PlayerSearchFlags.None;
bool includePlayers = authenticated | flag1;
bool allPlayers = authenticated & flag1;
bool includeNpcs = dummyNpcs | flag2;
bool allNpcs = dummyNpcs & flag2;
foreach (Player player in (IEnumerable<Player>) Player.List)
{
if (includePlayers && player.IsPlayer && (allPlayers || player.IsReady == authenticated) || includeNpcs && player.IsNpc && (allNpcs || player.IsDummy == dummyNpcs) || host && player.IsHost)
yield return player;
}
}
Though this code looks horrendous decompiled lol
You can just open it on github
the code on github isnt much better lol
source makes more sense why it like that ๐
[HarmonyPatch(typeof(NetworkServer), nameof(NetworkServer.UnpackAndInvoke))]
public static class HostDisconnectPatch
{
public static void Postfix(ref bool __result, NetworkConnectionToClient connection, NetworkReader reader, int channelId)
{
if (connection.connectionId == 0)
{
__result = true;
}
}
}
tada your server stops killing itself
atp I'd just patch player.list if you're only using your own plugins and you don't wanna deal with accidentally using it and exploding a server
what i did a while ago, just didn't filter out the host
[2025-05-17 18:17:26.414 +00:00] [ERROR] [LabApi] 'InvalidOperationException' occured while invoking 'Dying' on 'Buckets.EventsHandler.PlayerEvents': 'Collection was modified; enumeration operation may not execute.', stack trace:
If i do ev.Player.ClearInventory(); in PlayerDyingEventArgs, but if i do
while (ev.Player.Items.Any())
{
var first = ev.Player.Items.First();
ev.Player.Inventory.ServerRemoveItem(first.Base.ItemSerial, null);
}
It actually works fine but i feel like a while is not a good idea for performance
im pretty sure that was fixed in 1.0.0
Oh nice to know how it was fixed? so i will not get the error and not run a while on a Single thread
Nothing wrong with that
while loops
As long as you know you're leaving it eventually
Im confused, like its not like the same piece of code i did? and its the same exact rn in 0.7.0?
yeah that method will actually freeze the server if the player is wearing scp1344
scp 1344 my hated
0.8 was missing the .ToArray() part
love the item, hate the gimmicks when interacting with it in code
No its not?
yeah its easy to forget about
0.6
hmm no 0.8 tag, but in 0.7 it was definitely wrong https://github.com/northwood-studios/LabAPI/blob/886980ecdd1fcc4d0e4abb11f94e332a39e9375d/LabApi/Features/Wrappers/Players/Player.cs#L1264
Is there a way to debug event handlers and find out which one's affecting something?
what specifically
u could technically patch the event call
I guess
trying to find out what's fucking up some damage
not taking any grenade damage sometimes
thats beryl
@marble cobalt
What's up?
^
releases badge links to nwapi
Oh whoops
We'll fix it up later
also beryl can u check my dm :3
Later, have too much stuff to do ๐
i will murder you
to what?
break u
better not be ssss stuff
no promises
errr
public static bool HasDoorPermission(this Player player, IDoorPermissionRequester requester, bool checkBypass, bool checkRole = true, bool checkInventory = false, bool checkCurrentItem = true)
{
if (player.IsBypassEnabled)
return true;
if (player.RoleBase is IDoorPermissionProvider roleProvider && requester.PermissionsPolicy.CheckPermissions(roleProvider.GetPermissions(requester)))
return true;
foreach (Item? item in player.Items)
{
if (item?.Base is IDoorPermissionProvider itemProvider && requester.PermissionsPolicy.CheckPermissions(itemProvider.GetPermissions(requester)))
return true;
}
return false;
}
errrrrr
then pr it in the next like
classes for custom keycards
yeah!
instead of just making a method to give u an item, u instead make a class for it :3
errrrr
what
what
public static bool HasDoorPermission(this Player player, IDoorPermissionRequester requester, bool checkBypass, bool checkRole = true, bool? checkInventory = false)
{
if (checkBypass && player.IsBypassEnabled)
return true;
if (checkRole && player.RoleBase is IDoorPermissionProvider roleProvider && requester.PermissionsPolicy.CheckPermissions(roleProvider.GetPermissions(requester)))
return true;
if (!checkInventory.HasValue)
return false;
if (checkInventory.Value)
{
if (player.Items.Any(item => InternalCheckItemForPermission(requester, item)))
return true;
}
else
{
if (InternalCheckItemForPermission(requester, player.CurrentItem))
return true;
}
return false;
}
i dont like this
hm
@restive turret ur like
stinky coder
what do u think
ignore the nullable bool
๐
that
one
is terrible
oh
@icy knoll what were u on about keycards before
Why nullable bool
cuz i have an idea on what i wanna do w that already
errr
brain damage
i couldnt decide how to do it
its temp
until i figure out how i wanna do it
enum ?
nugett
no!
the labapi create keycard item stuff gives back a KeycardItem which you then need to save in a variable to give to people and stuff. whereas i think the better way is to create a class to manage it, and just have a Give function to give it to someone and stuff like that
errrrr
idk
๐
ill figure it out
i think it'd be useful!
i will always call nuget, nugget
chicken nugget package
well i already had an idea
i ate a nugget burger yesterday
ur like 5 smh /j
modded?
@unique crane Just wanted to quickly ask before making an idea thread on github. Are there any updates on this? (#1313986094978695270 message)
Currently the client still checks for validation with no way to override this server-side.
@jaunty trail ur being made fun of here
unknown ๐
peak
you spent money on that?
fr
so i grabbed it as an extra?
bruh
its 3 dollars ๐
smh
lumi hates burger king confirmed
thats like 2 quid in the UK
anyway
so i would def buy too
public static bool HasDoorPermission(this Player player, IDoorPermissionRequester requester, bool checkBypass, bool checkRole = true, bool? checkInventory = false)
{
if (checkBypass && player.IsBypassEnabled)
return true;
if (checkRole && player.RoleBase is IDoorPermissionProvider roleProvider && requester.PermissionsPolicy.CheckPermissions(roleProvider.GetPermissions(requester)))
return true;
if (!checkInventory.HasValue)
return false;
if (checkInventory.Value)
{
if (player.Items.Any(CheckItemForPermission))
return true;
}
else
{
if (CheckItemForPermission(player.CurrentItem))
return true;
}
return false;
bool CheckItemForPermission(Item? item)
=> item?.Base is IDoorPermissionProvider itemProvider &&
requester.PermissionsPolicy.CheckPermissions(itemProvider.GetPermissions(requester));
}
so uhhh
make it enum
?
idk
didbt u sebt this?
our local burger king gave someone moldy burger buns (with the burger) and when they went to get it exchanged for a new one, they just replaced the buns, not the whole burger ๐
its a 2 minute walk to BK
theyre great
mcdonalds >>>
what do i call the enum
StinkyNamelessEnum
but its not worth a 20 minute walk over burger kings 2 minutes
mcdonaldsEnum
a door permission check?
[Flags]
enum DoorPermissionCheckEnum
{
None,
CheckRole,
CheckBypass,
CheckFullInventory,
CheckCurrentItem,
}
well
im not trying to make anythign
What is going on ๐ญ:
yeah yeah
someone made a burger out of you
at burger king
nugget burger
Nuh uh
why
yea i mean a single if statement i can call to see if player has permission to do a basegame open
wahh
true...
.
why me bruh
cuz i can
grrr
public static bool HasDoorPermission(this Player player, IDoorPermissionRequester requester, DoorPermissionCheck checkFlags = DoorPermissionCheck.Bypass | DoorPermissionCheck.Role | DoorPermissionCheck.CurrentItem)
{
if (checkFlags.HasFlag(DoorPermissionCheck.Bypass) && player.IsBypassEnabled)
return true;
if (checkFlags.HasFlag(DoorPermissionCheck.Role) && player.RoleBase is IDoorPermissionProvider roleProvider && requester.PermissionsPolicy.CheckPermissions(roleProvider.GetPermissions(requester)))
return true;
foreach (Item item in player.Items)
{
bool isCurrent = item == player.CurrentItem;
if (!checkFlags.HasFlag(DoorPermissionCheck.CurrentItem) && isCurrent)
continue;
if (!checkFlags.HasFlag(DoorPermissionCheck.InventoryExludingCurrent) && !isCurrent)
continue;
if (item?.Base is IDoorPermissionProvider itemProvider && requester.PermissionsPolicy.CheckPermissions(itemProvider.GetPermissions(requester)))
return true;
}
return false;
}
acs?
docs?
yes
or what
Assembly-CSharp
a..cs
damn
is this better
u stinker
I guess? You can also do is:
if item ==null continue
Ye
Oh nvm
It cant
Because if you dont have anything the item is nothing
But the current item might return null
thats fine with CurrentItem
is it not
errr
errrrr(or)
/// <summary>
/// Flags to use for <see cref="PlayerExtensions.HasDoorPermission"/>
/// </summary>
[Flags]
public enum DoorPermissionCheck
{
/// <summary>
/// None. Will not check anything.
/// </summary>
None = 0,
/// <summary>
/// Used to consider <see cref="AdminFlags.BypassMode"/>.
/// </summary>
Bypass = 1,
/// <summary>
/// Used to consider the player's <see cref="PlayerRoleBase"/>.
/// </summary>
Role = 2,
/// <summary>
/// Used to consider the player's <see cref="Player.CurrentItem"/>
/// </summary>
CurrentItem = 4,
/// <summary>
/// Used to consider the player's inventory, not including the item theyre holding.
/// </summary>
InventoryExludingCurrent = 8,
/// <summary>
/// Used to consider the player's ENTIRE inventory.
/// </summary>
FullInventory = CurrentItem | InventoryExludingCurrent,
}
Ye seems good
awesome
Can't wait for all your plugins break
mine wont
trust
KeycardCustomTaskForce
KeycardCustomSite02
KeycardCustomManagement
KeycardCustomMetalCase

Idk





