#plugins-dev-chat
1 messages · Page 45 of 1
Just raycast
How i never used it
Check what mask player interactions use
Raycast from the player's camera position, in the direction they're facing
(add like, 10/20cm away from the camera position to avoid hitting the head)
Raycast using the interaction distance
If you hit something, check the components for a door variant
Oh components i totally forgot that
Is there any event where I can get the User Id of the player when he leaves the server?
When LabApi.Events.Handlers.PlayerEvents.Left is called the UserId of the player is already null
ig use leaving instead
if that exists
It doesn't because you cant stop a user from leaving
alt f4 be like
i dont think its null, something else must be going on
Not null for us
yeah i would have alot of problems if thats true
are you using exiled?
Is PlayedTime null
no i mean, do you have exiled installed. not if your using it here
PlayedTime cannot be null because the error says the argument is null and not the list.
Fair
Yes it is installed
try without it installed
Wait do devs really try to use both at the same time
Sounds like a recipe for disaster
It is
Exiled slowly begin to be much headache for me
Idk we just use labapi and then patch whatever we need that it doesn't give us
Using both would be suicide imo
It is
I had to make my own "ExiledFixer" plugin
also this goes for any plugin with alot of patches, im not singling exiled out its just the most popular and has the most patches
next would be cedmod
All of our plugins are handmade for that reason
If something breaks we know it's on us
are there any good docs anywhere for LabAPI, or is it a case of look into other projects to figure out people have solved certain issues?
Well yeah
Our scale broke bc i tried to use the Player:Scale and then respawning the player
Oh we're currently missing a few features because of player scaling
Was funny
C*dm*d
Happened while I was sleeping
I fixed it, and then a few days later it broke again
Servers just instant dying
No logs
LabApi wiki
So now we're at a point where 14.1.1's scaling is actually worse than manual scaling in 14.1 and older
I wish we could revert it but nope
Idk I only started working on SL stuff during the 14.1 beta
yeah thats unfortunate
Plz riptide fix
Sucks because we used it for a good amount of things
But the instant crashes that take down 2 servers are a no no
Ye and the 1 -1 1 scale just crashed the s3rv3r
I'm probably gonna try to tinker with it into working but I really hope we get a permanent fix soon
I actually forgot to disable it
but it hasn't broken anything so
¯_(ツ)_/¯
Main source was pets, if you changed their role a few times they'd explode
Wtf
yeah someone found that out and decided it'd be funny to do it a few times in a row
machine just completely became unresponsive after the like, 3rd crash
Wow
so I just disabled them for now
Add a time limit
I think I can probably get them stable again but I have bigger fish to fry
nah, that'd be a bandaid
i'm guessing even if you do it with a minute apart it breaks
it wasn't like, multiple role changes a second
Scaling should've just been a sync var on a component in the reference hub, not role based
😭
sweet
Once again, resetting values is what I would expect from role set
Every other value resets
and this one wont
Think about it
Could still be done when initializing the role on the server
and it would run before OnPlayerChangedRole
meaning it really wouldn't affect developers at all
But
If you fixed setting the scale in OnPlayerRoleChanged, at the very least it'll be less of a pain
We can just modify our fake role sync to send a scale update message after the role sync one
- changing this behavior now will break other plugins
But yes the scale msg OnRoleChanged will be fixed
hopefully
fingers crossed
I dont want to promise you anything as
well yea.. sometimes things are not merged instantly
Even something as nasty as this?
Well bug fixes usually are
Especially without any LabAPI change
purely base game PR is merged fast
¯_(ツ)_/¯
I dont decide these things
or dont know about them until I see them on gitlab
or beryl tells me
Well hopefully sooner than later hah
Not only does the server crash but it made our machines completely unresponsive
RAM usage spiked for some reason
When I did the same thing on Host
is caused infinite loop of 2 scale messages being sent again and again
As they were different
that might explain the RAM usage
Berly could make a nuget package :33
But idk what happens on the dedicated
Maybe the role isnt marked as client's?
and it sends the message back to dedicated,
?
Causing the infinite loop
maybe
actually
is the fix fully serverside?
because if so I could just patch it in temporarily while waiting for 14.1.2
I can show you what I did
that would be awesome ^-^
Just copied the role sync to a seperate method, removed it from Update
Actually removed whole Update() method
And put it there
Seems to be working fine
Still waiting for QA
Yippee
But this sends the role message and whatever you set in the RoleChanged at the end of the frame
Wait so the RoleSyncInfoPack will still be used, right?
alright so patch FpcScaleController's ctor to set the backing field, and send the role data immediately instead of on next frame?
Yeah just like on screenshot
sec
harmony's giving me trouble patching the ctor
which is weird
[HarmonyPatch(typeof(FpcScaleController), [typeof(FpcMotor)])]
public static class NWFpcScaleControllerFixes
{
[HarmonyTranspiler]
[HarmonyDebug]
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase method, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator)
.MatchEndForward(
new(OpCodes.Ldarg_0),
new(OpCodes.Call),
new(OpCodes.Call)
)
.Set(OpCodes.Stfld, AccessTools.Field(typeof(FpcScaleController), nameof(FpcScaleController._scale)));
return matcher.InstructionEnumeration();
}
}
this should work
[HarmonyPatch(typeof(FpcScaleController), MethodType.Constructor, typeof(FpcMotor))] did it
weird
IL_000D: ldarg.0
IL_000E: call static UnityEngine.Vector3 UnityEngine.Vector3::get_one()
IL_0013: stfld UnityEngine.Vector3 PlayerRoles.FirstPersonControl.FpcScaleController::_scale
kk this should be good
onto the rest
yea u need to specify constructor
same for enumerators
and uhh Getters and Setters (but those can technically be done by replacing nameof() with set_Method
enumerator can too technically using get targetting method thingy prob
Wait in that scenario isn't OnRoleChanged supposed to be called before SendNewRoleInfo()?
or am I missing something
No its called after you call the send method
alrighty, i'll check if it works once the patches are written
Oh my part of the client now its time to start decomp of sl and rewrite thanks to this piece of code 
IL_008B: call System.Void PlayerRoles.PlayerRoleManager::InitializeNewRole(PlayerRoles.RoleTypeId targetId, PlayerRoles.RoleChangeReason reason, PlayerRoles.RoleSpawnFlags spawnFlags, Mirror.NetworkReader data)
IL_0090: ldarg.0
IL_0091: call static System.Void BrightPlugin.Patches.Fixes.Scale.NWRoleManagerSetRolePatch::SendNewRoleInfo(PlayerRoles.PlayerRoleManager roleManager)
time to test
well
gotta remove all the hacky scaling stuff i did
Wait a second
@unique crane just to be certain, with your changes, that means I don't have to wait at all to send fake role sync right
I can do it in PlayerChangedRole and it'll be received after the real role sync message?
??
Should be
also found out that setting the scale within one frame still crashes the server
bruh
im just joking what i meant by that piece of code we can now fully recreate the client
Gotta fix that
Why do you do transpliers the first time you implement something?
Just do prefix with return false for checking if it works in the first place
takes 3 minutes and I don't have to worry about porting them to transpilers later
but fair
I did do it for Update
i'm gonna make the delay for fake role sync one frame out of precaution
if that works i'll try none
@unique crane can confirm scale works now, kudos
testing fake role sync on same frame
it works
thank you so much
i'm gonna be able to get rid of so many delays
Cant wait to be in 14.1.2.1
Yeah just dont do like
player.Scale = new Vector3(0.5, 0.5, 0.5);
player.Scale = new Vector3(0.51, 0.51, 0.51);
this will still crash the server
that's spooky
Spooky Scary Scale
spooky scare scale message
that shivers down my spine
-# idk the lyrics
Another day thanking God for "Attach unity debugger"
I guess tried to foreach the loop while insufe it?
Another day of putting debug.log everywhere
wouldn't crash like this
the only thing I could see maybe is this being ran on the host player
and if you set it twice in the same frame, the first message and the second message play infinite ping pong
Ye
Lmao
who decided to do that in the constructor
david pressed the "attach plugin devs to problem" button
*attract
Lmao
Many stuff doesn't wanna be fixed i guess
"you and your bright's bullshit"
for providing a very detailed and 100% reproduceable issue
😭
it's a vanilla server too
like this ain't modded at all
and can happen in regular gameplay
Can you check the utc date on those
Thats what happened on Host game, but I dont think it should happen on dedicated?
I guess it does
it's the only thing I could see happening
Hi! How can I check from the DamageHandler if the player died in PocketDimension?
is UniversalDamageHandler
.TranslationId == (translation id of pocket dimension)
(ev.DamageHandler is UniversalDamageHandler universal && universal.TranslationId == DeathTranslations.PocketDecay.Id)
Thanks
d
D
eez
@grand flower Yep
no
I was right?
Infinite loop
at least it wasn't some esoteric bug
But why tf does server receive it again??
Interesting fact: you don't have to run the coroutine every round
dedi player is also the server right
so NetworkServer.active would return true
so when it does .Scale = when receiving the messages
it sends another
i'll apply that to my patches
Exclude server
or idk
Yeah
me when the server is authenticated
I did I just did hub.authManager.InstanceMode is ReadyClient
what if it breaks something niche that the server is supposed to receive 
Hmmm no
the whole game has to be tested now
Glad that is not my job
im guessing he's only doing it for Scale
No I mean
I changed just the scale code
gonna test that locally
And prob do the same for gravity
we don't touch it atm so it's fine
[HarmonyPatch(typeof(FpcScaleController), nameof(FpcScaleController.Scale), MethodType.Setter)]
public static class NWFpcScaleSetterFixes
{
[HarmonyPrefix]
public static bool Prefix(FpcScaleController __instance, Vector3 value)
{
if (value == __instance._scale)
{
return false;
}
__instance._scale = value;
__instance.Hub.transform.localScale = new Vector3(__instance._scale.x, __instance._scale.y, __instance._scale.z);
if (!NetworkServer.active || __instance.Motor.Hub == null)
{
return false;
}
new SyncedScaleMessages.ScaleMessage(__instance._scale, __instance.Hub)
.SendToHubsConditionally(hub => hub.authManager && hub.authManager.InstanceMode == ClientInstanceMode.ReadyClient);
return false;
}
}
wait what I was smoking with the localScale set
uh
oh yeah you can just assign
LOL
yep that works
can assign the scale a billion times now
awesome
static n?
Mini micro nano optimalization of not creating a new delegate object every call
i didnt even know that was possible
me when [HarmonyPrefix]
(extra line)
shock

It may revolt
I'm an Unreal Engine developer
lines don't scare me
the coding standards forbid abbreviations

I very much like Blueprints if you don't use them for gameplay code
The worst thing about working for clients is when they do their gameplay in C++, then Blueprints, which calls C++, which calls 3 different Blueprints
something breaks, I have to hop back and forth between the two and is it exhausting
They're still good for gameplay, but like
UI, stuff that designers wanna do, prototyping
Yeah prototyping
anything that's really the core gameplay you wanna do in C++ otherwise it makes maintenance hell

Alright it's 5 am
I opened the PR for Brights, I sleep
actually fuck forgot something for work bwahaha
fml
Imagine not having afternoon right now
guess i'm sleeping at 6 am
with the way this night's going I'll be there before I sleep
rip
waking up at 8am for meeting 
truly the life
i love the endless perpetual morning standup meetings
PD3 is a spagetti
Pov developers
i wake up at 4 am 
i dont
that is not enough 😭
💀
yea i know
when you develop for american servers
thats what you gonna do
How are you still alive
Ah yes 3 hour sleep is useful for exams right
I would die if I went to my maturita with 3 hours of sleep
nah i mean its useful because i don't feel anything
Wait is it called like that everywhere?
i thought it was called like that only in italy

yea? that comes from latin / italian
Its called maturita in czech republic
fr crazy
ah
it's uh
ok
"érett" = mature
plus a bunch of suffixes
crazy

Well yeah can confirm would die too
After finished my maturita can't really woke up at 8 am
Zh
Is it me, or changing the scale with the new scalefpccontroller when the role is chznged crashes the server?
Yes known
David and Cyn fixed it
Scroll up you see cyns patch
Or wait till 14.1.2 (or 14.1.1.1
)
0.1 delay
Thanks!
Vizsga 
how should i add text to the screen like who is spectating you, what effects you have
player.ShowHint
yYeah was about to suggest https://canary.discord.com/channels/330432627649544202/1375005422624313364 😄
some plugins show the hint their player is experiencing to the spectator which is cook
it may be proprietary
it takes one extension method 
With the new scale module in the fpc thingy, what would be the intended way of getting the fpc thing and then setting a players height?
Im not that well-versed with the things
layer.Scale.y += 0.5; i think
If not works just.
Var lsc = Player.scale;
lsc.y += 0.5;
Player.scale = lsc;
also, be aware of this #plugins-dev-chat message
add a bit of delay if you do it on role change
Oh, that easy? Alright then
The height script for our server was made by someone else and still uses Exiled, but since 14.1.1 we have the issue of players feet being in the ground.....
I hope LabAPIs Player doesnt do that
Yeah happened on our end too
With Exiled or LabAPI?
Might need to tp up after applying high
maybe i add that to ruei :3
atm jumping or falling or anything doesnt fix it. They still have their feet in the ground
Server has both, using the old then new stuff idk which one was broken
I certainly think it was the new .Scale
hmm ill see, thank you
i need to figure out how to support animated hint parameters
wait til hint effects 
wait why wasnt the animation stuff a hint effect 😭
what
there is hint params and hint effects
why wasnt the animation a hint effect? or does it only affect {0} {1} stuff or?
#nullable disable
namespace Hints
{
public class AnimationCurveHintParameter : HintParameter
{
[OriginalAttributes(FieldAttributes.Private)]
public double _offset;
[OriginalAttributes(FieldAttributes.Private)]
public string _format;
[OriginalAttributes(FieldAttributes.Private)]
public bool _integral;
[OriginalAttributes(FieldAttributes.Private)]
public AnimationCurve _curve;
public static AnimationCurveHintParameter FromNetwork(NetworkReader reader)
{
AnimationCurveHintParameter curveHintParameter = new AnimationCurveHintParameter();
curveHintParameter.Deserialize(reader);
return curveHintParameter;
}
public AnimationCurveHintParameter(
double offset,
AnimationCurve curve,
string format,
bool integral)
{
this._offset = offset;
this._curve = curve;
this._format = format;
this._integral = integral;
}
public override void Serialize(NetworkWriter writer)
{
writer.WriteDouble(this._offset);
writer.WriteString(this._format);
writer.WriteBool(this._integral);
writer.WriteAnimationCurve(this._curve);
}
public override void Deserialize(NetworkReader reader)
{
this._offset = reader.ReadDouble();
this._format = reader.ReadString();
this._integral = reader.ReadBool();
this._curve = reader.ReadAnimationCurve();
}
[OriginalAttributes(MethodAttributes.Family)]
public override string UpdateState(float progress)
{
float f = this._curve.Evaluate((float) (NetworkTime.time - this._offset));
return this._integral ? Mathf.RoundToInt(f).ToString(this._format, (IFormatProvider) CultureInfo.InvariantCulture) : f.ToString(this._format, (IFormatProvider) CultureInfo.InvariantCulture);
}
}
}
hint effects are just predefined client sided animation curves
effects also apply to the entire hint which isnt very usefull if you use a hint combiner
so how do animation curve hint providers work?
only replace stuff in string.Format() or?
same as any other param
northwood should pull a sigma and make UI elements networkable
Me putting a 4K Advertisement onto death people screen to buy a "2nd life" pack on patrooon
yeah ok so it replaces {0} and stuff then ok
legit just do the same as any normal param lol
u have to track the progress tho :)
huh
can you show how it works or smth 😭
most things you do new()
what
i did
public override string UpdateState(float progress)
{
float f = this._curve.Evaluate((float) (NetworkTime.time - this._offset));
return this._integral ? Mathf.RoundToInt(f).ToString(this._format, (IFormatProvider) CultureInfo.InvariantCulture) : f.ToString(this._format, (IFormatProvider) CultureInfo.InvariantCulture);
}
no like
it updates state
how to set it up
i assumed this was called on the client
i didnt know you update the state 😭
client does update it
yeah
but if you send a new one
to a player
i highly doubt itll save the old one
cuz what if you want to change it
what if you are sending a completely different one
you should use NetworkTime.time somewhere in the offset if you dont want discontinuities
you can see in the UpdateState that it uses NetworkTime.time as the way to keep everything in sync
Holy Team Fortress 2
imagine the Unity HTML embeds
Uh @unique crane question
The changes you gave me apparently break the black screen
unity rich text isn't html smh
huh
Well Im not referring to rich text, im pretty sure UI has a html embed but idk
And apparently what you gave me breaks that feature
I wonder if I can just like, only make it happen if your new role is spectator
Oookay
networked UI elements would be fire though
me when people start putting ads on their server
so i can spawn a text element using a specific font in a specific spot on a players screen
gonna eat my dinner and then look at it
can already happen 
Theyre too pussy to do it with HSM or Ruei

I would have sold out already and added 5000 Hint ads
what?
🔥
david why r u breaking everything
david as a LabAPI broker 
Let me see if it happens in the branch build
@unique crane it only happens after dying and respawning once
typical nw moment
it was too good to be true
😭
Actually I found much bigger issue
The blackout doesnt go away when you die
?
david what has thy done
Whats wrong with that uh?
@grand flower new idea: Instead of removing the 1 frame delay we move the event to the 1 frame delay
And keep the scale fix ofc
Uh
Hm
Maybe
I'd check if you're still able to get the event to run for when the player disconnects
(Destroyed role)
But that could work
The only downside to this is that changing/changed will now run on different frames
Dunno if that'll break anyone's code
why does giving items in PlayerSpawnedEventArgs not work? I have a log that says that an item should be given to a player but it's not, when it's directly before it
do I need to do Timing.CallDelayed() on this or? 😭
use exiled
no?
yes
i just migrated off of exiled because i dont like it anymore
all my future plugins arent going to use exiled either
there should be a receiving loadout event, use that instead
so lets not say "use exiled instead" whenever someone asks a labapi question, ok?
does that work for class ds even if they dont have a loadout?
ragebait
i would hope so
let's not do that either then, because it's super annoying
lets try and see then
Programmers are getting younger and younger by the day, impressive
lets hope and pray
i would assume they have the empty loadout, since its gets cleared if you do assign loadout through RA
if that makes sense
hmm
yeah
also, is it possible to change the volume of a message via PlayerReceivingVoiceMessageEventArgs?
like only on that specific players side
decode, amplify, encode
do you have the samples?
just the byte[]
you gotta decode that
is there in-game methods for that?
use an OpusDecoder and OpusEncoder
also you're probably gonna have horrible performance by doing so
he means opus decoder and encoder every frame i think
i managed to crash the server (and sometimes clients) with like 10 encoders in parallel
hmm
is there a more direct way to amplify
maybe i need to save the decoded message once it's being sent, and then grab it in the recieve
idk what would be the best method for that tho...
yeah that's better
how would you guys recommend that be done?
Or put them into seperate queue for processing
and sent when they are ready
on seperate thread
ofc
also, can you do this with speaker toys?
wouldnt tank performance then no?
I guess?
scp proximity chat does this
No but there is gonna be slight audio delay
But like
Try it and seeeee
then you should switch to speaker toys and sync vars
nevermind then id rather it be as quick as possible then 😭
me when im legit adding a volume slider for intercom 
?
what would you guys recommend for this fr 😭
different thread for each reciever
decode during sending
or
a different method
i just dont know how id handle decode during sending and then grabbing on recieving
seems quite hard 😭
@unique crane Watcha think about a "PlayerRoleSent" event
considering the data is coming in like that quickly
Called in that Update function after sending the data to the players
That way you don't break the changed event
Although it can be a bit more confusing for devs
Yeah..
maybe...?
hopefully opus supports multiple threads
you also gotta initialize and dispose of the decoder in that thread
simple
how about Awaitables instead
public static Awaitable SendAmplified(VoiceMessage message, List<Player> targets)
{
await Awaitable.BackgroundThreadAsync();
// decode, amplify, encode
await Awaitable.MainThreadAsync();
// send
}
personalizing this is not nice with voice messages
wdym as send? like send to client? isn't that bad on another thread?
await Awaitable.MainThreadAsync();
yeah but you did // send after that
what do i send 😭
ohhhh
you send it back to the main thread
gotcha
public static Awaitable ModifyVolume
make it async
i forgor
smth like this?
do NOT reallocate the buffers 😭
also using OpusEncoder
and decoder
otherwise it looks good :3
so set msg to be a new instance or smth?
it's a ref, no?
you can group by volume
wait so you wanna personalize it?
every client will have a different volume set
yeah
so i want everyone to kind of have a different voice message come out lol
you can't have ref params in async methods
voicemessage is a struct anway
i am not putting a speaker toy in replace of every 079 speaker there is already for intercom 😭
i just wanna control the volume of intercom via server specific settings
that's it
rn ive got a two button setting that lets you mute
works fine
but i wanna make it a volume instead
well intercom does go through 079 speakers right?
no
just make a non-spatial speaker toy
on each player?
this is starting to sound a bit more impossible now 😭
okay
back to this
group the receivers by volume setting (linq has groupby)
decode once for each packet
me when most people will probably have a diffent volume setting 😭
amplify per group
i'd assume some keep it on 1
fair
make it a dropdown with like 5 options 
yes but how would I store this? wont there be like some sort of conflict tryna get from a list or smth?
in the sending event
how
what
uh
no
cancel the event
send the original message to those who have it on 100%
group the rest
now ur confusing me
this sounds like smth for recieving not sending 😭
Is it just the github in #labapi-information ? The docs don't seem to cover all the classes, methods, and datatypes that I imagine we have access to
you have the voice message in sending
cancel the sending event
send the message yourself
what about in proximity chat msgs tho and stuff
scp proximity chat
have you tried
telling the players to stop crying
that would be more ideal with speakers tbf
like
so many have said
"it's too loud"
i disagree
😭
have they paid for your patreon
on your server
if not, silence peasants 
oh i get why it's too loud
cuz it isn't spatial
honestly
make proximity chat with speakers
and see if thedy're happy
the plugin i use does use speakers
lol
sadly it is exiled
as idk a labapi version and im too lazy to code it 😭
me when a player leaving doesn't remove the opush handler
😭
i love memory leaks
wait
this means that this constantly will use more and more memory 😭
wait nvm
wait nvm again
mb
lol
Its not shutting down
Do it
and it isn't chatgpt code
lmao
im too lazy david!
do i speedrun it
and id probably require secretapi for it or smth so that i could make player specific volume ssss stuff
i can stream the speedrun in vc :3
this would be really cool
because idk ssss stuff without secretapi or exiled
and exiled is pretty crap for that stuff 😭
dont speedrun too hard that you forget to patch memory leaks 
i won't mem leak
mhmmmmm
No fun
when stream then 
Player.Inventory.ServerRemoveItem requires a ItemPickupBase, but i only have an Item. How can i use this function if i dont have a Pickup, since it is in their Inventory?
Ohhh, that is what it would "become"
Alright, thank you
also if you have the player i'm pretty sure you could just player.RemoveItem(item)
I tried that but for some reason it leaves a ghost item in my inventory until i update it
what timezone are you in
wha
BST
- Give revolver
- Hold revolver
- player.RemoveItem(revolver.Base)
- Ingame the Revolver gets 'holstered'
- Cant take it back out by clicking it
- Cant drop it by clicking it
- If i pick up a new item like a medkit, the revolver disappears out of my inventory
So like, it gets deleted server side, but not client side, idk
player.RemoveItem and Player.Inventory.ServerRemoveItem are the same, could we see the code you wrote?
Oh i think i accidentally did
player.Inventory.UserInventory.Items.Remove
wups :x
oops
@unique crane about to patch the PlayerRoleChanged event to be in Update() after sendNextFrame
Did you try it yet? If not I'll just let you know how that goes
No I didnt yet
nw moment
@icy knoll you up?
[HarmonyPatch(typeof(PlayerRoleManager), nameof(PlayerRoleManager.Update))]
public static class NWRoleManagerDisableUpdate
{
[HarmonyTranspiler]
[HarmonyDebug]
public static IEnumerable<CodeInstruction> Update_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase method, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator)
.End()
.MatchEndBackwards(new CodeMatch(OpCodes.Ret))
.Advance(-1) // Go behind the ret
.Insert(
new(OpCodes.Ldarg_0),
new(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerRoleManager), nameof(PlayerRoleManager._hub))),
new(OpCodes.Ldloc_1),
new(OpCodes.Ldarg_0),
new(OpCodes.Call, AccessTools.PropertyGetter(typeof(PlayerRoleManager), nameof(PlayerRoleManager.CurrentRole))),
new(OpCodes.Ldarg_2),
new(OpCodes.Ldarg_3),
new(OpCodes.Newobj, AccessTools.Constructor(typeof(PlayerChangedRoleEventArgs),
[typeof(ReferenceHub), typeof(RoleTypeId), typeof(PlayerRoleBase), typeof(RoleChangeReason), typeof(RoleSpawnFlags)])),
new(OpCodes.Call, AccessTools.Method(typeof(PlayerEvents), nameof(PlayerEvents.OnChangedRole)))
);
return matcher.InstructionEnumeration();
}
}
// Removes the call to PlayerEvents.OnChangedRole() to move it to Update.
[HarmonyPatch(typeof(PlayerRoleManager), nameof(PlayerRoleManager.ServerSetRole))]
public static class NWRoleManagerSetRolePatch
{
[HarmonyTranspiler]
[HarmonyDebug]
public static IEnumerable<CodeInstruction> ServerSetRole_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase method, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator)
.MatchEndForward(
new(OpCodes.Ldarg_0),
new(OpCodes.Ldc_I4_1),
new(OpCodes.Stfld, AccessTools.Field(typeof(PlayerRoleManager), nameof(PlayerRoleManager._sendNextFrame)))
)
.Advance(1);
// Removes LabApi.Events.Handlers.PlayerEvents.OnChangedRole(new PlayerChangedRoleEventArgs(this._hub, roleTypeId, this.CurrentRole, reason, spawnFlags));
return matcher
.RemoveInstructions(matcher.Remaining)
.InstructionEnumeration();
}
}
should hopefully work
let's see
ah fuck
can't access the reason
from Update()
fuck it no more transpilers
@rare hinge yo how did u fix the
at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) [0x00186] in <fba24a13802445559d6435422e829b75>:0
at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromFileBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) [0x0003a] in <fba24a13802445559d6435422e829b75>:0
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) [0x00006] in <fba24a13802445559d6435422e829b75>:0```
error?
how i can get path to .config\SCP Secret Laboratory\LabAPI\configs?
from configuration loader or something
PathManager
magic
my evil plan to get people to start using codematchers is working
That is very evil plan
code matcher is peak
[HarmonyPatch(typeof(PlayerRoleManager))]
public static class NWPlayerRoleManagerPatches
{
private static readonly Dictionary<uint, PlayerChangedRoleEventArgs> _pendingEvents = new();
public static void OnChangedRole(PlayerChangedRoleEventArgs args)
{
_pendingEvents.Remove(args.Player.NetworkId);
// Role is destroyed/none, fire immediately.
if (args.NewRole.RoleTypeId is (RoleTypeId.Destroyed or RoleTypeId.None))
{
PlayerEvents.OnChangedRole(args);
return;
}
// Add the event to the player's pending events, which will be used on the next frame.
_pendingEvents[args.Player.NetworkId] = args;
}
public static void FirePendingEvents(ReferenceHub hub)
{
var player = Player.Get(hub);
if (!player.IsValid())
{
return;
}
if (_pendingEvents.TryGetValue(player.NetworkId, out var args))
{
PlayerEvents.OnChangedRole(args);
_pendingEvents.Remove(player.NetworkId);
}
}
[HarmonyPatch(nameof(PlayerRoleManager.Update))]
[HarmonyTranspiler]
[HarmonyDebug]
public static IEnumerable<CodeInstruction> Update_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase method, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator)
.End()
.MatchEndBackwards(new CodeMatch(OpCodes.Ret))
.SetOpcodeAndAdvance(OpCodes.Nop)
.InsertAndAdvance(
new(OpCodes.Ldarg_0),
new(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerRoleManager), nameof(PlayerRoleManager._hub))),
new(OpCodes.Call, AccessTools.Method(typeof(NWPlayerRoleManagerPatches), nameof(FirePendingEvents)))
);
return matcher.InstructionEnumeration();
}
[HarmonyPatch(nameof(PlayerRoleManager.ServerSetRole))]
[HarmonyTranspiler]
[HarmonyDebug]
public static IEnumerable<CodeInstruction> ServerSetRole_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase method, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator)
.MatchEndForward(
new(OpCodes.Ldarg_0),
new(OpCodes.Ldfld),
new(OpCodes.Ldloc_1),
new(OpCodes.Ldarg_0),
new(OpCodes.Call),
new(OpCodes.Ldarg_2),
new(OpCodes.Ldarg_3),
new(OpCodes.Newobj),
new(OpCodes.Call)
)
.SetOperandAndAdvance(AccessTools.Method(typeof(NWPlayerRoleManagerPatches), nameof(OnChangedRole)));
return matcher.InstructionEnumeration();
}
}
trying this
@unique crane so it works
however the first time the player spawns it seems to work differently?
like
hmmm
Everything seems to work fine
the bugs are gone
i'll debug why the scale isn't correct on first spawn
Cyn, is harmony's UnpatchAll removes every patch and not just patches that made with only that assembly?
oh it does?
It removes all
Yes
i think
i might be schizo
how much roughly
I remember that being a bug
I haven't tested personally
Idk tho
I always unregister with the id
idk
oh i think
its cuz harmony.UnPatchAll()
Without supplying an id
you can do this harmony.UnpatchAll(harmony.Id);
Yeah
if you only want to unpatch the ones you applied to that instance
The issue is that when you dont specify id despite it being part of the instance method.. it does all
Idk why
Harmony moment
yeah xD
Nice, ye just wastn sure,
Time to suggest into https://discord.com/channels/330432627649544202/1384288396637110434

shouldve been static method but oh well
now I have a weird bug
ServerSetRole fires PlayerChangedRole
But Update never calls
hmmm
it's if you call Server Set Role inside PlayerRoleChanged
oops
@unique crane Looks like this would solve it, excellent idea
we're gonna put it on our test server and get players to hang out on it a little to make sure it doesn't implode
But tldr what I did was:
- In ServerSetRole, only call
PlayerEvents.OnChangedRoleimmediately if the new role isDestroyedorNone(unsure None is needed but w/e) - If it isn't, hold the changed role args.
- In Update(), after sending the role sync data, if there's a pending event, execute it.
Bonus is you can set the player's position/rotation in PlayerChangedRole now and it works with no delays

[HarmonyPatch(typeof(PlayerRoleManager))]
public static class NWPlayerRoleManagerPatches
{
private static readonly Dictionary<uint, PlayerChangedRoleEventArgs> _pendingEvents = new();
public static void OnChangedRole(PlayerChangedRoleEventArgs args)
{
_pendingEvents.Remove(args.Player.NetworkId);
// Role is destroyed/none, fire immediately.
if (args.NewRole.RoleTypeId is (RoleTypeId.Destroyed or RoleTypeId.None))
{
PlayerEvents.OnChangedRole(args);
return;
}
// Add the event to the player's pending events, which will be used on the next frame.
_pendingEvents[args.Player.NetworkId] = args;
}
public static void FirePendingEvents(ReferenceHub hub)
{
var player = Player.Get(hub);
if (!player.IsValid())
{
return;
}
if (_pendingEvents.TryGetValue(player.NetworkId, out var args))
{
_pendingEvents.Remove(player.NetworkId);
PlayerEvents.OnChangedRole(args);
}
}
[HarmonyPatch(nameof(PlayerRoleManager.Update))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> Update_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase method, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator)
.End()
.MatchEndBackwards(new CodeMatch(OpCodes.Ret))
.SetOpcodeAndAdvance(OpCodes.Nop)
.InsertAndAdvance(
new(OpCodes.Ldarg_0),
new(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerRoleManager), nameof(PlayerRoleManager._hub))),
new(OpCodes.Call, AccessTools.Method(typeof(NWPlayerRoleManagerPatches), nameof(FirePendingEvents)))
);
return matcher.InstructionEnumeration();
}
[HarmonyPatch(nameof(PlayerRoleManager.ServerSetRole))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> ServerSetRole_Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase method, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator)
.MatchEndForward(
new(OpCodes.Ldarg_0),
new(OpCodes.Ldfld),
new(OpCodes.Ldloc_1),
new(OpCodes.Ldarg_0),
new(OpCodes.Call),
new(OpCodes.Ldarg_2),
new(OpCodes.Ldarg_3),
new(OpCodes.Newobj),
new(OpCodes.Call)
)
.SetOperandAndAdvance(AccessTools.Method(typeof(NWPlayerRoleManagerPatches), nameof(OnChangedRole)));
return matcher.InstructionEnumeration();
}
}
Can someone explain where is the rule that prohibits the use of AI generated images ?
It is not really nice to delete 2 posts with plugins without explanation (I could have just deleted the attachment from the topic)
I love discord forums breaking my phone
We don't have an explicit rule against using AI generated art in #server-rules however we generally don't really allow any AI generated art on this server, so for the sake of consistency we've removed your 2 posts, feel free to post them again without the pictures.
What was the problem with asking me to delete the attachment ? And can I use an image not generated by the AI ?
Am I blind or I don't see any mention of AI there
That's what he's saying, there's no such rule
Ah its in the #art-showcase 's Metadata
Or whatever dc calls that
Except that they deleted 2 of my topics from the #1336031121699377213 🫠
Not my issue, I dont use AI for these stuff 
I'm sorry for the inconvenience this may cause (since you have to repost them) but we've decided this way. Feel free to use any images that was not generated by AI, additionally I'd mention that since this is just a 0 warning this just served as notice instead an actual warn.
Wtf is a 0 warning
whys there points
pls explain thanks
yea but whats the points for
well
not what do they do but how are they used
the rules specify amount of warns = punishment, unless im blind i dont see anything related to how the warning points are used
First point just a warning nothing happens, expires after 4 weeks, when you already have a warning and you receive another you are softbanned (kicked and iirc the last day's messages are removed), this expires in 8 weeks, 3rd warning point immediate perma mute by cassie which you need to appeal
Oh
Point as in
oh
😭
Why what did you think?
Like youd give different punishments different amount of points
But instead its literally just a counter of the amount
ye
pog
done 🐟
this is the best plugin of all time
knowyourcoroutines is crazy useful
give me some time to do some Photoshop
how i can disable limit to view?
FogControl
how much?
1
☝️
> 70 meters/units
Whenever teleporting a player to another player that's in an elevator, is there a way to force the teleported player's waypoint to be the elevator's?
that way it doesn't fall through it?
- 0, 0.25
also, is there a way to increase the jump height of SCP-096
Player.Gravity
This doesn't normally happens
When you teleport to someone while in the elevator
yeah that's good
i've managed to call unpatched one time and i was wondering where all the features went 
@icy knoll btw, the SSSS keybind doesn't work whatsoever, no log
-# with secretapi
yeah turns out there was a delay
all good
that feels meh, nvm
this works
wtf 😭
Is there a way I can uh make primitives not shiny
It has this weird stippling effect from reflections that are gross and icky
i think you have z-fighting there
make sure two objects don't exactly overlap
also you can't set the material's metallic or smoothness props
Create a new empty array
Hi dumb
Need to find a way to detect a player being stuck in geometry while their scale is being increased

player collisions are boxes?
there are multiple sphere colliders
but a box would probably suffice
if you wanna make sure, use the player model's hitboxidentities
what do you need
i don't think that's supported atm
you can work around it by creating a symlink
hmmm
guessing I have to use BoxcastAll?
Or is there a layer I can use that only hits the map
i think simply boxcasting will work as it hits anything
ideally you'd only ignore players and items
layermask
are there constants I can use somewhere




