#plugins-dev-chat
1 messages · Page 24 of 1
okay
i am not a fan of that
but oh well
Hey david i have a question regarding toys do you know why when spawning lights with just spawn message its the only toy that doesn’t work at ALL no mirror error or anything
Can you elaborate
hes trying to fake spawn toys on client
and not spawn on server
Or you can invert it
Spawn it for everyone and destroy it one players who shouldnt have it
That should work
are you spawning as initialstate?
No they bug out on the recent update
If you despawn them
And then rejoin the light becomes black
After you write the SyncVar
writer.WriteVector3(this.Position);
writer.WriteQuaternion(this.Rotation);
writer.WriteVector3(this.Scale);
writer.WriteByte(this.MovementSmoothing);
writer.WriteBool(this.IsStatic);
writer.WriteFloat(this.LightIntensity);
writer.WriteFloat(this.LightRange);
writer.WriteColor(this.LightColor);
global::Mirror.GeneratedNetworkCode._Write_UnityEngine.LightShadows(writer, this.ShadowType);
writer.WriteFloat(this.ShadowStrength);
global::Mirror.GeneratedNetworkCode._Write_UnityEngine.LightType(writer, this.LightType);
global::Mirror.GeneratedNetworkCode._Write_UnityEngine.LightShape(writer, this.LightShape);
writer.WriteFloat(this.SpotAngle);
writer.WriteFloat(this.InnerSpotAngle);
writer.WriteUInt(this.ServerParentId(base.transform.parent));
Yes
Im doing all of this
Well since you cause desync
You will have to send it again
Your responsible for that
No but if you connect
Send it
Disconnect
And reconneft
And so it resends it
It bugs out
How so?
Idk
Client throws an error on something
About a dictionary
And a random number
???
show the code for the fakelighttoy spawn
Im not at my pc but this is what happening
Yeah thats gonna help me as much as not telling me about it
Here
94 is the bytes i commented it out the part for testing other stuff
But this is the code i run
And on the bottom the client parent as 0
honestly no idea
i dont even know what msg yo sending so cant reverse that on mirror side
Try assigning a different netId
also how is your syncvar 78 or 94 ?
when i calculate the lighsource has 16383 as SyncVar Dirty bit
I generate it everytime
94

ye but HOW
78 is capybara
adding all syncvar values
Oh wait no i was testing text toys
But yea i will try back
To do it with dirtysncvars
tbh would be easier to edit or patch the sending method to see what basegame wants as bytes
I will be doing that i think
Else i have no idea
anyway the correct dirtySize is 32767 which for writing as compressedvarulong is 3952 as USHORT
hopefully i am right
if not you can hook or write the assembly to show that
Yea rhe size of the syncvar is 94
Client
Tells me
Mirror on the error tells me
Missing 53
Bytes
?
Yes
No errors
No anything
Just doesn’t spawn
Mirror doesn’t scream at me
Its likely something to do on the client
Because similar packet works on primitives
Check client log then
Then how did you come to this conclusion
Because i spawned a server side one and destroyed it
Then i crashed from my own connection that sucks
And rejoining i had a light that was eating other lights and the entire light system was fucked
Because the packet is correct and im sure about that
My theory is it could be checking on network spawned?
Because everything else works except the lights
If you use directional lights you can only have 4 at once
Nope i just had one
Weird
I have an idea on how to make them work, but yea i don’t think it will work
Found no receiver for incoming ClientRpc [48108] on Respawn Effects Controller, the server and client should have the same NetworkBehaviour instances [netId=273].
what the flip
@unique crane ur like smart... right
help ...
i dont understandd :D
it seems desync?
thats the point
but
public static void SendFakeRpcMessage(this Player target, NetworkBehaviour behaviour, Type type, string rpcName, params object[] values)
{
NetworkWriterPooled writer = NetworkWriterPool.Get();
foreach (object obj in values)
writer.Write(obj);
RpcMessage rpcMessage = new()
{
netId = behaviour.netId,
componentIndex = behaviour.ComponentIndex,
functionHash = (ushort)ReflectionExtensions.GetLongFuncName(type, rpcName).GetStableHashCode(),
payload = writer.ToArraySegment(),
};
target.Connection.Send(rpcMessage);
NetworkWriterPool.Return(writer);
}
something here isnt right
48108 is the hashcode
wait thats not right
it should be -31296712
I dont think that ID is actually exists
errrr
so ur code isnt right
for getting hashcode
since it should be -31296712 and not 48108
where tf does mirror determine the hashcode
public static string GetLongFuncName(Type type, MethodInfo method)
{
return $"{method.ReturnType.FullName} {type.FullName}::{method.Name}({string.Join(", ", method.GetParameters().Select(x => x.ParameterType.FullName))})";
}
this is what i GetStableHashCode()
I honestly do not know
private static void OnRPCMessage(RpcMessage message)
{
NetworkIdentity networkIdentity;
if (!NetworkClient.spawned.TryGetValue(message.netId, out networkIdentity))
return;
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
networkIdentity.HandleRemoteCall(message.componentIndex, message.functionHash, RemoteCallType.ClientRpc, (NetworkReader) reader);
}
my bad
net id is correct
where
.
here
public static string GetLongFuncName(Type type, MethodInfo method)
{
return $"{method.ReturnType.FullName} {type.FullName}::{method.Name}({string.Join(",", method.GetParameters().Select(x => x.ParameterType.FullName))})";
}
return $"{method.ReturnType.FullName} {type.FullName}::{method.Name}({string.Join(",", method.GetParameters().Select(x => x.ParameterType.FullName))})";
it works on my testing so
huh
broke deez
Disconnecting connId=0 to prevent exploits from an Exception in MessageHandler: EndOfStreamException ReadBlittable<System.UInt16> not enough data in buffer to read 2 bytes: [ @ 0/0]
at Mirror.NetworkReader.ReadBlittable[T] () [0x00000] in <00000000000000000000000000000000>:0
at Mirror.NetworkReaderExtensions.ReadString (Mirror.NetworkReader reader) [0x00000] in <00000000000000000000000000000000>:0
at Respawning.RespawnEffectsController.InvokeUserCode_RpcCassieAnnouncement__String__Boolean__Boolean__Boolean__String (Mirror.NetworkBehaviour obj, Mirror.NetworkReader reader, Mirror.NetworkConnectionToClient senderConnection) [0x00000] in <00000000000000000000000000000000>:0
at Mirror.NetworkIdentity.HandleRemoteCall (System.Byte componentIndex, System.UInt16 functionHash, Mirror.RemoteCalls.RemoteCallType remoteCallType, Mirror.NetworkReader reader, Mirror.NetworkConnectionToClient senderConnection) [0x00000] in <00000000000000000000000000000000>:0
at Mirror.NetworkClient.OnRPCMessage (Mirror.RpcMessage message) [0x00000] in <00000000000000000000000000000000>:0
at Mirror.NetworkClient+<>c__DisplayClass56_0`1[T].<ReplaceHandler>b__0 (Mirror.NetworkConnection _, T value) [0x00000] in <00000000000000000000000000000000>:0
at Mirror.NetworkMessages+<>c__DisplayClass9_0`2[T,C].<WrapHandler>g__Wrapped|0 (C conn, T msg, System.Int32 _) [0x00000] in <00000000000000000000000000000000>:0
at Mirror.NetworkMessages+<>c__DisplayClass8_0`2[T,C].<WrapHandler>b__0 (Mirror.NetworkConnection conn, Mirror.NetworkReader reader, System.Int32 channelId) [0x00000] in <00000000000000000000000000000000>:0
at Mirror.NetworkClient.UnpackAndInvoke (Mirror.NetworkReader reader, System.Int32 channelId) [0x00000] in <00000000000000000000000000000000>:0
at Mirror.NetworkClient.OnTransportData (System.ArraySegment`1[T] data, System.Int32 channelId) [0x00000] in
and did work
2 Bytes are missing skill issue
errrrr
public static void SendFakeCassieMessage(
this Player target,
string message,
bool isHeld = false,
bool isNoisy = true,
bool isSubtitles = true,
string customSubtitles = "")
{
foreach (RespawnEffectsController allController in RespawnEffectsController.AllControllers)
{
SendFakeRpcMessage(target, allController, typeof(RespawnEffectsController), nameof(RespawnEffectsController.RpcCassieAnnouncement), message, isHeld, isNoisy, isSubtitles, customSubtitles);
}
}
wtf is missing
are you sure u sending msg
public void RpcCassieAnnouncement(
string words,
bool makeHold,
bool makeNoise,
bool customAnnouncement,
string customSubtitles)
{
NetworkWriterPooled writer = NetworkWriterPool.Get();
writer.WriteString(words);
writer.WriteBool(makeHold);
writer.WriteBool(makeNoise);
writer.WriteBool(customAnnouncement);
writer.WriteString(customSubtitles);
this.SendRPCInternal("System.Void Respawning.RespawnEffectsController::RpcCassieAnnouncement(System.String,System.Boolean,System.Boolean,System.Boolean,System.String)", -31296712, (NetworkWriter) writer, 0, true);
NetworkWriterPool.Return(writer);
}
PlayerEvents.ChangedRole += (ev) =>
{
ev.Player.SendFakeCassieMessage("Hi ! Spawn wave !!!");
};
yes
maybe its customsubtitles
cant be empty string..?
idk
it can
seems like your writing is fuckedup
maybe its not arguments but something internal
uint16
also my client didnt notice the disconnect 💀
Dont you need some internal id?
i dont know
i have net id
Oh
[2025-05-19 14:09:55.274 +02:00] [ERROR] [LabApi] 'NullReferenceException' occured while invoking '<Enable>b__21_0' on 'SecretAPI.SecretApi+<>c': 'Object reference not set to an instance of an object.', stack trace:
at UnityEngine.Bindings.ThrowHelper.ThrowNullReferenceException (System.Object obj) [0x00018] in <6869b1608d104370ab4484f8f699b3fc>:0
at UnityEngine.Component.GetComponentFastPath (System.Type type, System.IntPtr oneFurtherThanResultValue) [0x00006] in <6869b1608d104370ab4484f8f699b3fc>:0
at UnityEngine.Component.GetComponent[T] () [0x00021] in <6869b1608d104370ab4484f8f699b3fc>:0
at Mirror.NetworkBehaviour.get_netIdentity () [0x00016] in <d73d070e2abb49cd982556c9f692e950>:0
at Mirror.NetworkBehaviour.get_netId () [0x00000] in <d73d070e2abb49cd982556c9f692e950>:0
at SecretAPI.Extensions.MirrorExtensions.SendFakeRpcMessage (LabApi.Features.Wrappers.Player target, Mirror.NetworkBehaviour behaviour, System.Type type, System.String rpcName, System.Object[] values) [0x00033] in <d15932af09ce4ad086b77f2cf4e54024>:0
oh.
that error wasnt there before
skill issue
[2025-05-19 14:11:56.720 +02:00] [INFO] [SecretAPI] Hi ! Spawn wave !!!
[2025-05-19 14:11:56.736 +02:00] [INFO] [SecretAPI] False
[2025-05-19 14:11:56.753 +02:00] [INFO] [SecretAPI] True
[2025-05-19 14:11:56.769 +02:00] [INFO] [SecretAPI] True
[2025-05-19 14:11:56.784 +02:00] [INFO] [SecretAPI]
[2025-05-19 14:11:56.801 +02:00] [ERROR] [SecretAPI] Mirror.RpcMessage
[2025-05-19 14:11:56.877 +02:00] [INFO] [SecretAPI] Hi ! Spawn wave !!!
[2025-05-19 14:11:56.891 +02:00] [INFO] [SecretAPI] False
[2025-05-19 14:11:56.907 +02:00] [INFO] [SecretAPI] True
[2025-05-19 14:11:56.923 +02:00] [INFO] [SecretAPI] True
[2025-05-19 14:11:56.939 +02:00] [INFO] [SecretAPI]
[2025-05-19 14:11:56.954 +02:00] [ERROR] [SecretAPI] Mirror.RpcMessage
[2025-05-19 14:11:56.970 +02:00] EVE (76561198397744811@steam) disconnected from IP address 127.0.0.1. Last class: Destroyed.
you should skip that something here is null
omfg
teeheeehee
i think exiled has a null check on the cassie controller
announcer wtv
idk
i dont wanna check exiled if thats correct
ill hope so
anyway
uhhh
i still dont know what arg im missing
whats the error saying to u
Disconnecting connId=0 to prevent exploits from an Exception in MessageHandler: EndOfStreamException ReadBlittable<System.UInt16> not enough data in buffer to read 2 bytes: [ @ 0/0]
Is there an event to detect whenever an admin uses a command, with nwapi I used RemoteAdminCommandEvent
maybe try:
rpc message here
using (NetworkWriterPooled networkWriterPooled = NetworkWriterPool.Get())
{
networkWriterPooled.Write<RpcMessage>(rpcMessage);
networkConnectionToClient.Send<RpcMessage>(rpcMessage, 0);
}
i dont write the rpc message into the writer tho
try doing so
wait
i just networkwriter .write it
public static void WriteString(this NetworkWriter writer, string value)
{
if (value == null)
{
writer.WriteUShort((ushort) 0);
}
else
{
int maxByteCount = writer.encoding.GetMaxByteCount(value.Length);
writer.EnsureCapacity(writer.Position + 2 + maxByteCount);
int bytes = writer.encoding.GetBytes(value, 0, value.Length, writer.buffer, writer.Position + 2);
if (bytes > 65534)
throw new IndexOutOfRangeException(string.Format("NetworkWriter.WriteString - Value too long: {0} bytes. Limit: {1} bytes", (object) bytes, (object) (ushort) 65534));
writer.WriteUShort(checked ((ushort) (bytes + 1)));
writer.Position += bytes;
}
}
however
stuff like that
it writes the length
unless i misunderstand
try doing what i suggested
gotta figure out how to use the correct extension for all
ty
ok.
i doubt itd work but ok
wait tf is this gonna do
why would i write the rpc into the networkwriter
¯_(ツ)_/¯
the rpc has the writer
mirror doing it too
not the other way around
no its not
its written into it
then disposed
i think ik the issue is just
we need the length written to it
which we need networkwriterextensions
but i would need a switch for every single type
💔
public static void SendFakeRpcMessage(this Player target, NetworkBehaviour behaviour, Type type, string rpcName, params object[] values)
{
NetworkWriterPooled writer = NetworkWriterPool.Get();
foreach (object obj in values)
writer.Write(obj);
issue starts here im 99% sure
try printing the position after the write
I though that WriteString() does that
public void Write<T>(T value)
{
Action<NetworkWriter, T> write = Writer<T>.write;
if (write == null)
Debug.LogError((object) string.Format("No writer found for {0}. This happens either if you are missing a NetworkWriter extension for your custom type, or if weaving failed. Try to reimport a script to weave again.", (object) typeof (T)));
else
write(this, value);
}
this is what i call
Write()
but if the Writer<T>.write does that then why is NetworkWriterExtensions needed for mirror
public static string ReadString(this NetworkReader reader)
{
ushort num = reader.ReadUShort();
if (num == (ushort) 0)
return (string) null;
ushort count = (ushort) ((uint) num - 1U);
ArraySegment<byte> arraySegment = count <= (ushort) 65534 ? reader.ReadBytesSegment((int) count) : throw new EndOfStreamException(string.Format("NetworkReader.ReadString - Value too long: {0} bytes. Limit is: {1} bytes", (object) count, (object) (ushort) 65534));
return reader.encoding.GetString(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
}
thats what client does
bv:
Writer<string>.write = new Action<NetworkWriter, string>(NetworkWriterExtensions.WriteString);
theres multiple of this
also that could break basegame potentionally
idk
why am i gray
muted
2 differences between me and exiled
exiled checks if playerr is sstill connected
and then has
public static ReadOnlyDictionary<Type, MethodInfo> WriterExtensions
{
get
{
if (WriterExtensionsValue.Count == 0)
{
foreach (MethodInfo method in typeof(NetworkWriterExtensions).GetMethods().Where(x => !x.IsGenericMethod && x.GetCustomAttribute(typeof(ObsoleteAttribute)) == null && (x.GetParameters()?.Length == 2)))
WriterExtensionsValue.Add(method.GetParameters().First(x => x.ParameterType != typeof(NetworkWriter)).ParameterType, method);
Type fuckNorthwood = Assembly.GetAssembly(typeof(RoleTypeId)).GetType("Mirror.GeneratedNetworkCode");
foreach (MethodInfo method in fuckNorthwood.GetMethods().Where(x => !x.IsGenericMethod && (x.GetParameters()?.Length == 2) && (x.ReturnType == typeof(void))))
WriterExtensionsValue.Add(method.GetParameters().First(x => x.ParameterType != typeof(NetworkWriter)).ParameterType, method);
foreach (Type serializer in typeof(ServerConsole).Assembly.GetTypes().Where(x => x.Name.EndsWith("Serializer")))
{
foreach (MethodInfo method in serializer.GetMethods().Where(x => (x.ReturnType == typeof(void)) && x.Name.StartsWith("Write")))
WriterExtensionsValue.Add(method.GetParameters().First(x => x.ParameterType != typeof(NetworkWriter)).ParameterType, method);
}
}
return ReadOnlyWriterExtensionsValue;
}
}
💔
if (target.Connection == null)
return;
thats not the issue tho rn
its the other difference between me and exiled
so i was right
lmao
probably
classic
yeah
ah ye cus it prob try to ser the object
as a type
public void Write<T>(T value)
and when u do its Write<object>(data)
have you ever checked your LALog?
err
im stupid.
[2025-05-19 14:11:56.802 +02:00] [ERROR] [SecretAPI] Mirror.RpcMessage
[2025-05-19 14:11:56.866 +02:00] [STDOUT] No writer found for System.Object. This happens either if you are missing a NetworkWriter extension for your custom type, or if weaving failed. Try to reimport a script to weave again.
[2025-05-19 14:11:56.867 +02:00] [STDOUT] No writer found for System.Object. This happens either if you are missing a NetworkWriter extension for your custom type, or if weaving failed. Try to reimport a script to weave again.
[2025-05-19 14:11:56.867 +02:00] [STDOUT] No writer found for System.Object. This happens either if you are missing a NetworkWriter extension for your custom type, or if weaving failed. Try to reimport a script to weave again.
[2025-05-19 14:11:56.868 +02:00] [STDOUT] No writer found for System.Object. This happens either if you are missing a NetworkWriter extension for your custom type, or if weaving failed. Try to reimport a script to weave again.
[2025-05-19 14:11:56.868 +02:00] [STDOUT] No writer found for System.Object. This happens either if you are missing a NetworkWriter extension for your custom type, or if weaving failed. Try to reimport a script to weave again.
[2025-05-19 14:11:56.877 +02:00] [INFO] [SecretAPI] Hi ! Spawn wave !!!
[2025-05-19 14:11:56.892 +02:00] [INFO] [SecretAPI] False
[2025-05-19 14:11:56.907 +02:00] [INFO] [SecretAPI] True
[2025-05-19 14:11:56.923 +02:00] [INFO] [SecretAPI] True
[2025-05-19 14:11:56.939 +02:00] [INFO] [SecretAPI]
[2025-05-19 14:11:56.954 +02:00] [ERROR] [SecretAPI] Mirror.RpcMessage
[2025-05-19 14:11:56.970 +02:00] EVE (76561198397744811@steam) disconnect
😭
yeah
so its cuz its object
wtf do i do
@thin shuttle do u think i can still exiled mirror extension
well
specifically i wanna steal the static dictionaries
public static ReadOnlyDictionary<Type, MethodInfo> WriterExtensions
or is there another way to do this hmm
yes
NetworkWriterPooled networkWriterPooled = NetworkWriterPool.Get();
foreach (object obj in objects)
{
var GenericType = typeof(Writer<>).MakeGenericType(obj.GetType());
var writer = Activator.CreateInstance(GenericType);
var writeAction = writer.GetType().GetEvent("write");
if (writeAction == null)
{
CL.Warn($"Tried to write type: {obj.GetType()} but has no NetworkWriter!");
return;
}
writeAction.RaiseMethod.Invoke(writer, [networkWriterPooled, obj]);
}
player.Connection.Send(new RpcMessage()
{
netId = networkBehaviour.netId,
componentIndex = networkBehaviour.ComponentIndex,
functionHash = (ushort)functionHash,
payload = networkWriterPooled.ToArraySegment()
});
NetworkWriterPool.Return(networkWriterPooled);
try this
[2025-05-19 14:48:32.267 +02:00] [ERROR] [LabApi] 'MissingMethodException' occured while invoking '<Enable>b__21_0' on 'SecretAPI.SecretApi+<>c': 'Default constructor not found for type Mirror.Writer`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]', stack trace:
its static
might have it
IT WORKS
@restive turret i love you
/p
Type genericType = typeof(Writer<>).MakeGenericType(obj.GetType());
FieldInfo? writeField = genericType.GetField("write", BindingFlags.Static | BindingFlags.Public);
if (writeField == null)
{
Logger.Warn($"Tried to write type: {obj.GetType()} but has no NetworkWriter!");
return;
}
object? writeDelegate = writeField.GetValue(null);
if (writeDelegate is Delegate del)
{
del.DynamicInvoke(writer, obj);
}
else
{
Logger.Warn($"Writer<{obj.GetType()}>.write is not a delegate!");
}
using LabApi.Loader.Features.Plugins;
using LabApi.Events.Handlers;
using System;
using System.Net.Http;
using System.Text;
using LabApi.Events.Arguments.ServerEvents;
namespace Plugins
{
public class AdminWebhookPlugin : Plugin
{
private static readonly HttpClient httpClient = new HttpClient();
private const string WebhookUrl = "";
public override string Name => "Admin Webhook Plugin";
public override string Author => "BorkoAXT";
public override string Description => "Logs admin commands to Discord webhook";
public override Version Version => new Version(0, 0, 1, 0);
public override Version RequiredApiVersion => new Version(3, 0, 0);
public override void Enable()
{
ServerEvents.CommandExecuted += OnPlayerCommand;
}
public override void Disable()
{
ServerEvents.CommandExecuted -= OnPlayerCommand;
}
private void OnPlayerCommand(CommandExecutedEventArgs ev)
{
var adminName = ev.Sender.Nickname;
var command = ev.CommandName;
var time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
var message = $"**Admin command Used**\n👤 **By:** {adminName}\n🔨 **Command:** `{command}`\n⌚ **At:** {time}";
var payload = new
{
content = message
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
_ = httpClient.PostAsync(WebhookUrl, content);
}
}
}
can anyone tell me why this might not work. I tried it and nothing happened but I can't really tell what's wrong
You are too full of hate small and full of hate like chiwawas
WHAT
Im just saying facts
you are hating on the best lib ever for networking

;(
LabAPI register commands before loading Config ?
💀
we have a small bug
even when setting PlayerUnlockingGeneratorEventArgs.IsAllowed = true it doesnt unlock
@obtuse spruce use labapi issues tabn
This:
if (!playerUnlockingGeneratorEventArgs.IsAllowed)
{
flag = false;
}
Should be:
flag = playerUnlockingGeneratorEventArgs.IsAllowed;
ive made a PR
Bro you just adding exiled in your API
Wasn't the goal to prevent an Event when any of the event listeners blocks it?
idk but there should be the ShouldUnlock or smth
Seems like a blocking pattern
Why is another EventHandler currently blocking the event?
what
OOh I know what you want to do, you want a player to be able to open the generator without the correct keycard?
im adding stuff I use
in my own project
well except the mirror stuff
i just wanted to try it
idk if ill even merge it
Since I see events as "if any blocks, then don't do event" pipeline (managing every change state at once would be nightmare) you could just open it manually when event fires
i hope it will be merge https://github.com/northwood-studios/LabAPI/pull/134 🙏
fixed in 14.2
actually
what in sl uses rpc
other than set parent on admin toys and cassie
i cannot remember anything else
tehy use in somewhere
SL have add set parent ????
oh
lmao mirror handle it perfectly ?
its an rpc
it has nothing to do with mirror
you tell game
"pls make this parent"
then it sends it along side a net id
silly goose
well yeah but its for sl to handle
mirror sends the msg
yes
but if it cant do that the game wouldnt work at all
and client goes "oh okay" goes through its list of spawned objects, finds the one with the net id equal to what server said
and sets it
slem do you know what message is being sent to the client for sync vars? always the spawnmessage?
i think its a state message
might be wrong
this maybe
i don't think
im so smart
nvm idk
it actually is
lol
ok i will shut up
How cute u r
very
How can i use Labapi to send a player a console and a RA-console message?
player.SendConsoleMessage();
Thanks, and that is just the regular console iirc right?
Is there something for the RA-console?
target.ReferenceHub.queryProcessor.SendToClient();
o.o
Thanks ^^"
is there a way to switch off a radio?
im tryna make like a powercut event and it makes radios not work or smthn
I think so, but it doesnt sync to the client very well
public static IEnumerator<float> PlayMusic(string filepath)
{
var speaker = SpeakerToy.Create();
using var vorbis = new VorbisReader(filepath);
var channels = vorbis.Channels;
var samples = new float[vorbis.TotalSamples * channels];
List<float> final = new List<float>();
while(vorbis.ReadSamples(samples, 0, samples.Length) > 0)
{
for (int i = 0; i < samples.Length; i++)
{
final.Add(samples[i]);
}
yield return Timing.WaitForOneFrame;
}
speaker.Play(final.ToArray());
}```
i have no idea
doesnt look like you set the speaker up, you have to be near it to hear the sound. maybe place it next to the player or parent it to the player
dont you need to play the noise every frame with speaker.Play() with the byte array
i got it
labapi wrappers for the speaker toy use a transmitter which handles the encoding
Oh okay
i don't like it though cuz you have to allocate arrays every time you wanna queue a "clip"
for those who are reading entire songs into memory:
what is wrong with you 
ok very strange.
If I disable the collision on a Primitive, the client instantly disconnects
what
Yeah
like
if (!collidable) {
Collider? spawnedCollider = AccessTools.Field(typeof(AdminToys.PrimitiveObjectToy), "_collider").GetValue(spawned) as Collider;
if (spawnedCollider == null) {
Log.Error("Failed to get toy collider");
}
else {
spawnedCollider!.enabled = false;
}
//spawned.Flags = PrimitiveFlags.Visible;
}
This kills the client
primitive.Flags &= ~PrimitiveFlags.Collidable
I want to do that, but that makes RayCasting ignore it as well
does audioplayerapi do better for songs and long clips like that?
well
check how i did it in sloc
it works for me
ummmmm
will do ty
you can also use the plugin 
🥲
.ogg limitation is kinda sad
the users have to convert their file not only to ogg but to 48000Hz mono
so this reads entire thing i assume
new float[reader.TotalSamples * channels]
source engine level limitatjons
kek
i wanna create an audio player api that is more developer-friendly
and doesn't allocate megabytes of RAM
how should a really long file be read then
ideally you'd read and play it in real time with a small buffer size
but right now that's not possible*
-# *with LabAPI or Killers' AudioPlayerApi, unless you do some patching or hacks
technically you can load any amount of audio until you get an OOM 
ud probably have to program it yourseld
yep
i assume its possible though
idk how buffers and streams and stuff work though
i would do it if i could
it's not that difficult but it has some caveats
you should be able to with speaker.play unless im missing something
it requires a sample array
which is not ideal
the developer would have to reuse arrays somehow but it's not easy to tell when a clip has been played
Found out why. Anti exploit disconnects you if any player action causes an exception
At the body of the function, cause I do not have 0Harmony.dll 
AccessTools is from harmony
yyyyeaaaaa
Install the harmonylib nuget reference if you need harmony
you should be able to just compare the duraiton left, since when you are streaming you buffer by a certain amount of time
i just *= 5
is that reliable though?
the transmitter runs in a coroutine sooooo
when do you invoke play for it
whenever there's less than n clips?
This is intentional, also We have a bit cursed setup, we do not use nuget at all
yeah i would like to have a small buffer to avoid allocations pretty much completely
instead of shuffling through a pool of arrays
ok very strange. isTrigger still doesn't work. Still collidable
I do not get it. This worked before
also uhhhhh
this is a bit weird
and the transmit coroutine doesn't get killed when the speaker is destroyed
is that intentional?
x is a referencehub here
yeah but you could use Player.AuthenticatedList
instead of an unverified check and dictionary lookups
do i make a PR

transmitters are separate from the speaker toys themselves, but yeah if all toys with controllerId matching the transmitter are destroyed then we could probably stop the playback on all transmitters targetting that id
thats fine
aight makes sense

does round start trigger PlayerChangeRoleEvent?
it should with the spawn reason RoundStart
^
also what are the events to check when damage are dealt to players, whether that be humans or scps?
i mean if you start typing the name of the type, your IDE should suggest it
How so?
just a lot to tackle without a documentation page not you guys' fault
u know what javadoc sites look like right
something like that would be super helpful
like an api reference, yeah
probably wouldn't be that difficult to auto-generate it but ehh
do you use NuGet?
then you have doc access in your IDE and you can navigate fairly easily
I havent touched Java for 2 years
Oh wait its like that big UI window
AAAH
I know
yes, using Rider but I'm brand new to C# so idrk how it works yet
coming from java with intellij
just like me fr
invoke the "quick documentation" action when your cursor is above the symbol like in IntelliJ
should work if you installed the LabApi reference through NuGet
ive never had to use the quick documentation in intellij...
how did you do that then
did you
did you go to the web-based api reference every time?
😭
i just had it on a second monitor leave me be
interesting choice
this thing is pretty useful
also you can use "go to definition" to decompile classes
which should contain docs if applicable
you can't unload assembly from appdomain so good luck


F
@unique crane i need explanation of why this has been separated in two event ?
what the purpose ?
why not just making one event
Because the Tesla idles before going off
It activates when you're in the room, but doesn't fire until you're in proximity
That's why it's two separate events
doen't need to be that way ?
just make property going on and off depending of your proximity
(by default if it's in range of Idling it's trigger the event)
so the property "IsInIdleRange" is true by default
(ev.DisableTesla is an Exiled thing)
but other than that it's would have been easier to make it in a single event
FYI you can use Player.ReadyList instead of AllHubs
its exiled Player
Yeah
yeah
no worry
i just need to know why NW wanted to put 2 event instead of one that handle both Idling Triggering
Do PlayerLeftEvent and PlayerKickedEvent both trigger when someone is kicked or banned?
because mostly with how nw did make it you will need to register two event to disable a tesla for a player
Kicked shouldn't be call with Ban ?
not sure who made that event, but we could always change it
i need an event that broadly covers every situation a player could disconnect from the server if thats a thing
i have no idea what that would be
yeah because my exiled method goes from
it should
to this
also instead of giving only 1 ReferenceHub as who trigger the tesla give all the player who could have trigger the tesla
(or just don't say who trigger the tesla)
because that would depends on where is Player in Player.List
and for plugin feature is kinda suck / unfair for player
i see
for example if you give a penality to player that make tesla trigger then you can only put it to the player that is in the area & is the higher in Player.List
can you make an issue on the labapi github for it
i will let you make the suggestion for me it's everything i have to said here
erm (in PlayerChangedRoleEventArgs)
not really have time rn
Yeah but also tbf they do different events for things like Player Flipping Coin and Player Flipped Coin
i am handling Exiled Issue rn
Just makes it easier to handle outside cases
A lot of them CAN be condensed but like why
that different that at different time of the event
this two event are done at same time
is not after the event pass
Flipping & Flipped is fair
because something changed
They're same time?
between this two state
I would imagine they would activate different depending on proximity to tesla gate
between PlayerIdling and PlayerTriggering nothing happnened between this two so no reason to separated them
Did you judge it based on walking into the tesla room or spawning in the tesla room?
Like were you intentionally triggering both?
Idling and Triggering should activate at different times based on proximity
i judge it by how code is done
between this two event code do nothing other than check
and do not affect TeslaGate state
PlayerTriggering & PlayerTriggered something happenened between this two so that a good event
This is generally my understandng of how idling vs triggering should be
nothing to do about in game style
Wdym?
is perfect circle but yeah mostly that
Yeah cause it's just basic distance but I was too lazy to draw big circles
I feel like I'm completely missing your point
im looking now and wont the current method execute for each player in range?
I don't see what the issue is with this
They're two separate things
Idling and triggering can happen at the same time, but they can also happen separately
The Information is represented in Pink
So the action is represented in Red
You need one event to handle this because every information can be get before the Action is done
hub is overwrite anyways it's would be first or last depending on how it's done anyways
the state between this two actions isn't important to have an event on it
That's subjective
that not subjective
You could say the same thing with other events like Scp173 Creating Tantrum and SCP173 Created Tantrum but for niche outside cases in plugins the distinction can be useful
that different give me method and i will show you why
You could have it be the same event and have a flag saying whether or not it's creating or created, and call the same event both times, just like what you're proposing with the tesla gate
anyways i thinks Ritide got what i means and why it's actually useless for having two event instead of one
(because nothing happenned between this two action)
Except something can happen between the two actions
no nothing
Idle can trigger without triggering Triggering
Triggering = Idling, Idling =/= Triggiering
i know
that why they are different propperty
nothing happenned they happpened at same time
on client only
you only send packet to client
that tesla get idle/ triggering
I'm confused as to why you say they happen at the same time, because you can trigger Idling separately from Trigger, meaning they can happen at different times
the moment in code is at same time
the update in code
that why i told you to not think as distance
that not the important part
for making event
I NEED EXILED 14.1
just install it ?
It's the same thing for other events too
NOT HAVE IT
there only one event before and one after
that good
Wait what ADDED
on Tesla there two event before and two event after
YAY
That's only if you leave trigger and idle range simultaneously, which won't happen without teleportation
while they could be combine in one event before and one after
they happen simultaneously
just give false if player is too far to trigger Triggering and enough near to respond true if in idle
But they don't? The idling check and triggering check happen at the same time, yes, but this check is repeated to continuely check what range you're in
yeah
'happen at the same time' that the important aprt while making event
you don't need 2 event
for something happening at same time
you only need to give both information and both action possibility to it
But they don't always happen at the same time?????
they do
You can Idle without Triggering, by definition meaning they don't happen at the same time
If one event can trigger without the other, then it merits having its own event
that why propperty with true and false exist
you have the same ability with 1 TriggeringTesla event from
than both event from LabAPI
exiled one is not more restrictive because of being united
Yes, but there is purpose in breaking it up
Yes you could have a boolean stating whether or not you're triggering, and merge it into one event, but you can do that with a lot of other events too
The point in the way they do it is to make it straight-forward and easy for people to handle it
i don't find it easier if for disabling tesla you need to register two event
while for exiled you only need to register one
That's if you're totally disabling tesla
What about people who want it to be able to idle without triggering?
Then you just have to nullify one event, instead of doing and check and then nullifying
i'm with yamato on this one
have 2 arg?
ev.IsAllowed = false only disable for this player
other one will still trigger
Yes I know
Your point is that if people want to handle it separately, they can just use an if statement to check which it is
What about people who want it to be able to idle without triggering?
simple
ev.IsTriggerable = false
^
My point is that you can just keep it separate
ev.IsTriggerable = false;
or
ev.IsInIdleRange = false;
^^^^^^^^
^^^^^^^^
I'm not saying you CAN'T do it your way
I'm saying that the way it is currently is fine
me when i quit sl
i am saying than the actual way is an overcomplicated way and useless event
Just because you can use an if check instead of separate events doesn't make it useless
dev purpose is also to simplify code to the maximum
there is no simplifying
Tbf this implementation already is pretty dumb, and can be simplified while still keeping the events separate
Tbf i prefer old NWAPI implementation for this one
I understand your point, just I disagree
i fully disagreed with overcomplicated code
so it's fine
:)
sure it's work by making more event
Two events isn't overcomplicated, it's just separating workload, but ig that's just difference in opinion
You could argue it's more work to separate events into things like Lunging vs Lunged or Creating vs Created and go through the exact same debate
no like i said that PERFECTLY FINE
Exactly
My point is that the argument you'd make for something like that is almost the exact same as the argument you're making now for condensing these events
no it's not the same
Because you can just use an if statement to distinguish between the two and handle them separately
like i said the difference between what you said and what i said it's what happen in between
Triggering and Idling have nothing between this two
The thing is Creating vs Created can happen at the same time
They can also happen at different times depending on the event
Same thing with tesla gate
Creating
Created have an action going one in between
Not always
Sometimes the Creating event is just used to allow someone to cancel it before created
Except there is
The triggering event being separate allows you to cancel someone triggering it without cancelling idling
thanks lol sorry responded late
yeah action has pass
anyways i need to continue fix for exiled
You CAN condense it
i need to go
Doesn't mean you should
also one event means less allocations less overhead overall (both GC and event invocation)
compared to 2
i also see no benefit in having it twice
anyways now i fix LabAPI tesla Event on Exiled
There is many places where some more parameters would benefit much
can yall implement getters and setters for things like this
like i know why OldRole doesnt have a setter but why doesnt NewRole have either
What event
PlayerChangedRoleEvent
Use Changing
The players role has already been changed in the event ur using
Thus theres no cancelling or modifying it
Only the result
i dont need to modify them, just some consistency would be nice
@buoyant oyster Okay so
Role change is requested
ChangingRole is called with the proper stuff
Based on that, role will be changed
Then ChangedRole will be called with the result
Hurting is before Hurt
You cannot modify Hurt because the damage has already been done in Hurting
i know how this works, thats not what i mean
its a small nitpick anyway its whatever
Ur asking for a setter that shouldnt be there though
the issue is like
Yes getters for Team
NewRole has it because its PlayerRoleBase
OldRole is stored as RoleTypeId because it will be pooled
ah
Ughh I need to publicize mirror?
What for?
I'm just publicizing
I use BepInEx
Yeah
Ya
It just means another step to do every update lmao
Wait quick question
When I change a player's scale, will it update automatically for new people joining, or will I have to send them the message as well?
Itll be auto
Dope
Unless ur trying to fake a scale
But yes it should work fine if ur just doing normal scale
Nah I'm changing the local scale and then updating it
Ye cause with disguising you fake it
So you have to update it for every new join
And every player role change
That's why the superior way to do CISpy is to not fuck with appearance lmao
Just work with the damage handling
I did pretty much that already
I meant the sync of appearance
Works great on testing
On the server I do dev stuff for we used to do CISpy with disguise and people kept noticing inconsitencies in the disguise somehow and were able to figure out who it was
Apparently faking the connection wasn't full-proof or something idk
I only recently started doing dev stuff and I'm completely remaking everything so it'll be different
I can always fasten the Coroutine to sync faster
I think the problem was just that there's slight differences between the team models for different classes so the game would freak out with a couple niche cases
Worked with faking spcs too
Slejm...
Yeah I'm just not gonna fuck with it
Its completely public for that I half used exiled and ported to labapi plus did some more stuff
@hearty shard

I mean I could I'm just not going to I don't really have any reason to go for it
If I do CISpy stuff I can just fuck with damage handler stuff instead
Ye , I dont really wanna fk damage handler
Fair
I already doing it with custom damaging
I think it doesn't even trigger it if its on same team
I forgot i said it tbh
errr
yeah idk
Uh
Better start chomping then
A well done eve steak
easy way to grab the zombie count that displays in the upper right of the screen as 049?
[ERROR] [LabApi] 'MethodAccessException' occured while invoking 'OnPlayerFlippedCoin' on 'SodaPlugin.CoinEventHandler': 'Method Mirror.NetworkServer.SendSpawnMessage(Mirror.NetworkIdentity,Mirror.NetworkConnection)' is inaccessible from method SodaPlugin.SizeHandler.ChangePlayerSize(LabApi.Features.Wrappers.Player,UnityEngine.Vector3)''
Motherfucker
I publicized mirror and tried to use SendSpawnMessage
And it didn't work
did you enable unsafe code
we have all been there
no
I apologize on their behalf
Anyone ever get a bug where a player's set to 0 hp, is a "spectator" but stays in the world
like they're still alive but also they're not
its a desync moment iirc
I dont remember the cause
Havent seen that issue since like a year ago xd
we're having this happen again and again
i think I managed to reduce it but it's like
wtf
does anyone have a specific number for the players FOV? I needs it for math
can the server change the accuracy of a weapon for the player
Is it just me or PlayerEscapingEvent is not called in 14.1
Probably just me
Yeah it was me
I genuinely have no clue what to do lmao
How the fuck am I supposed to do SSSS
Pardon my french
Also wait you're so right now I feel like I just came to a crazy realization
Am I that stupid
it's all coming together
I just had to look at it like this:
Generally the majority of use cases will be made more convenient by combining rather than splitting
Even if it "follows the general pattern" or it makes sense on a surface level to split a lot of these up, you have to ask what's more convenient for a majority of people using it
Does LabAPI have a wrapper to spawn a live grenade
Kind of
TimedGrenadeProjectile.SpawnActive?
Add your SS entries to the array
Make sure you have them added cuz I deleted that line and spent 4h debugging it

Yes
little suggestion but would it be possible to add a damage multiplier parameter to the method?
Damage is based on a curve
ik
had to make my own way of modifying the curve by applying the multiplier to it
just figured it'd be cool as a simple parameter
if there is do tell :O
Oh yeah
Y'know what would be fun
which isn't toooo hard but it's a little bit of a setup
Getting the xml of the game too 
Tbh i found the curve thing but no idea about it's values
Isn't the default curve in the explosion settings
heads up: don't make the mistake of modifying the curve in the grenade prefab
don't ask how I found out
Yeah
Maybe that isn't ideal
Funny
yeah no took me a while to figure out how players were reporting SCPs dying from 5 meters away to one nade, pink candy or jailbird
I think that's a lot
yeah
that sounds fun
yeaaah no
lost my sanity chasing that one
almost started thinking we had an outdated patch corrupting IL or something
Forgot to copy the dll 
How would I check if a Keycard fullfill a set of permissions?
checked that a few times
but the whole "bug would keep happening until a server restart" ended up pointing me towards that direction
Something like this
Or check the details
I should do something like that base labapi
Basically ye that

oohh imagine if you could introduce custom permissions for keycard for more advanced handling
Also dont forget to NOT inlcude single use keycard
If u dont clamp the value you can maybe create a 5,5,5 kc
Tbh no idea if that even would work
I meant like you could create a whole new perm group
Patch the enum
The client won't see it :\
Ah well yeah, don't think that will happen
Also easier to create a custom item wrapper and just handle attributes separately if you want to do it currently, but in the future where more "modding" rather than "plugin" approach exists it would be nice
if we get "modding" approach at all
SCP:SL surf servers 
Also an I the only one or when blackout you don't see anything we scp like prev?
Make the item with primitives also as a first-person model
Won't be visible in the inventory as you'd like but it would have visuals
I've received user reports of this happening
Wha
Funny af and broken
SCPs sometimes loose their night vision
i had it happen a year ago when i turned off lights by sending fake syncvar
Tbh it would be nice to turn off night vision for SCPs
Well you get it basegame
how i can change damage in OnPlayerHurting?
Yeah thanks for having realised it :)
Cast the handler to StandardDamageHandler which had a setter for damage
Why not just hand it over right away?
Make a PR if it's that annoying 
I can't even find what causes the events
You dont need the cause (its basegame)
but what cause events
Idk where its called

You just gotta
Amount
get => damage is Standard standard ? standard.Damage : 0
set
{
if damage is Standard thing
thing.Amount = 5;
}
written on mobile
but yeah its smth along those lines
only internal set
then how
PlayerStats.DealDamage iirc
Though it's irrelevant in the PR's context
again unsafe code 
Tick enable unsafe code
(it sounds scary)
this is not normal always using unsafe code
lol
yes, but it game framework
not third party
Microsoft is using unsafe code a lot
So
As long as you don't write unsafe blocks you will be fine
^
Marshal.As, CollectionsMarshal.AsSpan etc
(^ Not in framework 4.8 lol)
Even strings have unsafe code in them
Would you rather use reflection every time or tick a box once when setting up the project
I used to do reflection a lot but when I realized that publicizing exists:
he sleeping
Transpiler testing 
both will be called if is cheater?
Yesterday my steam session said i played 200 minutes
finally now I played SL more than R6S
Doesn't Cheater send to gmods and Player report to Server?
slavery has occured
cheater is sent to to both
Interesting
Wat 😭
https://cdn.discordapp.com/attachments/1130118580462161943/1374338120874590290/image.png?ex=682daf9d&is=682c5e1d&hm=ba27a1b0c72bfa73a056e3aa3910af6c3610a5b8ec1f5c71ac9f0e5b1db9ba6f&
how can i disable spawn pickups on boxes and other generation moments
make the plugin

What event is dispatched when I interact the the small chamber where the SCPs are in? e.g. 018, etc



