Merge branch 'prefab-redo' of https://github.com/misternebula/quantum-space-buddies into prefab-redo

This commit is contained in:
Mister_Nebula 2022-02-03 09:30:18 +00:00
commit 34e67dad6d
44 changed files with 320 additions and 552 deletions

76
.gitignore vendored
View File

@ -1,20 +1,12 @@
# Created by https://www.gitignore.io/api/visualstudio
# Edit at https://www.gitignore.io/?templates=visualstudio
### VisualStudio ###
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
## ##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
.idea
# User-specific files # User-specific files
*.rsuser *.rsuser
*.suo *.suo
*.user *.user
!*.csproj.user
*.userosscache *.userosscache
*.sln.docstates *.sln.docstates
@ -31,12 +23,14 @@ mono_crash.*
[Rr]eleases/ [Rr]eleases/
x64/ x64/
x86/ x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/ [Aa][Rr][Mm]/
[Aa][Rr][Mm]64/ [Aa][Rr][Mm]64/
bld/ bld/
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
[Ll]og/ [Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory # Visual Studio 2015/2017 cache/options directory
.vs/ .vs/
@ -68,6 +62,9 @@ project.lock.json
project.fragment.lock.json project.fragment.lock.json
artifacts/ artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop # StyleCop
StyleCopReport.xml StyleCopReport.xml
@ -76,6 +73,7 @@ StyleCopReport.xml
*_p.c *_p.c
*_h.h *_h.h
*.ilk *.ilk
*.meta
*.obj *.obj
*.iobj *.iobj
*.pch *.pch
@ -92,6 +90,7 @@ StyleCopReport.xml
*.tmp_proj *.tmp_proj
*_wpftmp.csproj *_wpftmp.csproj
*.log *.log
*.tlog
*.vspscc *.vspscc
*.vssscc *.vssscc
.builds .builds
@ -133,9 +132,6 @@ _ReSharper*/
*.[Rr]e[Ss]harper *.[Rr]e[Ss]harper
*.DotSettings.user *.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in # TeamCity is a build add-in
_TeamCity* _TeamCity*
@ -146,6 +142,11 @@ _TeamCity*
.axoCover/* .axoCover/*
!.axoCover/settings.json !.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results # Visual Studio code coverage results
*.coverage *.coverage
*.coveragexml *.coveragexml
@ -293,6 +294,17 @@ node_modules/
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw *.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output # Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts **/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts
@ -349,24 +361,46 @@ ASALocalRun/
# Local History for Visual Studio # Local History for Visual Studio
.localhistory/ .localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database # BeatPulse healthcheck temp database
healthchecksdb healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017 # Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/ MigrationBackup/
# End of https://www.gitignore.io/api/visualstudio # Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
.idea
# Unecessary asset bundle file # Unecessary asset bundle file
QSB/AssetBundles/AssetBundles* QSB/AssetBundles/AssetBundles*
QSB.csproj.user QSB/AssetBundles/*.manifest
GameAssets/
Chert/
Riebeck/
IgnoreInGithub/
OWML.Config.json
WeavedFiles/QSB.dll
WeavedFiles/QSB.dll.mdb
qsb-unityproject qsb-unityproject
# User specific locations # User specific locations

View File

@ -3,6 +3,6 @@
<PropertyGroup> <PropertyGroup>
<GameDir>C:\Program Files\Epic Games\OuterWilds</GameDir> <GameDir>C:\Program Files\Epic Games\OuterWilds</GameDir>
<OwmlDir>$(AppData)\OuterWildsModManager\OWML</OwmlDir> <OwmlDir>$(AppData)\OuterWildsModManager\OWML</OwmlDir>
<UnityAssetsDir>$(SolutionDir)\qsb-unityproject\Assets</UnityAssetsDir> <UnityAssetsDir>$(SolutionDir)\qsb-unityproject\Assets\DLLs</UnityAssetsDir>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -21,7 +21,7 @@
<PropertyGroup Label="Default Locations" Condition="!Exists('$(DevEnvLoc)')"> <PropertyGroup Label="Default Locations" Condition="!Exists('$(DevEnvLoc)')">
<GameDir>C:\Program Files\Epic Games\OuterWilds</GameDir> <GameDir>C:\Program Files\Epic Games\OuterWilds</GameDir>
<OwmlDir>$(AppData)\OuterWildsModManager\OWML</OwmlDir> <OwmlDir>$(AppData)\OuterWildsModManager\OWML</OwmlDir>
<UnityAssetsDir>$(SolutionDir)\qsb-unityproject\Assets</UnityAssetsDir> <UnityAssetsDir>$(SolutionDir)\qsb-unityproject\Assets\DLLs</UnityAssetsDir>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'"> <ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -4,7 +4,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Mono.Cecil" Version="0.11.4" /> <PackageReference Include="Mono.Cecil" Version="0.11.4" />
<Reference Include="../UnityEngine/UnityEngine.CoreModule.dll"/> <Reference Include="../UnityEngine/UnityEngine.CoreModule.dll" />
<Reference Include="../Mirror/*.dll" /> <Reference Include="../Mirror/*.dll" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -7,14 +7,10 @@ namespace Mirror.Weaver
{ {
public static class Extensions public static class Extensions
{ {
public static bool Is(this TypeReference td, Type t) public static bool Is(this TypeReference td, Type type) =>
{ type.IsGenericType
if (t.IsGenericType) ? td.GetElementType().FullName == type.FullName
{ : td.FullName == type.FullName;
return td.GetElementType().FullName == t.FullName;
}
return td.FullName == t.FullName;
}
public static bool Is<T>(this TypeReference td) => Is(td, typeof(T)); public static bool Is<T>(this TypeReference td) => Is(td, typeof(T));

View File

@ -78,7 +78,9 @@ namespace Mirror.Weaver
*/ */
public static MethodDefinition ProcessCommandInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition method, MethodDefinition cmdCallFunc, ref bool WeavingFailed) public static MethodDefinition ProcessCommandInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition method, MethodDefinition cmdCallFunc, ref bool WeavingFailed)
{ {
MethodDefinition cmd = new MethodDefinition(Weaver.InvokeRpcPrefix + method.Name, string cmdName = Weaver.GenerateMethodName(Weaver.InvokeRpcPrefix, method);
MethodDefinition cmd = new MethodDefinition(cmdName,
MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig,
weaverTypes.Import(typeof(void))); weaverTypes.Import(typeof(void)));

View File

@ -7,32 +7,18 @@ namespace Mirror.Weaver
{ {
const string RpcPrefix = "UserCode_"; const string RpcPrefix = "UserCode_";
// creates a method substitute // For a function like
// For example, if we have this: // [ClientRpc] void RpcTest(int value),
// public void CmdThrust(float thrusting, int spin) // Weaver substitutes the method and moves the code to a new method:
// { // UserCode_RpcTest(int value) <- contains original code
// xxxxx // RpcTest(int value) <- serializes parameters, sends the message
// }
// //
// it will substitute the method and move the code to a new method with a provided name // Note that all the calls to the method remain untouched.
// for example: // FixRemoteCallToBaseMethod replaces them afterwards.
//
// public void CmdTrust(float thrusting, int spin)
// {
// }
//
// public void <newName>(float thrusting, int spin)
// {
// xxxxx
// }
//
// Note that all the calls to the method remain untouched
//
// the original method definition loses all code
// this returns the newly created method with all the user provided code
public static MethodDefinition SubstituteMethod(Logger Log, TypeDefinition td, MethodDefinition md, ref bool WeavingFailed) public static MethodDefinition SubstituteMethod(Logger Log, TypeDefinition td, MethodDefinition md, ref bool WeavingFailed)
{ {
string newName = RpcPrefix + md.Name; string newName = Weaver.GenerateMethodName(RpcPrefix, md);
MethodDefinition cmd = new MethodDefinition(newName, md.Attributes, md.ReturnType); MethodDefinition cmd = new MethodDefinition(newName, md.Attributes, md.ReturnType);
// force the substitute method to be protected. // force the substitute method to be protected.
@ -70,8 +56,16 @@ namespace Mirror.Weaver
return cmd; return cmd;
} }
// Finds and fixes call to base methods within remote calls // For a function like
//For example, changes `base.CmdDoSomething` to `base.CallCmdDoSomething` within `this.CallCmdDoSomething` // [ClientRpc] void RpcTest(int value),
// Weaver substitutes the method and moves the code to a new method:
// UserCode_RpcTest(int value) <- contains original code
// RpcTest(int value) <- serializes parameters, sends the message
//
// FixRemoteCallToBaseMethod replaces all calls to
// RpcTest(value)
// with
// UserCode_RpcTest(value)
public static void FixRemoteCallToBaseMethod(Logger Log, TypeDefinition type, MethodDefinition method, ref bool WeavingFailed) public static void FixRemoteCallToBaseMethod(Logger Log, TypeDefinition type, MethodDefinition method, ref bool WeavingFailed)
{ {
string callName = method.Name; string callName = method.Name;
@ -86,28 +80,43 @@ namespace Mirror.Weaver
foreach (Instruction instruction in method.Body.Instructions) foreach (Instruction instruction in method.Body.Instructions)
{ {
// if call to base.CmdDoSomething within this.CallCmdDoSomething // is this instruction a Call to a method?
if (IsCallToMethod(instruction, out MethodDefinition calledMethod) && // if yes, output the method so we can check it.
calledMethod.Name == baseRemoteCallName) if (IsCallToMethod(instruction, out MethodDefinition calledMethod))
{ {
TypeDefinition baseType = type.BaseType.Resolve(); // when considering if 'calledMethod' is a call to 'method',
MethodDefinition baseMethod = baseType.GetMethodInBaseType(callName); // we originally compared .Name.
//
if (baseMethod == null) // to fix IL2CPP build bugs with overloaded Rpcs, we need to
// generated rpc names like
// RpcTest(string value) => RpcTestString(strig value)
// RpcTest(int value) => RpcTestInt(int value)
// to make them unique.
//
// calledMethod.Name is still "RpcTest", so we need to
// convert this to the generated name as well before comparing.
string calledMethodName_Generated = Weaver.GenerateMethodName("", calledMethod);
if (calledMethodName_Generated == baseRemoteCallName)
{ {
Log.Error($"Could not find base method for {callName}", method); TypeDefinition baseType = type.BaseType.Resolve();
WeavingFailed = true; MethodDefinition baseMethod = baseType.GetMethodInBaseType(callName);
return;
}
if (!baseMethod.IsVirtual) if (baseMethod == null)
{ {
Log.Error($"Could not find base method that was virtual {callName}", method); Log.Error($"Could not find base method for {callName}", method);
WeavingFailed = true; WeavingFailed = true;
return; return;
} }
instruction.Operand = baseMethod; if (!baseMethod.IsVirtual)
{
Log.Error($"Could not find base method that was virtual {callName}", method);
WeavingFailed = true;
return;
}
instruction.Operand = baseMethod;
}
} }
} }
} }

View File

@ -8,10 +8,10 @@ namespace Mirror.Weaver
{ {
public static MethodDefinition ProcessRpcInvoke(WeaverTypes weaverTypes, Writers writers, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed) public static MethodDefinition ProcessRpcInvoke(WeaverTypes weaverTypes, Writers writers, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed)
{ {
MethodDefinition rpc = new MethodDefinition( string rpcName = Weaver.GenerateMethodName(Weaver.InvokeRpcPrefix, md);
Weaver.InvokeRpcPrefix + md.Name,
MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, MethodDefinition rpc = new MethodDefinition(rpcName, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig,
weaverTypes.Import(typeof(void))); weaverTypes.Import(typeof(void)));
ILProcessor worker = rpc.Body.GetILProcessor(); ILProcessor worker = rpc.Body.GetILProcessor();
Instruction label = worker.Create(OpCodes.Nop); Instruction label = worker.Create(OpCodes.Nop);

View File

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
namespace Mirror.Weaver namespace Mirror.Weaver
{ {
@ -148,6 +150,15 @@ namespace Mirror.Weaver
return get; return get;
} }
// for [SyncVar] health, weaver generates
//
// NetworkHealth
// {
// get => health;
// set => GeneratedSyncVarSetter(...)
// }
//
// the setter used to be manually IL generated, but we moved it to C# :)
public MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDefinition fd, string originalName, long dirtyBit, FieldDefinition netFieldId, ref bool WeavingFailed) public MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDefinition fd, string originalName, long dirtyBit, FieldDefinition netFieldId, ref bool WeavingFailed)
{ {
//Create the set method //Create the set method
@ -164,135 +175,92 @@ namespace Mirror.Weaver
// NOTE: SyncVar...Equal functions are static. // NOTE: SyncVar...Equal functions are static.
// don't Emit Ldarg_0 aka 'this'. // don't Emit Ldarg_0 aka 'this'.
// new value to set // call WeaverSyncVarSetter<T>(T value, ref T field, ulong dirtyBit, Action<T, T> OnChanged = null)
worker.Emit(OpCodes.Ldarg_1); // IL_0000: ldarg.0
// IL_0001: ldarg.1
// IL_0002: ldarg.0
// IL_0003: ldflda int32 Mirror.Examples.Tanks.Tank::health
// IL_0008: ldc.i4.1
// IL_0009: conv.i8
// IL_000a: ldnull
// IL_000b: call instance void [Mirror]Mirror.NetworkBehaviour::GeneratedSyncVarSetter<int32>(!!0, !!0&, uint64, class [netstandard]System.Action`2<!!0, !!0>)
// IL_0010: ret
// reference to field to set // 'this.' for the call
// make generic version of SetSyncVar with field type
if (fd.FieldType.Is<UnityEngine.GameObject>())
{
// reference to netId Field to set
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
worker.Emit(OpCodes.Call, weaverTypes.syncVarGameObjectEqualReference);
}
else if (fd.FieldType.Is<NetworkIdentity>())
{
// reference to netId Field to set
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
worker.Emit(OpCodes.Call, weaverTypes.syncVarNetworkIdentityEqualReference);
}
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>())
{
// reference to netId Field to set
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
MethodReference getFunc = weaverTypes.syncVarNetworkBehaviourEqualReference.MakeGeneric(assembly.MainModule, fd.FieldType);
worker.Emit(OpCodes.Call, getFunc);
}
else
{
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, fd);
GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(weaverTypes.syncVarEqualReference);
syncVarEqualGm.GenericArguments.Add(fd.FieldType);
worker.Emit(OpCodes.Call, syncVarEqualGm);
}
worker.Emit(OpCodes.Brtrue, endOfMethod);
// T oldValue = value;
// TODO for GO/NI we need to backup the netId don't we?
VariableDefinition oldValue = new VariableDefinition(fd.FieldType);
set.Body.Variables.Add(oldValue);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, fd);
worker.Emit(OpCodes.Stloc, oldValue);
// this
worker.Emit(OpCodes.Ldarg_0); worker.Emit(OpCodes.Ldarg_0);
// new value to set // first push 'value'
worker.Emit(OpCodes.Ldarg_1); worker.Emit(OpCodes.Ldarg_1);
// reference to field to set // push 'ref T this.field'
worker.Emit(OpCodes.Ldarg_0); worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, fd); worker.Emit(OpCodes.Ldflda, fd);
// dirty bit // push the dirty bit for this SyncVar
// 8 byte integer aka long
worker.Emit(OpCodes.Ldc_I8, dirtyBit); worker.Emit(OpCodes.Ldc_I8, dirtyBit);
// hook?
MethodDefinition hookMethod = GetHookMethod(td, fd, ref WeavingFailed);
if (hookMethod != null)
{
// IL_000a: ldarg.0
// IL_000b: ldftn instance void Mirror.Examples.Tanks.Tank::ExampleHook(int32, int32)
// IL_0011: newobj instance void class [netstandard]System.Action`2<int32, int32>::.ctor(object, native int)
// this.
worker.Emit(OpCodes.Ldarg_0);
// the function
worker.Emit(OpCodes.Ldftn, hookMethod);
// call 'new Action<T,T>()' constructor to convert the function to an action
// we need to make an instance of the generic Action<T,T>.
//
// TODO this allocates a new 'Action' for every SyncVar hook call.
// we should allocate it once and store it somewhere in the future.
// hooks are only called on the client though, so it's not too bad for now.
TypeReference actionRef = assembly.MainModule.ImportReference(typeof(Action<,>));
GenericInstanceType genericInstance = actionRef.MakeGenericInstanceType(fd.FieldType, fd.FieldType);
worker.Emit(OpCodes.Newobj, weaverTypes.ActionT_T.MakeHostInstanceGeneric(assembly.MainModule, genericInstance));
}
// pass 'null' as hook
else worker.Emit(OpCodes.Ldnull);
// call GeneratedSyncVarSetter<T>.
// special cases for GameObject/NetworkIdentity/NetworkBehaviour
// passing netId too for persistence.
if (fd.FieldType.Is<UnityEngine.GameObject>()) if (fd.FieldType.Is<UnityEngine.GameObject>())
{ {
// reference to netId Field to set // GameObject setter needs one more parameter: netId field ref
worker.Emit(OpCodes.Ldarg_0); worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, netFieldId); worker.Emit(OpCodes.Ldflda, netFieldId);
worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarSetter_GameObject);
worker.Emit(OpCodes.Call, weaverTypes.setSyncVarGameObjectReference);
} }
else if (fd.FieldType.Is<NetworkIdentity>()) else if (fd.FieldType.Is<NetworkIdentity>())
{ {
// reference to netId Field to set // NetworkIdentity setter needs one more parameter: netId field ref
worker.Emit(OpCodes.Ldarg_0); worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, netFieldId); worker.Emit(OpCodes.Ldflda, netFieldId);
worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarSetter_NetworkIdentity);
worker.Emit(OpCodes.Call, weaverTypes.setSyncVarNetworkIdentityReference);
} }
// TODO this only uses the persistent netId for types DERIVED FROM NB.
// not if the type is just 'NetworkBehaviour'.
// this is what original implementation did too. fix it after.
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>()) else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>())
{ {
// reference to netId Field to set // NetworkIdentity setter needs one more parameter: netId field ref
// (actually its a NetworkBehaviourSyncVar type)
worker.Emit(OpCodes.Ldarg_0); worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, netFieldId); worker.Emit(OpCodes.Ldflda, netFieldId);
// make generic version of GeneratedSyncVarSetter_NetworkBehaviour<T>
MethodReference getFunc = weaverTypes.setSyncVarNetworkBehaviourReference.MakeGeneric(assembly.MainModule, fd.FieldType); MethodReference getFunc = weaverTypes.generatedSyncVarSetter_NetworkBehaviour_T.MakeGeneric(assembly.MainModule, fd.FieldType);
worker.Emit(OpCodes.Call, getFunc); worker.Emit(OpCodes.Call, getFunc);
} }
else else
{ {
// make generic version of SetSyncVar with field type // make generic version of GeneratedSyncVarSetter<T>
GenericInstanceMethod gm = new GenericInstanceMethod(weaverTypes.setSyncVarReference); MethodReference generic = weaverTypes.generatedSyncVarSetter.MakeGeneric(assembly.MainModule, fd.FieldType);
gm.GenericArguments.Add(fd.FieldType); worker.Emit(OpCodes.Call, generic);
// invoke SetSyncVar
worker.Emit(OpCodes.Call, gm);
}
MethodDefinition hookMethod = GetHookMethod(td, fd, ref WeavingFailed);
if (hookMethod != null)
{
//if (NetworkServer.localClientActive && !getSyncVarHookGuard(dirtyBit))
Instruction label = worker.Create(OpCodes.Nop);
worker.Emit(OpCodes.Call, weaverTypes.NetworkServerGetLocalClientActive);
worker.Emit(OpCodes.Brfalse, label);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldc_I8, dirtyBit);
worker.Emit(OpCodes.Call, weaverTypes.getSyncVarHookGuard);
worker.Emit(OpCodes.Brtrue, label);
// setSyncVarHookGuard(dirtyBit, true);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldc_I8, dirtyBit);
worker.Emit(OpCodes.Ldc_I4_1);
worker.Emit(OpCodes.Call, weaverTypes.setSyncVarHookGuard);
// call hook (oldValue, newValue)
// Generates: OnValueChanged(oldValue, value);
WriteCallHookMethodUsingArgument(worker, hookMethod, oldValue);
// setSyncVarHookGuard(dirtyBit, false);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldc_I8, dirtyBit);
worker.Emit(OpCodes.Ldc_I4_0);
worker.Emit(OpCodes.Call, weaverTypes.setSyncVarHookGuard);
worker.Append(label);
} }
worker.Append(endOfMethod); worker.Append(endOfMethod);
@ -415,11 +383,6 @@ namespace Mirror.Weaver
return (syncVars, syncVarNetIds); return (syncVars, syncVarNetIds);
} }
public void WriteCallHookMethodUsingArgument(ILProcessor worker, MethodDefinition hookMethod, VariableDefinition oldValue)
{
WriteCallHookMethod(worker, hookMethod, oldValue, null);
}
public void WriteCallHookMethodUsingField(ILProcessor worker, MethodDefinition hookMethod, VariableDefinition oldValue, FieldDefinition newValue, ref bool WeavingFailed) public void WriteCallHookMethodUsingField(ILProcessor worker, MethodDefinition hookMethod, VariableDefinition oldValue, FieldDefinition newValue, ref bool WeavingFailed)
{ {
if (newValue == null) if (newValue == null)

View File

@ -15,7 +15,9 @@ namespace Mirror.Weaver
public static MethodDefinition ProcessTargetRpcInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed) public static MethodDefinition ProcessTargetRpcInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed)
{ {
MethodDefinition rpc = new MethodDefinition(Weaver.InvokeRpcPrefix + md.Name, MethodAttributes.Family | string trgName = Weaver.GenerateMethodName(Weaver.InvokeRpcPrefix, md);
MethodDefinition rpc = new MethodDefinition(trgName, MethodAttributes.Family |
MethodAttributes.Static | MethodAttributes.Static |
MethodAttributes.HideBySig, MethodAttributes.HideBySig,
weaverTypes.Import(typeof(void))); weaverTypes.Import(typeof(void)));

View File

@ -1,4 +1,3 @@
using MirrorWeaver;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -32,6 +31,29 @@ namespace Mirror.Weaver
// multi threaded logging. // multi threaded logging.
public Logger Log; public Logger Log;
// remote actions now support overloads,
// -> but IL2CPP doesnt like it when two generated methods
// -> have the same signature,
// -> so, append the signature to the generated method name,
// -> to create a unique name
// Example:
// RpcTeleport(Vector3 position) -> InvokeUserCode_RpcTeleport__Vector3()
// RpcTeleport(Vector3 position, Quaternion rotation) -> InvokeUserCode_RpcTeleport__Vector3Quaternion()
// fixes https://github.com/vis2k/Mirror/issues/3060
public static string GenerateMethodName(string initialPrefix, MethodDefinition md)
{
initialPrefix += md.Name;
for (int i = 0; i < md.Parameters.Count; ++i)
{
// with __ so it's more obvious that this is the parameter suffix.
// otherwise RpcTest(int) => RpcTestInt(int) which is not obvious.
initialPrefix += $"__{md.Parameters[i].ParameterType.Name}";
}
return initialPrefix;
}
public Weaver(Logger Log) public Weaver(Logger Log)
{ {
this.Log = Log; this.Log = Log;
@ -171,7 +193,7 @@ namespace Mirror.Weaver
Stopwatch rwstopwatch = Stopwatch.StartNew(); Stopwatch rwstopwatch = Stopwatch.StartNew();
// Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages // Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages
modified = ReaderWriterProcessor.Process(CurrentAssembly, resolver, Log, writers, readers, ref WeavingFailed); modified = ReaderWriterProcessor.Process(CurrentAssembly, resolver, Log, writers, readers, ref WeavingFailed);
QSBReaderWriterProcessor.Process(CurrentAssembly, writers, readers, ref WeavingFailed); MirrorWeaver.QSBReaderWriterProcessor.Process(CurrentAssembly, writers, readers, ref WeavingFailed);
rwstopwatch.Stop(); rwstopwatch.Stop();
Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds"); Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");

View File

@ -19,7 +19,6 @@ namespace Mirror.Weaver
public MethodReference RemoteCallDelegateConstructor; public MethodReference RemoteCallDelegateConstructor;
public MethodReference NetworkServerGetActive; public MethodReference NetworkServerGetActive;
public MethodReference NetworkServerGetLocalClientActive;
public MethodReference NetworkClientGetActive; public MethodReference NetworkClientGetActive;
// custom attribute types // custom attribute types
@ -28,19 +27,17 @@ namespace Mirror.Weaver
// array segment // array segment
public MethodReference ArraySegmentConstructorReference; public MethodReference ArraySegmentConstructorReference;
// Action<T,T> for SyncVar Hooks
public MethodReference ActionT_T;
// syncvar // syncvar
public MethodReference generatedSyncVarSetter;
public MethodReference generatedSyncVarSetter_GameObject;
public MethodReference generatedSyncVarSetter_NetworkIdentity;
public MethodReference generatedSyncVarSetter_NetworkBehaviour_T;
public MethodReference syncVarEqualReference; public MethodReference syncVarEqualReference;
public MethodReference syncVarNetworkIdentityEqualReference;
public MethodReference syncVarGameObjectEqualReference;
public MethodReference setSyncVarReference;
public MethodReference setSyncVarHookGuard;
public MethodReference getSyncVarHookGuard;
public MethodReference setSyncVarGameObjectReference;
public MethodReference getSyncVarGameObjectReference; public MethodReference getSyncVarGameObjectReference;
public MethodReference setSyncVarNetworkIdentityReference;
public MethodReference getSyncVarNetworkIdentityReference; public MethodReference getSyncVarNetworkIdentityReference;
public MethodReference syncVarNetworkBehaviourEqualReference;
public MethodReference setSyncVarNetworkBehaviourReference;
public MethodReference getSyncVarNetworkBehaviourReference; public MethodReference getSyncVarNetworkBehaviourReference;
public MethodReference registerCommandReference; public MethodReference registerCommandReference;
public MethodReference registerRpcReference; public MethodReference registerRpcReference;
@ -72,9 +69,11 @@ namespace Mirror.Weaver
TypeReference ArraySegmentType = Import(typeof(ArraySegment<>)); TypeReference ArraySegmentType = Import(typeof(ArraySegment<>));
ArraySegmentConstructorReference = Resolvers.ResolveMethod(ArraySegmentType, assembly, Log, ".ctor", ref WeavingFailed); ArraySegmentConstructorReference = Resolvers.ResolveMethod(ArraySegmentType, assembly, Log, ".ctor", ref WeavingFailed);
TypeReference ActionType = Import(typeof(Action<,>));
ActionT_T = Resolvers.ResolveMethod(ActionType, assembly, Log, ".ctor", ref WeavingFailed);
TypeReference NetworkServerType = Import(typeof(NetworkServer)); TypeReference NetworkServerType = Import(typeof(NetworkServer));
NetworkServerGetActive = Resolvers.ResolveMethod(NetworkServerType, assembly, Log, "get_active", ref WeavingFailed); NetworkServerGetActive = Resolvers.ResolveMethod(NetworkServerType, assembly, Log, "get_active", ref WeavingFailed);
NetworkServerGetLocalClientActive = Resolvers.ResolveMethod(NetworkServerType, assembly, Log, "get_localClientActive", ref WeavingFailed);
TypeReference NetworkClientType = Import(typeof(NetworkClient)); TypeReference NetworkClientType = Import(typeof(NetworkClient));
NetworkClientGetActive = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_active", ref WeavingFailed); NetworkClientGetActive = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_active", ref WeavingFailed);
@ -84,7 +83,7 @@ namespace Mirror.Weaver
TypeReference NetworkBehaviourType = Import<NetworkBehaviour>(); TypeReference NetworkBehaviourType = Import<NetworkBehaviour>();
TypeReference RemoteProcedureCallsType = Import(typeof(RemoteCalls.RemoteProcedureCalls)); TypeReference RemoteProcedureCallsType = Import(typeof(RemoteCalls.RemoteProcedureCalls));
TypeReference ScriptableObjectType = Import<UnityEngine.ScriptableObject>(); TypeReference ScriptableObjectType = Import<ScriptableObject>();
ScriptableObjectCreateInstanceMethod = Resolvers.ResolveMethod( ScriptableObjectCreateInstanceMethod = Resolvers.ResolveMethod(
ScriptableObjectType, assembly, Log, ScriptableObjectType, assembly, Log,
@ -98,19 +97,15 @@ namespace Mirror.Weaver
NetworkClientConnectionReference = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_connection", ref WeavingFailed); NetworkClientConnectionReference = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_connection", ref WeavingFailed);
syncVarEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SyncVarEqual", ref WeavingFailed); generatedSyncVarSetter = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter", ref WeavingFailed);
syncVarNetworkIdentityEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SyncVarNetworkIdentityEqual", ref WeavingFailed); generatedSyncVarSetter_GameObject = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter_GameObject", ref WeavingFailed);
syncVarGameObjectEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SyncVarGameObjectEqual", ref WeavingFailed); generatedSyncVarSetter_NetworkIdentity = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter_NetworkIdentity", ref WeavingFailed);
setSyncVarReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SetSyncVar", ref WeavingFailed); generatedSyncVarSetter_NetworkBehaviour_T = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter_NetworkBehaviour", ref WeavingFailed);
setSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SetSyncVarHookGuard", ref WeavingFailed);
getSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarHookGuard", ref WeavingFailed); syncVarEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SyncVarEqual", ref WeavingFailed);
setSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SetSyncVarGameObject", ref WeavingFailed);
getSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarGameObject", ref WeavingFailed); getSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarGameObject", ref WeavingFailed);
setSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SetSyncVarNetworkIdentity", ref WeavingFailed);
getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarNetworkIdentity", ref WeavingFailed); getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarNetworkIdentity", ref WeavingFailed);
syncVarNetworkBehaviourEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SyncVarNetworkBehaviourEqual", ref WeavingFailed);
setSyncVarNetworkBehaviourReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SetSyncVarNetworkBehaviour", ref WeavingFailed);
getSyncVarNetworkBehaviourReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarNetworkBehaviour", ref WeavingFailed); getSyncVarNetworkBehaviourReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarNetworkBehaviour", ref WeavingFailed);
registerCommandReference = Resolvers.ResolveMethod(RemoteProcedureCallsType, assembly, Log, "RegisterCommand", ref WeavingFailed); registerCommandReference = Resolvers.ResolveMethod(RemoteProcedureCallsType, assembly, Log, "RegisterCommand", ref WeavingFailed);

View File

@ -1,7 +1,6 @@
using QSB.Anglerfish.WorldObjects; using QSB.Anglerfish.WorldObjects;
using QSB.AuthoritySync; using QSB.AuthoritySync;
using QSB.Syncs.Unsectored.Rigidbodies; using QSB.Syncs.Unsectored.Rigidbodies;
using QSB.Utility;
using QSB.WorldSync; using QSB.WorldSync;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
@ -54,6 +53,8 @@ namespace QSB.Anglerfish.TransformSync
protected override void Uninit() protected override void Uninit()
{ {
base.Uninit();
if (QSBCore.IsHost) if (QSBCore.IsHost)
{ {
netIdentity.UnregisterAuthQueue(); netIdentity.UnregisterAuthQueue();
@ -61,8 +62,6 @@ namespace QSB.Anglerfish.TransformSync
AttachedRigidbody.OnUnsuspendOWRigidbody -= OnUnsuspend; AttachedRigidbody.OnUnsuspendOWRigidbody -= OnUnsuspend;
AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend; AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend;
base.Uninit();
} }
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.SendAuthQueueMessage(AuthQueueAction.Add); private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.SendAuthQueueMessage(AuthQueueAction.Add);

View File

@ -1,48 +0,0 @@
ManifestFileVersion: 0
CRC: 2158942079
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: d7c4b4eca299ae0206b1a6bfb13a7ba5
TypeTreeHash:
serializedVersion: 2
Hash: 0b6dcb0adf46bff667535938056e8d8d
HashAppended: 0
ClassTypes:
- Class: 1
Script: {instanceID: 0}
- Class: 21
Script: {instanceID: 0}
- Class: 28
Script: {instanceID: 0}
- Class: 48
Script: {instanceID: 0}
- Class: 114
Script: {fileID: 1015169618, guid: 7f3cc24903ed9434188d184e6d0fcc8f, type: 3}
- Class: 114
Script: {fileID: 602583937, guid: 7f3cc24903ed9434188d184e6d0fcc8f, type: 3}
- Class: 114
Script: {fileID: 1980459831, guid: 106784ef860579a438677482e738fed4, type: 3}
- Class: 114
Script: {fileID: 1741964061, guid: 106784ef860579a438677482e738fed4, type: 3}
- Class: 114
Script: {fileID: -765806418, guid: 106784ef860579a438677482e738fed4, type: 3}
- Class: 114
Script: {fileID: 708705254, guid: 106784ef860579a438677482e738fed4, type: 3}
- Class: 115
Script: {instanceID: 0}
- Class: 128
Script: {instanceID: 0}
- Class: 213
Script: {instanceID: 0}
- Class: 222
Script: {instanceID: 0}
- Class: 223
Script: {instanceID: 0}
- Class: 224
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/Prefabs/DialogueBubble.prefab
- Assets/GameAssets/Texture2D/UI_DialogueBox_d.png
Dependencies: []

View File

@ -1,32 +0,0 @@
ManifestFileVersion: 0
CRC: 1531115438
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 69af2ff9e30a3a4e0f059dc00ea13d16
TypeTreeHash:
serializedVersion: 2
Hash: ae2cf77de671e115b4e55d2b65767202
HashAppended: 0
ClassTypes:
- Class: 1
Script: {instanceID: 0}
- Class: 4
Script: {instanceID: 0}
- Class: 21
Script: {instanceID: 0}
- Class: 23
Script: {instanceID: 0}
- Class: 33
Script: {instanceID: 0}
- Class: 43
Script: {instanceID: 0}
- Class: 48
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/Prefabs/Cube.prefab
- Assets/Prefabs/Capsule.prefab
- Assets/Materials/DebugVis.mat
- Assets/Prefabs/Sphere.prefab
Dependencies: []

BIN
QSB/AssetBundles/empty Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,68 +0,0 @@
ManifestFileVersion: 0
CRC: 443713126
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 7d0ca7d72c1b77d3f455afb9deb14138
TypeTreeHash:
serializedVersion: 2
Hash: a1e72967751de663a1cbd29bd1e98be5
HashAppended: 0
ClassTypes:
- Class: 21
Script: {instanceID: 0}
- Class: 28
Script: {instanceID: 0}
- Class: 43
Script: {instanceID: 0}
- Class: 48
Script: {instanceID: 0}
- Class: 74
Script: {instanceID: 0}
- Class: 90
Script: {instanceID: 0}
- Class: 91
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/GameAssets/Texture2D/Traveller_HEA_Chert_ao.png
- Assets/GameAssets/AnimationClip/Riebeck_Playing.anim
- Assets/GameAssets/Avatar/Traveller_HEA_Chert_ANIM_Chatter_ChipperAvatar.asset
- Assets/GameAssets/AnimationClip/Chert_Drum_Panicked.anim
- Assets/GameAssets/Material/Traveller_HEA_Riebeck_mat.mat
- Assets/GameAssets/AnimatorController/Traveller_Chert.controller
- Assets/GameAssets/AnimationClip/Chert_Chatter_Chipper.anim
- Assets/GameAssets/AnimationClip/Chert_Drum_Chipper.anim
- Assets/GameAssets/Mesh/NewDrum_polySurface2.asset
- Assets/GameAssets/AnimationClip/Playing_banjo.anim
- Assets/GameAssets/Texture2D/Traveller_HEA_Riebeck_n.png
- Assets/GameAssets/Avatar/Traveller_HEA_Riebeck_ANIM_TalkingAvatar.asset
- Assets/GameAssets/Texture2D/Structure_HEA_VillageCabin_n.png
- Assets/GameAssets/AnimationClip/Chert_Chatter_Nervous.anim
- Assets/GameAssets/Mesh/Chert_DrumStick_Geo1.asset
- Assets/GameAssets/Material/Structure_HEA_VillageMetal_mat.mat
- Assets/GameAssets/Texture2D/Structure_HEA_VillageCabin_d.png
- Assets/GameAssets/Material/Structure_HEA_VillageCabin_mat.mat
- Assets/GameAssets/Texture2D/Traveller_HEA_Chert_d.png
- Assets/GameAssets/Texture2D/Traveller_HEA_Riebeck_Banjo_n.png
- Assets/GameAssets/AnimationClip/Playing_to_idle.anim
- Assets/GameAssets/Texture2D/Traveller_HEA_Chert_n.png
- Assets/GameAssets/Texture2D/Traveller_HEA_Riebeck_s.png
- Assets/GameAssets/AnimationClip/Chert_Chatter_Panicked.anim
- Assets/GameAssets/Material/Traveller_HEA_Riebeck_Banjo_mat.mat
- Assets/GameAssets/AnimationClip/Chert_Dream.anim
- Assets/GameAssets/AnimationClip/Riebeck_Talking.anim
- Assets/GameAssets/Texture2D/Traveller_HEA_Riebeck_Banjo_d.png
- Assets/GameAssets/AnimationClip/Riebeck_DreamIdle.anim
- Assets/GameAssets/Texture2D/Traveller_HEA_Riebeck_Banjo_ao.png
- Assets/GameAssets/Texture2D/Traveller_HEA_Chert_s.png
- Assets/GameAssets/Texture2D/Structure_HEA_VillageMetal_n.png
- Assets/GameAssets/Texture2D/Traveller_HEA_Riebeck_d.png
- Assets/GameAssets/AnimatorController/Traveller_Riebeck.controller
- Assets/GameAssets/Texture2D/Structure_HEA_VillageMetal_s.png
- Assets/GameAssets/Texture2D/Traveller_HEA_Riebeck_ao.png
- Assets/GameAssets/Texture2D/Structure_HEA_VillageMetal_d.png
- Assets/GameAssets/Texture2D/Traveller_HEA_Riebeck_Banjo_s.png
- Assets/GameAssets/Material/Traveller_HEA_Chert_mat.mat
- Assets/GameAssets/Texture2D/Structure_HEA_VillageCabin_s.png
Dependencies: []

View File

@ -1,17 +0,0 @@
ManifestFileVersion: 0
CRC: 3102539871
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: a82172ddab4ffc78bd7c16996c5f9328
TypeTreeHash:
serializedVersion: 2
Hash: 5ad585dd02dfb5016c0dad519eab8f49
HashAppended: 0
ClassTypes:
- Class: 49
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/TextAssets/GalaxyMap.txt
Dependencies: []

View File

@ -4,15 +4,9 @@ using QSB.EchoesOfTheEye.SlideProjectors.WorldObjects;
using QSB.Messaging; using QSB.Messaging;
using QSB.Patches; using QSB.Patches;
using QSB.Player; using QSB.Player;
using QSB.Utility;
using QSB.WorldSync; using QSB.WorldSync;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace QSB.EchoesOfTheEye.SlideProjectors namespace QSB.EchoesOfTheEye.SlideProjectors.Patches
{ {
internal class ProjectorPatches : QSBPatch internal class ProjectorPatches : QSBPatch
{ {
@ -20,34 +14,26 @@ namespace QSB.EchoesOfTheEye.SlideProjectors
[HarmonyPostfix] [HarmonyPostfix]
[HarmonyPatch(typeof(SlideProjector), nameof(SlideProjector.OnPressInteract))] [HarmonyPatch(typeof(SlideProjector), nameof(SlideProjector.OnPressInteract))]
public static void Interact(SlideProjector __instance) public static void Interact(SlideProjector __instance) =>
{ __instance.GetWorldObject<QSBSlideProjector>()
var worldObject = QSBWorldSync.GetWorldObject<QSBSlideProjector>(__instance); .SendMessage(new ProjectorAuthorityMessage(QSBPlayerManager.LocalPlayerId));
worldObject.SendMessage(new ProjectorAuthorityMessage(QSBPlayerManager.LocalPlayerId));
}
[HarmonyPostfix] [HarmonyPostfix]
[HarmonyPatch(typeof(SlideProjector), nameof(SlideProjector.CancelInteraction))] [HarmonyPatch(typeof(SlideProjector), nameof(SlideProjector.CancelInteraction))]
public static void CancelInteract(SlideProjector __instance) public static void CancelInteract(SlideProjector __instance) =>
{ __instance.GetWorldObject<QSBSlideProjector>()
var worldObject = QSBWorldSync.GetWorldObject<QSBSlideProjector>(__instance); .SendMessage(new ProjectorAuthorityMessage(0));
worldObject.SendMessage(new ProjectorAuthorityMessage(0u));
}
[HarmonyPostfix] [HarmonyPostfix]
[HarmonyPatch(typeof(SlideProjector), nameof(SlideProjector.NextSlide))] [HarmonyPatch(typeof(SlideProjector), nameof(SlideProjector.NextSlide))]
public static void NextSlide(SlideProjector __instance) public static void NextSlide(SlideProjector __instance) =>
{ __instance.GetWorldObject<QSBSlideProjector>()
var worldObject = QSBWorldSync.GetWorldObject<QSBSlideProjector>(__instance); .SendMessage(new NextSlideMessage());
worldObject.SendMessage(new NextSlideMessage());
}
[HarmonyPostfix] [HarmonyPostfix]
[HarmonyPatch(typeof(SlideProjector), nameof(SlideProjector.PreviousSlide))] [HarmonyPatch(typeof(SlideProjector), nameof(SlideProjector.PreviousSlide))]
public static void PreviousSlide(SlideProjector __instance) public static void PreviousSlide(SlideProjector __instance) =>
{ __instance.GetWorldObject<QSBSlideProjector>()
var worldObject = QSBWorldSync.GetWorldObject<QSBSlideProjector>(__instance); .SendMessage(new PreviousSlideMessage());
worldObject.SendMessage(new PreviousSlideMessage());
}
} }
} }

View File

@ -34,7 +34,7 @@ namespace QSB.EchoesOfTheEye.SlideProjectors.WorldObjects
{ {
if (AttachedObject._oneShotSource != null) if (AttachedObject._oneShotSource != null)
{ {
AttachedObject._oneShotSource.PlayOneShot(global::AudioType.Projector_Next, 1f); AttachedObject._oneShotSource.PlayOneShot(AudioType.Projector_Next);
} }
if (AttachedObject.IsProjectorFullyLit()) if (AttachedObject.IsProjectorFullyLit())
@ -62,7 +62,7 @@ namespace QSB.EchoesOfTheEye.SlideProjectors.WorldObjects
{ {
if (AttachedObject._oneShotSource != null) if (AttachedObject._oneShotSource != null)
{ {
AttachedObject._oneShotSource.PlayOneShot(global::AudioType.Projector_Prev, 1f); AttachedObject._oneShotSource.PlayOneShot(AudioType.Projector_Prev);
} }
if (AttachedObject.IsProjectorFullyLit()) if (AttachedObject.IsProjectorFullyLit())

View File

@ -56,6 +56,8 @@ namespace QSB.JellyfishSync.TransformSync
protected override void Uninit() protected override void Uninit()
{ {
base.Uninit();
if (QSBCore.IsHost) if (QSBCore.IsHost)
{ {
netIdentity.UnregisterAuthQueue(); netIdentity.UnregisterAuthQueue();
@ -63,8 +65,6 @@ namespace QSB.JellyfishSync.TransformSync
AttachedRigidbody.OnUnsuspendOWRigidbody -= OnUnsuspend; AttachedRigidbody.OnUnsuspendOWRigidbody -= OnUnsuspend;
AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend; AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend;
base.Uninit();
} }
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.SendAuthQueueMessage(AuthQueueAction.Add); private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.SendAuthQueueMessage(AuthQueueAction.Add);

View File

@ -57,24 +57,16 @@ namespace QSB.OrbSync.TransformSync
protected override void Uninit() protected override void Uninit()
{ {
base.Uninit();
if (QSBCore.IsHost) if (QSBCore.IsHost)
{ {
netIdentity.UnregisterAuthQueue(); netIdentity.UnregisterAuthQueue();
} }
// this is null sometimes on here, but not on other similar transforms syncs (like anglers) var body = AttachedTransform.GetAttachedOWRigidbody();
// idk why, but whatever body.OnUnsuspendOWRigidbody -= OnUnsuspend;
if (AttachedTransform) body.OnSuspendOWRigidbody -= OnSuspend;
{
var body = AttachedTransform.GetAttachedOWRigidbody();
if (body)
{
body.OnUnsuspendOWRigidbody -= OnUnsuspend;
body.OnSuspendOWRigidbody -= OnSuspend;
}
}
base.Uninit();
} }
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.SendAuthQueueMessage(AuthQueueAction.Add); private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.SendAuthQueueMessage(AuthQueueAction.Add);

View File

@ -1,16 +1,10 @@
using OWML.Common; using OWML.Common;
using QSB.Audio;
using QSB.Messaging; using QSB.Messaging;
using QSB.Player.Messages; using QSB.Player.Messages;
using QSB.PlayerBodySetup.Local; using QSB.PlayerBodySetup.Local;
using QSB.PlayerBodySetup.Remote; using QSB.PlayerBodySetup.Remote;
using QSB.RoastingSync;
using QSB.SectorSync;
using QSB.Syncs.Sectored.Transforms; using QSB.Syncs.Sectored.Transforms;
using QSB.Tools;
using QSB.Utility; using QSB.Utility;
using QSB.WorldSync;
using System.Linq;
using UnityEngine; using UnityEngine;
namespace QSB.Player.TransformSync namespace QSB.Player.TransformSync

View File

@ -9,49 +9,22 @@ namespace QSB.PlayerBodySetup.Remote
{ {
public static class FixMaterialsInAllChildren public static class FixMaterialsInAllChildren
{ {
private static List<MaterialDefinition> _materialDefinitions = new(); private static readonly List<(string MaterialName, Material ReplacementMaterial)> _materialDefinitions = new();
static void ReplaceMaterial(Renderer renderer, int index, Material mat) private static void ReplaceMaterial(Renderer renderer, int index, Material mat)
{ {
var mats = renderer.materials; var mats = renderer.materials;
mats[index] = mat; mats[index] = mat;
renderer.materials = mats; renderer.materials = mats;
} }
static void CheckReplaceMaterials(Renderer renderer, string materialName, Material replacementMaterial) private static void ReplaceMaterials(Renderer renderer, string materialName, Material replacementMaterial)
{ {
for (var i = 0; i < renderer.materials.Length; i++) for (var i = 0; i < renderer.materials.Length; i++)
{ {
if (renderer.materials[i].name.Trim() == $"{materialName} (Instance)") if (renderer.materials[i].name.Trim() == $"{materialName} (Instance)")
{ {
ReplaceMaterial(renderer, i, replacementMaterial); ReplaceMaterial(renderer, i, replacementMaterial);
continue;
}
}
}
public static void ReplaceMaterials(Transform rootObject)
{
DebugLog.DebugWrite($"Replace materials on children of {rootObject.name}");
if (_materialDefinitions.Count == 0)
{
try
{
GenerateMaterialDefinitions();
}
catch (Exception ex)
{
DebugLog.ToConsole($"Exception when generating material definitions. {ex}", OWML.Common.MessageType.Error);
return;
}
}
foreach (var renderer in rootObject.GetComponentsInChildren<Renderer>(true))
{
foreach (var def in _materialDefinitions)
{
CheckReplaceMaterials(renderer, def.MaterialName, def.ReplacementMaterial);
} }
} }
} }
@ -70,7 +43,14 @@ namespace QSB.PlayerBodySetup.Remote
foreach (var name in matNameList) foreach (var name in matNameList)
{ {
var matchingMaterial = allMaterials.FirstOrDefault(x => x.name == name); DebugLog.DebugWrite(name);
var matchingMaterial = allMaterials.Where(x => x.name == name).ToArray();
foreach (var item in matchingMaterial)
{
DebugLog.DebugWrite($"- {item.name}");
}
if (matchingMaterial == default) if (matchingMaterial == default)
{ {
@ -78,7 +58,23 @@ namespace QSB.PlayerBodySetup.Remote
return; return;
} }
_materialDefinitions.Add(new(name, matchingMaterial)); _materialDefinitions.Add(new(name, matchingMaterial[0]));
}
}
public static void ReplaceMaterials(Transform rootObject)
{
if (_materialDefinitions.Count == 0)
{
GenerateMaterialDefinitions();
}
foreach (var renderer in rootObject.GetComponentsInChildren<Renderer>(true))
{
foreach (var (materialName, replacementMaterial) in _materialDefinitions)
{
ReplaceMaterials(renderer, materialName, replacementMaterial);
}
} }
} }
} }

View File

@ -1,16 +0,0 @@
using UnityEngine;
namespace QSB.PlayerBodySetup.Remote
{
public struct MaterialDefinition
{
public MaterialDefinition(string materialName, Material replacementMaterial)
{
MaterialName = materialName;
ReplacementMaterial = replacementMaterial;
}
public string MaterialName { get; private set; }
public Material ReplacementMaterial { get; private set; }
}
}

View File

@ -27,7 +27,7 @@ namespace QSB.PlayerBodySetup.Remote
// Variable naming convention is broken here to reflect OW unity project (with REMOTE_ prefixed) for readability // Variable naming convention is broken here to reflect OW unity project (with REMOTE_ prefixed) for readability
var REMOTE_Player_Body = UnityEngine.Object.Instantiate(QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/REMOTE_Player_Body.prefab")); var REMOTE_Player_Body = Object.Instantiate(QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/REMOTE_Player_Body.prefab"));
REMOTE_Player_Body.transform.localPosition = Vector3.zero; REMOTE_Player_Body.transform.localPosition = Vector3.zero;
REMOTE_Player_Body.transform.localScale = Vector3.one; REMOTE_Player_Body.transform.localScale = Vector3.one;
REMOTE_Player_Body.transform.localRotation = Quaternion.identity; REMOTE_Player_Body.transform.localRotation = Quaternion.identity;

View File

@ -6,14 +6,14 @@
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<ProjectGuid>{1F00090A-C697-4C55-B401-192F3CFB9DC2}</ProjectGuid> <ProjectGuid>{1F00090A-C697-4C55-B401-192F3CFB9DC2}</ProjectGuid>
<OutputPath Condition="Exists($(OwmlDir))">$(OwmlDir)\Mods\QSB</OutputPath> <OutputPath Condition="Exists($(OwmlDir))">$(OwmlDir)\Mods\QSB</OutputPath>
<NoWarn>1998</NoWarn> <NoWarn>CS1998;CS0649</NoWarn>
</PropertyGroup> </PropertyGroup>
<Target Name="weave qsb" BeforeTargets="PostBuildEvent"> <Target Name="weave qsb" BeforeTargets="PostBuildEvent">
<Exec Command="&quot;$(SolutionDir)\MirrorWeaver\bin\$(Configuration)\MirrorWeaver&quot; &quot;$(OutputPath)\QSB.dll&quot; &quot;$(SolutionDir)\UnityEngine&quot;" /> <Exec Command="&quot;$(SolutionDir)\MirrorWeaver\bin\$(Configuration)\MirrorWeaver&quot; &quot;$(OutputPath)\QSB.dll&quot; &quot;$(SolutionDir)\UnityEngine&quot;" />
</Target> </Target>
<PropertyGroup> <PropertyGroup>
<PostBuildEvent Condition="Exists($(UnityAssetsDir)) and Exists($(GameDir)) and Exists($(OwmlDir))"> <PostBuildEvent Condition="Exists($(UnityAssetsDir)) and Exists($(GameDir)) and Exists($(OwmlDir))">
copy /y "$(OutputPath)" "$(UnityAssetsDir)" copy /y "$(OutputPath)\*.dll" "$(UnityAssetsDir)"
copy /y "$(GameDir)\OuterWilds_Data\Managed\Assembly-CSharp-firstpass.dll" "$(UnityAssetsDir)" copy /y "$(GameDir)\OuterWilds_Data\Managed\Assembly-CSharp-firstpass.dll" "$(UnityAssetsDir)"
copy /y "$(GameDir)\OuterWilds_Data\Managed\Unity.InputSystem.dll" "$(UnityAssetsDir)" copy /y "$(GameDir)\OuterWilds_Data\Managed\Unity.InputSystem.dll" "$(UnityAssetsDir)"
copy /y "$(GameDir)\OuterWilds_Data\Managed\UnityEngine.UI.dll" "$(UnityAssetsDir)" copy /y "$(GameDir)\OuterWilds_Data\Managed\UnityEngine.UI.dll" "$(UnityAssetsDir)"
@ -22,35 +22,18 @@
copy /y "$(OwmlDir)\Autofac.dll" "$(UnityAssetsDir)" copy /y "$(OwmlDir)\Autofac.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\Newtonsoft.Json.dll" "$(UnityAssetsDir)" copy /y "$(OwmlDir)\Newtonsoft.Json.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\0Harmony.dll" "$(UnityAssetsDir)" copy /y "$(OwmlDir)\0Harmony.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\MonoMod.Utils.dll" "$(UnityAssetsDir)" copy /y "$(OwmlDir)\MonoMod.*.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\MonoMod.RuntimeDetour.dll" "$(UnityAssetsDir)" copy /y "$(OwmlDir)\Mono.Cecil*.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\Mono.Cecil.dll" "$(UnityAssetsDir)" copy /y "$(OwmlDir)\OWML.*.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\Mono.Cecil.Mdb.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\Mono.Cecil.Pdb.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\Mono.Cecil.Rocks.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.Common.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.ModHelper.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.ModHelper.Assets.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.ModHelper.Events.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.ModHelper.Menus.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.ModHelper.Input.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.ModHelper.Interaction.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.Utils.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.Common.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.Logging.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.ModLoader.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.Patcher.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.GameFinder.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\OWML.Abstractions.dll" "$(UnityAssetsDir)"
copy /y "$(OwmlDir)\NAudio-Unity.dll" "$(UnityAssetsDir)" copy /y "$(OwmlDir)\NAudio-Unity.dll" "$(UnityAssetsDir)"
</PostBuildEvent> </PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Include="default-config.json"> <None Include="default-config.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="manifest.json"> <None Include="manifest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -70,7 +53,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="debugsettings.json"> <None Update="debugsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -37,7 +37,7 @@ namespace QSB
{ {
public static IModHelper Helper { get; private set; } public static IModHelper Helper { get; private set; }
public static string DefaultServerIP; public static string DefaultServerIP;
public static AssetBundle NetworkAssetBundle { get; internal set; } public static AssetBundle NetworkAssetBundle { get; private set; }
public static AssetBundle InstrumentAssetBundle { get; private set; } public static AssetBundle InstrumentAssetBundle { get; private set; }
public static AssetBundle ConversationAssetBundle { get; private set; } public static AssetBundle ConversationAssetBundle { get; private set; }
public static AssetBundle DebugAssetBundle { get; private set; } public static AssetBundle DebugAssetBundle { get; private set; }

View File

@ -40,10 +40,9 @@ namespace QSB
public GameObject AnglerPrefab { get; private set; } public GameObject AnglerPrefab { get; private set; }
public GameObject JellyfishPrefab { get; private set; } public GameObject JellyfishPrefab { get; private set; }
public GameObject OccasionalPrefab { get; private set; } public GameObject OccasionalPrefab { get; private set; }
public string PlayerName { get; private set; } private string PlayerName { get; set; }
private const int MaxConnections = 128; private const int MaxConnections = 128;
private const int MaxBufferedPackets = 64;
private GameObject _probePrefab; private GameObject _probePrefab;
private bool _everConnected; private bool _everConnected;
@ -132,14 +131,14 @@ namespace QSB
/// see https://docs.unity3d.com/Manual/AssetBundles-Native.html. /// see https://docs.unity3d.com/Manual/AssetBundles-Native.html.
private static GameObject MakeNewNetworkObject(int assetId, string name, Type transformSyncType) private static GameObject MakeNewNetworkObject(int assetId, string name, Type transformSyncType)
{ {
QSBCore.NetworkAssetBundle.Unload(false); var bundle = QSBCore.Helper.Assets.LoadBundle("AssetBundles/empty");
QSBCore.NetworkAssetBundle = QSBCore.Helper.Assets.LoadBundle("AssetBundles/network"); var template = bundle.LoadAsset<GameObject>("Assets/Prefabs/Empty.prefab");
bundle.Unload(false);
var template = QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/NetworkObject.prefab");
DebugLog.DebugWrite($"MakeNewNetworkObject - prefab id {template.GetInstanceID()} " DebugLog.DebugWrite($"MakeNewNetworkObject - prefab id {template.GetInstanceID()} "
+ $"for {assetId} {name} {transformSyncType.Name}"); + $"for {assetId} {name} {transformSyncType.Name}");
template.name = name; template.name = name;
template.GetRequiredComponent<NetworkIdentity>().SetValue("m_AssetId", assetId.ToGuid().ToString("N")); template.AddComponent<NetworkIdentity>().SetValue("m_AssetId", assetId.ToGuid().ToString("N"));
template.AddComponent(transformSyncType); template.AddComponent(transformSyncType);
return template; return template;
} }

View File

@ -134,7 +134,7 @@ namespace QSB.QuantumSync
public static void UpdateFromDebugSetting() public static void UpdateFromDebugSetting()
{ {
if (QSBCore.DebugSettings.ShowQuantumVisibilityObjects) if (QSBCore.DebugSettings.DrawQuantumVisibilityObjects)
{ {
if (_debugSphere == null) if (_debugSphere == null)
{ {

View File

@ -47,12 +47,6 @@ namespace QSB.Syncs.Sectored.Rigidbodies
_relativeAngularVelocity = reader.ReadVector3(); _relativeAngularVelocity = reader.ReadVector3();
} }
protected override void Uninit()
{
base.Uninit();
AttachedRigidbody = null;
}
protected override void GetFromAttached() protected override void GetFromAttached()
{ {
GetFromSector(); GetFromSector();

View File

@ -164,16 +164,7 @@ namespace QSB.Syncs
protected virtual void Init() protected virtual void Init()
{ {
try AttachedTransform = InitAttachedTransform();
{
AttachedTransform = InitAttachedTransform();
}
catch (Exception ex)
{
DebugLog.ToConsole($"Exception when Init-ing {this} : {ex}", MessageType.Error);
return;
}
IsInitialized = true; IsInitialized = true;
} }
@ -184,8 +175,6 @@ namespace QSB.Syncs
Destroy(AttachedTransform.gameObject); Destroy(AttachedTransform.gameObject);
} }
AttachedTransform = null;
ReferenceTransform = null;
IsInitialized = false; IsInitialized = false;
IsValid = false; IsValid = false;
} }
@ -308,7 +297,7 @@ namespace QSB.Syncs
private void OnGUI() private void OnGUI()
{ {
if (!QSBCore.DebugSettings.ShowDebugLabels if (!QSBCore.DebugSettings.DrawLabels
|| Event.current.type != EventType.Repaint || Event.current.type != EventType.Repaint
|| !IsValid || !IsValid
|| !ReferenceTransform) || !ReferenceTransform)

View File

@ -47,12 +47,6 @@ namespace QSB.Syncs.Unsectored.Rigidbodies
_relativeAngularVelocity = reader.ReadVector3(); _relativeAngularVelocity = reader.ReadVector3();
} }
protected override void Uninit()
{
base.Uninit();
AttachedRigidbody = null;
}
protected override void GetFromAttached() protected override void GetFromAttached()
{ {
transform.position = ReferenceTransform.ToRelPos(AttachedRigidbody.GetPosition()); transform.position = ReferenceTransform.ToRelPos(AttachedRigidbody.GetPosition());

View File

@ -251,7 +251,7 @@ namespace QSB.Utility
private static void DrawWorldObjectLabels() private static void DrawWorldObjectLabels()
{ {
if (!QSBCore.DebugSettings.ShowDebugLabels) if (!QSBCore.DebugSettings.DrawLabels)
{ {
return; return;
} }

View File

@ -9,7 +9,7 @@ namespace QSB.Utility
{ {
public static void ToConsole(string message, MessageType type = MessageType.Message) public static void ToConsole(string message, MessageType type = MessageType.Message)
{ {
if (NetworkClient.localPlayer != null && QSBCore.DebugSettings.PlayerIdInLogs) if (QSBCore.DebugSettings.PlayerIdInLogs && NetworkClient.localPlayer)
{ {
message = $"[{NetworkClient.localPlayer.netId}] " + message; message = $"[{NetworkClient.localPlayer.netId}] " + message;
} }

View File

@ -5,16 +5,16 @@ namespace QSB.Utility
public class DebugSettings public class DebugSettings
{ {
[JsonProperty("useKcpTransport")] [JsonProperty("useKcpTransport")]
public bool UseKcpTransport { get; set; } public bool UseKcpTransport;
[JsonProperty("overrideAppId")] [JsonProperty("overrideAppId")]
public int OverrideAppId { get; set; } = -1; public int OverrideAppId = -1;
[JsonProperty("dumpWorldObjects")] [JsonProperty("dumpWorldObjects")]
public bool DumpWorldObjects { get; set; } public bool DumpWorldObjects;
[JsonProperty("debugMode")] [JsonProperty("debugMode")]
public bool DebugMode { get; set; } public bool DebugMode;
[JsonProperty("drawGui")] [JsonProperty("drawGui")]
private bool _drawGui; private bool _drawGui;
@ -24,13 +24,13 @@ namespace QSB.Utility
private bool _drawLines; private bool _drawLines;
public bool DrawLines => DebugMode && _drawLines; public bool DrawLines => DebugMode && _drawLines;
[JsonProperty("showQuantumVisibilityObjects")] [JsonProperty("drawLabels")]
private bool _showQuantumVisibilityObjects; private bool _drawLabels;
public bool ShowQuantumVisibilityObjects => DebugMode && _showQuantumVisibilityObjects; public bool DrawLabels => DebugMode && _drawLabels;
[JsonProperty("showDebugLabels")] [JsonProperty("drawQuantumVisibilityObjects")]
private bool _showDebugLabels; private bool _drawQuantumVisibilityObjects;
public bool ShowDebugLabels => DebugMode && _showDebugLabels; public bool DrawQuantumVisibilityObjects => DebugMode && _drawQuantumVisibilityObjects;
[JsonProperty("avoidTimeSync")] [JsonProperty("avoidTimeSync")]
private bool _avoidTimeSync; private bool _avoidTimeSync;

View File

@ -1,12 +1,12 @@
{ {
"useKcpTransport": true, "useKcpTransport": true,
"overrideAppId": -1, "overrideAppId": -1,
"dumpWorldObjects": false,
"debugMode": true, "debugMode": true,
"drawGui": true, "drawGui": true,
"drawLines": true, "drawLines": true,
"dumpWorldObjects": false, "drawLabels": false,
"showQuantumVisibilityObjects": false, "drawQuantumVisibilityObjects": false,
"showDebugLabels": false,
"avoidTimeSync": false, "avoidTimeSync": false,
"skipTitleScreen": true, "skipTitleScreen": true,
"greySkybox": false, "greySkybox": false,

View File

@ -4,7 +4,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Update="SteamAPI\*"> <None Update="SteamAPI\*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
</Project> </Project>