Upload from upload_mods.ps1
This commit is contained in:
80
.gitignore
vendored
Normal file
80
.gitignore
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Build and Object Folders
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
|
||||||
|
# Nuget packages directory
|
||||||
|
packages/
|
||||||
|
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
x64/
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
*.ncrunch*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help
|
||||||
|
UpgradeLog*.XML
|
||||||
|
|
||||||
|
# Lightswitch
|
||||||
|
_Pvt_Extensions
|
||||||
|
GeneratedArtifacts
|
||||||
|
*.xap
|
||||||
|
ModelManifest.xml
|
||||||
|
|
||||||
|
#Backup file
|
||||||
|
*.bak
|
||||||
|
|
||||||
|
#zzzili
|
||||||
|
v15/
|
||||||
|
|
||||||
16
CheckStackSize.bat
Normal file
16
CheckStackSize.bat
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
echo off
|
||||||
|
set size=4194304
|
||||||
|
set client=7DaysToDie.exe
|
||||||
|
set dedi=7DaysToDieServer.exe
|
||||||
|
if exist ..\..\%client% (
|
||||||
|
.\editbin.exe /stack:%size% ..\..\%client%
|
||||||
|
echo Setting max stack size for %client% to %size%
|
||||||
|
) ^
|
||||||
|
else if exist ..\..\%dedi% (
|
||||||
|
.\editbin.exe /stack:%size% ..\..\%dedi%
|
||||||
|
echo Setting max stack size for %dedi% to %size%
|
||||||
|
) ^
|
||||||
|
else (
|
||||||
|
echo 7 days to die executable not found!
|
||||||
|
)
|
||||||
|
pause
|
||||||
98
CustomParticleLoader.csproj
Normal file
98
CustomParticleLoader.csproj
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{12A59F51-6655-49D7-BE95-F3E86A173979}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>CustomParticleLoader</RootNamespace>
|
||||||
|
<AssemblyName>CustomParticleLoader</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>.\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>.\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="0Harmony">
|
||||||
|
<HintPath>..\0_TFP_Harmony\0Harmony.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Assembly-CSharp">
|
||||||
|
<HintPath>..\..\7DaysToDie_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="LogLibrary">
|
||||||
|
<HintPath>..\..\7DaysToDie_Data\Managed\LogLibrary.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="UnityEngine">
|
||||||
|
<HintPath>..\..\7DaysToDie_Data\Managed\UnityEngine.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.AnimationModule">
|
||||||
|
<HintPath>..\..\7DaysToDie_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.AssetBundleModule">
|
||||||
|
<HintPath>..\..\7DaysToDie_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.CoreModule">
|
||||||
|
<HintPath>..\..\7DaysToDie_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.PhysicsModule">
|
||||||
|
<HintPath>..\..\7DaysToDie_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Scripts\Core\IExplosionProperty.cs" />
|
||||||
|
<Compile Include="Scripts\MinEventActions\MinEventActionRangedExplosion.cs" />
|
||||||
|
<Compile Include="Scripts\MonoBehaviours\AutoRemove.cs" />
|
||||||
|
<Compile Include="Scripts\Core\ExplosionComponent.cs" />
|
||||||
|
<Compile Include="Scripts\Core\CustomExplosionManager.cs" />
|
||||||
|
<Compile Include="Harmony\Init.cs" />
|
||||||
|
<Compile Include="Harmony\Patches.cs" />
|
||||||
|
<Compile Include="Scripts\NetPackages\NetPackageExplosionParams.cs" />
|
||||||
|
<Compile Include="Scripts\NetPackages\NetPackageExplosionSyncOnConnect.cs" />
|
||||||
|
<Compile Include="Scripts\MonoBehaviours\NetSyncHelper.cs" />
|
||||||
|
<Compile Include="Scripts\MonoBehaviours\ReverseTrackedBehaviour.cs" />
|
||||||
|
<Compile Include="Scripts\MonoBehaviours\Timer.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Scripts\MonoBehaviours\TrackedBehaviour.cs" />
|
||||||
|
<Compile Include="Scripts\MonoBehaviours\TrackedBehaviourBase.cs" />
|
||||||
|
<Compile Include="Scripts\Utilities\PlatformIndependentHash.cs" />
|
||||||
|
<Compile Include="Scripts\Utilities\StreamUtilsCompressed.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="ModInfo.xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
||||||
BIN
CustomParticleLoader.dll
Normal file
BIN
CustomParticleLoader.dll
Normal file
Binary file not shown.
BIN
CustomParticleLoader.pdb
Normal file
BIN
CustomParticleLoader.pdb
Normal file
Binary file not shown.
17
Harmony/Init.cs
Normal file
17
Harmony/Init.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
public class CustomParticleEffectLoaderInit : IModApi
|
||||||
|
{
|
||||||
|
private static bool inited = false;
|
||||||
|
public void InitMod(Mod _modInstance)
|
||||||
|
{
|
||||||
|
if (inited)
|
||||||
|
return;
|
||||||
|
inited = true;
|
||||||
|
Log.Out(" Loading Patch: " + GetType());
|
||||||
|
ModEvents.GameAwake.RegisterHandler(CustomExplosionManager.CreatePropertyParsers);
|
||||||
|
var harmony = new HarmonyLib.Harmony(GetType().ToString());
|
||||||
|
harmony.PatchAll(Assembly.GetExecutingAssembly());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
411
Harmony/Patches.cs
Normal file
411
Harmony/Patches.cs
Normal file
@@ -0,0 +1,411 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(GameManager))]
|
||||||
|
internal class ExplosionEffectPatch
|
||||||
|
{
|
||||||
|
public static void SendCustomExplosionPackage(int _clrIdx, Vector3 _center, Vector3i _blockpos, Quaternion _rotation, ExplosionData _explosionData, int _playerId, ItemValue _itemValueExplosive, List<BlockChangeInfo> _explosionChanges, GameObject result)
|
||||||
|
{
|
||||||
|
uint id = CustomExplosionManager.LastInitializedComponent != null ? CustomExplosionManager.LastInitializedComponent.CurrentExplosionParams._explId : uint.MaxValue;
|
||||||
|
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageExplosionParams>().Setup(_clrIdx, _center, _blockpos, _rotation, _explosionData, _playerId, id, _itemValueExplosive, _explosionChanges, result), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ExplodeState
|
||||||
|
{
|
||||||
|
public bool useCustom;
|
||||||
|
public int playerLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(nameof(GameManager.explode))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static bool explode_Prefix(GameManager __instance, int _clrIdx, Vector3 _worldPos, Vector3i _blockPos, Quaternion _rotation, ExplosionData _explosionData, int _entityId, ItemValue _itemValueExplosionSource, out ExplodeState __state)
|
||||||
|
{
|
||||||
|
__state = new ExplodeState()
|
||||||
|
{
|
||||||
|
useCustom = false,
|
||||||
|
playerLayer = -1,
|
||||||
|
};
|
||||||
|
int index = _explosionData.ParticleIndex;
|
||||||
|
//Log.Out(_worldPos.ToString() + _blockPos.ToString());
|
||||||
|
//Log.Out("Particle index:" + index.ToString());
|
||||||
|
if (index >= WorldStaticData.prefabExplosions.Length)
|
||||||
|
{
|
||||||
|
//Log.Out("Retrieving particle index:" + index.ToString());
|
||||||
|
bool flag = CustomExplosionManager.GetCustomParticleComponents(index, out ExplosionComponent components);
|
||||||
|
if (flag && components != null)
|
||||||
|
{
|
||||||
|
//Log.Out("Retrieved particle index:" + index.ToString());
|
||||||
|
//_explosionData = components.BoundExplosionData;
|
||||||
|
ExplosionValue value = new ExplosionValue()
|
||||||
|
{
|
||||||
|
Component = components,
|
||||||
|
CurrentExplosionParams = new ExplosionParams(_clrIdx, _worldPos, _blockPos, _rotation, _explosionData, _entityId, CustomExplosionManager.NextExplosionIndex++),
|
||||||
|
CurrentItemValue = _itemValueExplosionSource
|
||||||
|
};
|
||||||
|
//Log.Out("params:" + _clrIdx + _blockPos + _playerId + _rotation + _worldPos + _explosionData.ParticleIndex);
|
||||||
|
//Log.Out("params:" + components.CurrentExplosionParams._clrIdx + components.CurrentExplosionParams._blockPos + components.CurrentExplosionParams._playerId + components.CurrentExplosionParams._rotation + components.CurrentExplosionParams._worldPos + components.CurrentExplosionParams._explosionData.ParticleIndex);
|
||||||
|
CustomExplosionManager.PushLastInitComponent(value);
|
||||||
|
__state.useCustom = true;
|
||||||
|
}
|
||||||
|
#if DEBUG
|
||||||
|
else
|
||||||
|
Log.Warning("Failed to retrieve particle on server! Index:" + index.ToString());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
EntityPlayerLocal player = __instance.World.GetPrimaryPlayer();
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
__state.playerLayer = player.GetModelLayer();
|
||||||
|
if (__state.playerLayer != 24)
|
||||||
|
{
|
||||||
|
player.SetModelLayer(24, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__state.playerLayer = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch("explode")]
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
private static IEnumerable<CodeInstruction> explode_Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||||
|
{
|
||||||
|
var codes = new List<CodeInstruction>(instructions);
|
||||||
|
MethodInfo mtd_sendpackage = AccessTools.Method(typeof(ConnectionManager), nameof(ConnectionManager.SendPackage), new Type[] { typeof(NetPackage), typeof(bool), typeof(int), typeof(int), typeof(int), typeof(Vector3?), typeof(int) });
|
||||||
|
|
||||||
|
for (int i = 0, totali = codes.Count; i < totali; i++)
|
||||||
|
{
|
||||||
|
if (codes[i].opcode == OpCodes.Callvirt && codes[i].Calls(mtd_sendpackage))
|
||||||
|
{
|
||||||
|
codes.InsertRange(i + 1, new CodeInstruction[]
|
||||||
|
{
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_1),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_2),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_3),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg, 4),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg, 5),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg, 6),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg, 7),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_0),
|
||||||
|
CodeInstruction.LoadField(typeof(GameManager), nameof(GameManager.tempExplPositions)),
|
||||||
|
new CodeInstruction(OpCodes.Ldloc_1),
|
||||||
|
CodeInstruction.Call(typeof(ExplosionEffectPatch), nameof(SendCustomExplosionPackage))
|
||||||
|
});
|
||||||
|
codes.RemoveRange(i - 26, 27);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(nameof(GameManager.explode))]
|
||||||
|
[HarmonyPostfix]
|
||||||
|
private static void explode_Postfix(GameManager __instance, ExplodeState __state)
|
||||||
|
{
|
||||||
|
if (__state.playerLayer >= 0)
|
||||||
|
{
|
||||||
|
__instance.World.GetPrimaryPlayer().SetModelLayer(__state.playerLayer, false);
|
||||||
|
}
|
||||||
|
if (!__state.useCustom)
|
||||||
|
return;
|
||||||
|
CustomExplosionManager.PopLastInitComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(nameof(GameManager.ExplosionClient))]
|
||||||
|
[HarmonyPostfix]
|
||||||
|
private static void ExplosionClient_Postfix(GameManager __instance, ref GameObject __result, Vector3 _center, Quaternion _rotation, int _index, int _blastPower, float _blastRadius)
|
||||||
|
{
|
||||||
|
if (__result != null || __instance.World == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ExplosionValue components = CustomExplosionManager.LastInitializedComponent;
|
||||||
|
//sorcery uses index over 20 to trigger explosion without particle and spawn visual particle on its own,
|
||||||
|
//such usage could potentially break the chained explosion stack, thus this additional check is added.
|
||||||
|
//invalid explosion component is not pushed to the stack, if index param does not match index on the stack,
|
||||||
|
//then the param must be invalid, skip particle creation.
|
||||||
|
if (components != null && components.CurrentExplosionParams._explosionData.ParticleIndex == _index)
|
||||||
|
{
|
||||||
|
ApplyExplosionForce.Explode(_center, (float)_blastPower, _blastRadius);
|
||||||
|
__result = CustomExplosionManager.InitializeParticle(components.Component, _center - Origin.position, _rotation);
|
||||||
|
}
|
||||||
|
#if DEBUG
|
||||||
|
else
|
||||||
|
Log.Warning("Failed to retrieve particle on client! Index:" + _index.ToString());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(nameof(GameManager.SaveAndCleanupWorld))]
|
||||||
|
[HarmonyPostfix]
|
||||||
|
private static void SaveAndCleanupWorld_Postfix()
|
||||||
|
{
|
||||||
|
CustomExplosionManager.OnCleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
[HarmonyPatch(nameof(GameManager.PlayerSpawnedInWorld))]
|
||||||
|
[HarmonyPostfix]
|
||||||
|
private static void PlayerSpawnedInWorld_Postfix(ClientInfo _cInfo, RespawnType _respawnReason)
|
||||||
|
{
|
||||||
|
if(SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer && _cInfo != null && _cInfo.entityId != -1 && (_respawnReason == RespawnType.EnterMultiplayer || _respawnReason == RespawnType.JoinMultiplayer))
|
||||||
|
CustomParticleEffectLoader.OnClientConnected(_cInfo);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(NetEntityDistribution), nameof(NetEntityDistribution.Add), new Type[] { typeof(Entity) })]
|
||||||
|
internal class ExplosionSyncPatch
|
||||||
|
{
|
||||||
|
private static void Postfix(Entity _e)
|
||||||
|
{
|
||||||
|
if (_e is EntityPlayer)
|
||||||
|
CustomExplosionManager.OnClientConnected(SingletonMonoBehaviour<ConnectionManager>.Instance.Clients.ForEntityId(_e.entityId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch]
|
||||||
|
internal class ExplosionParsePatch
|
||||||
|
{
|
||||||
|
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.Init))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static bool Init_ItemClass_Prefix(ItemClass __instance)
|
||||||
|
{
|
||||||
|
if (CustomExplosionManager.parseParticleData(__instance.Properties, out var component))
|
||||||
|
{
|
||||||
|
component.BoundItemClass = __instance;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(ItemAction), nameof(ItemAction.ReadFrom))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static bool ReadFrom_ItemAction_Prefix(ItemAction __instance, ref DynamicProperties _props)
|
||||||
|
{
|
||||||
|
if (CustomExplosionManager.parseParticleData(_props, out var component))
|
||||||
|
{
|
||||||
|
component.BoundItemClass = __instance.item;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Block), nameof(Block.Init))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static bool Init_Block_Prefix(Block __instance)
|
||||||
|
{
|
||||||
|
CustomExplosionManager.parseParticleData(__instance.Properties, out _);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(EntityClass), nameof(EntityClass.Init))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static bool Init_EntityClass_Prefix(EntityClass __instance)
|
||||||
|
{
|
||||||
|
CustomExplosionManager.parseParticleData(__instance.Properties, out _);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.OnEntityDeath))]
|
||||||
|
internal class EntityExplosionPatch
|
||||||
|
{
|
||||||
|
private static void Postfix(EntityAlive __instance)
|
||||||
|
{
|
||||||
|
if (__instance.isEntityRemote || __instance is EntityCar || __instance is EntityZombieCop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ref ExplosionData explosion = ref EntityClass.list[__instance.entityClass].explosionData;
|
||||||
|
if (explosion.ParticleIndex > 0)
|
||||||
|
GameManager.Instance.ExplosionServer(0, __instance.GetPosition(), World.worldToBlockPos(__instance.GetPosition()), Quaternion.identity, explosion, __instance.entityId, 0f, false, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Explosion), nameof(Explosion.AttackEntites))]
|
||||||
|
internal class ExplosionAttackPatch
|
||||||
|
{
|
||||||
|
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var codes = new List<CodeInstruction>(instructions);
|
||||||
|
|
||||||
|
FieldInfo fld_hit_entities = AccessTools.Field(typeof(Explosion), nameof(Explosion.hitEntities));
|
||||||
|
Type entityDict = fld_hit_entities.FieldType;
|
||||||
|
|
||||||
|
LocalBuilder lbd_entity_dict = generator.DeclareLocal(entityDict);
|
||||||
|
|
||||||
|
codes.InsertRange(0, new CodeInstruction[]
|
||||||
|
{
|
||||||
|
new CodeInstruction(OpCodes.Newobj, entityDict.GetConstructor(new Type[]{ })),
|
||||||
|
new CodeInstruction(OpCodes.Stloc_S, lbd_entity_dict)
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i < codes.Count; ++i)
|
||||||
|
{
|
||||||
|
if (codes[i].opcode == OpCodes.Ldsfld && codes[i].LoadsField(fld_hit_entities))
|
||||||
|
{
|
||||||
|
codes[i].opcode = OpCodes.Ldloc_S;
|
||||||
|
codes[i].operand = lbd_entity_dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(ExplosionData))]
|
||||||
|
internal class ExplosionDataPatch
|
||||||
|
{
|
||||||
|
[HarmonyPatch(nameof(ExplosionData.Write))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static bool Prefix_ExplosionData_Write(BinaryWriter _bw, ref ExplosionData __instance)
|
||||||
|
{
|
||||||
|
_bw.Write((ushort)__instance.ParticleIndex);
|
||||||
|
_bw.Write((short)(__instance.Duration * 10f));
|
||||||
|
_bw.Write((short)(__instance.BlockRadius * 20f));
|
||||||
|
_bw.Write((short)__instance.EntityRadius);
|
||||||
|
_bw.Write((short)__instance.BlastPower);
|
||||||
|
_bw.Write(__instance.BlockDamage);
|
||||||
|
_bw.Write(__instance.EntityDamage);
|
||||||
|
_bw.Write(__instance.BlockTags);
|
||||||
|
_bw.Write(__instance.IgnoreHeatMap);
|
||||||
|
if (__instance.damageMultiplier != null)
|
||||||
|
{
|
||||||
|
_bw.Write(true);
|
||||||
|
__instance.damageMultiplier.Write(_bw);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_bw.Write(false);
|
||||||
|
}
|
||||||
|
if (__instance.BuffActions != null)
|
||||||
|
{
|
||||||
|
_bw.Write((byte)__instance.BuffActions.Count);
|
||||||
|
for (int i = 0; i < __instance.BuffActions.Count; i++)
|
||||||
|
{
|
||||||
|
_bw.Write(__instance.BuffActions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_bw.Write(0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(nameof(ExplosionData.Read))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static bool Prefix_ExplosionData_Read(BinaryReader _br, ref ExplosionData __instance)
|
||||||
|
{
|
||||||
|
__instance.ParticleIndex = _br.ReadUInt16();
|
||||||
|
__instance.Duration = _br.ReadInt16() * 0.1f;
|
||||||
|
__instance.BlockRadius = _br.ReadInt16() * 0.05f;
|
||||||
|
__instance.EntityRadius = _br.ReadInt16();
|
||||||
|
__instance.BlastPower = _br.ReadInt16();
|
||||||
|
__instance.BlockDamage = _br.ReadSingle();
|
||||||
|
__instance.EntityDamage = _br.ReadSingle();
|
||||||
|
__instance.BlockTags = _br.ReadString();
|
||||||
|
__instance.IgnoreHeatMap = _br.ReadBoolean();
|
||||||
|
if (_br.ReadBoolean())
|
||||||
|
{
|
||||||
|
__instance.damageMultiplier = new DamageMultiplier();
|
||||||
|
__instance.damageMultiplier.Read(_br);
|
||||||
|
}
|
||||||
|
|
||||||
|
int num = _br.ReadByte();
|
||||||
|
if (num > 0)
|
||||||
|
{
|
||||||
|
__instance.BuffActions = new List<string>();
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
__instance.BuffActions.Add(_br.ReadString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__instance.BuffActions = null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(ItemHasTags), nameof(ItemHasTags.IsValid))]
|
||||||
|
internal class ItemHasTagsPatch : HarmonyPatch
|
||||||
|
{
|
||||||
|
private static bool Prefix(MinEventParams _params, ref bool __result)
|
||||||
|
{
|
||||||
|
if (_params.ItemValue == null)
|
||||||
|
{
|
||||||
|
__result = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MinEventParams workarounds
|
||||||
|
[HarmonyPatch(typeof(ItemActionRanged), "fireShot")]
|
||||||
|
internal class ItemActionRangedFireShotPatch
|
||||||
|
{
|
||||||
|
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||||
|
{
|
||||||
|
var codes = new List<CodeInstruction>(instructions);
|
||||||
|
|
||||||
|
var fld_ranged_tag = AccessTools.Field(typeof(ItemActionAttack), nameof(ItemActionAttack.RangedTag));
|
||||||
|
var fld_params = AccessTools.Field(typeof(EntityAlive), nameof(EntityAlive.MinEventContext));
|
||||||
|
|
||||||
|
for (int i = 0; i < codes.Count; i++)
|
||||||
|
{
|
||||||
|
if (codes[i].LoadsField(fld_ranged_tag))
|
||||||
|
{
|
||||||
|
if (!codes[i + 3].LoadsField(fld_params))
|
||||||
|
{
|
||||||
|
codes.InsertRange(i + 2, new CodeInstruction[]
|
||||||
|
{
|
||||||
|
new CodeInstruction(OpCodes.Ldloc_1),
|
||||||
|
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.MinEventContext)),
|
||||||
|
new CodeInstruction(OpCodes.Dup),
|
||||||
|
new CodeInstruction(OpCodes.Ldloc, 10),
|
||||||
|
CodeInstruction.LoadField(typeof(WorldRayHitInfo), nameof(WorldRayHitInfo.hit)),
|
||||||
|
CodeInstruction.LoadField(typeof(HitInfoDetails), nameof(HitInfoDetails.pos)),
|
||||||
|
CodeInstruction.StoreField(typeof(MinEventParams), nameof(MinEventParams.Position)),
|
||||||
|
new CodeInstruction(OpCodes.Ldloc_1),
|
||||||
|
CodeInstruction.Call(typeof(EntityAlive), nameof(EntityAlive.GetPosition)),
|
||||||
|
CodeInstruction.StoreField(typeof(MinEventParams), nameof(MinEventParams.StartPosition))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//[HarmonyPatch(typeof(MinEventActionExplode), nameof(MinEventActionExplode.Execute))]
|
||||||
|
//class TempPatch
|
||||||
|
//{
|
||||||
|
// private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||||
|
// {
|
||||||
|
// var codes = instructions.ToList();
|
||||||
|
// var mtd_explode_server = AccessTools.Method(typeof(GameManager), nameof(GameManager.ExplosionServer));
|
||||||
|
// for (int i = 0; i < codes.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (codes[i].Calls(mtd_explode_server))
|
||||||
|
// {
|
||||||
|
// codes.InsertRange(i + 1, new CodeInstruction[]
|
||||||
|
// {
|
||||||
|
// new CodeInstruction(OpCodes.Ldloca_S, 2),
|
||||||
|
// new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(ExplosionData), nameof(ExplosionData.ToByteArray))),
|
||||||
|
// new CodeInstruction(OpCodes.Pop)
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return codes;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
9
ModInfo.xml
Normal file
9
ModInfo.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<xml>
|
||||||
|
<Name value="CustomParticleLoader" />
|
||||||
|
<DisplayName value="Custom Explosion Particle Loader" />
|
||||||
|
<Description value="Allow you to use custom particle for explosion effects, with your own monoscripts." />
|
||||||
|
<Author value="closer_ex" />
|
||||||
|
<Version value="1.5.1" />
|
||||||
|
</xml>
|
||||||
36
Properties/AssemblyInfo.cs
Normal file
36
Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// 有关程序集的一般信息由以下
|
||||||
|
// 控制。更改这些特性值可修改
|
||||||
|
// 与程序集关联的信息。
|
||||||
|
[assembly: AssemblyTitle("CustomParticleLoader")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("CustomParticleLoader")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||||
|
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||||
|
//请将此类型的 ComVisible 特性设置为 true。
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||||
|
[assembly: Guid("12a59f51-6655-49d7-be95-f3e86a173979")]
|
||||||
|
|
||||||
|
// 程序集的版本信息由下列四个值组成:
|
||||||
|
//
|
||||||
|
// 主版本
|
||||||
|
// 次版本
|
||||||
|
// 生成号
|
||||||
|
// 修订号
|
||||||
|
//
|
||||||
|
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||||
|
//通过使用 "*",如下所示:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
294
Scripts/Core/CustomExplosionManager.cs
Normal file
294
Scripts/Core/CustomExplosionManager.cs
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public static class CustomExplosionManager
|
||||||
|
{
|
||||||
|
private static Dictionary<int, string> hash_paths = new Dictionary<int, string>();
|
||||||
|
private static Dictionary<string, ExplosionComponent> hash_components = new Dictionary<string, ExplosionComponent>();
|
||||||
|
private static Dictionary<string, GameObject> hash_assets = new Dictionary<string, GameObject>();
|
||||||
|
private static HashSet<GameObject> hash_initialized = new HashSet<GameObject>();
|
||||||
|
private static List<IExplosionPropertyParser> list_parsers = new List<IExplosionPropertyParser>();
|
||||||
|
private static Stack<ExplosionValue> last_init_components = new Stack<ExplosionValue>();
|
||||||
|
|
||||||
|
public static event Action<PooledBinaryWriter> ClientConnected;
|
||||||
|
|
||||||
|
public static event Action<ClientInfo> HandleClientInfo;
|
||||||
|
|
||||||
|
public static event Action CleanUp;
|
||||||
|
|
||||||
|
public static ExplosionValue LastInitializedComponent
|
||||||
|
{
|
||||||
|
get => last_init_components.Count > 0 ? last_init_components.Peek() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint NextExplosionIndex { get; set; } = 0;
|
||||||
|
|
||||||
|
internal static void OnCleanUp()
|
||||||
|
{
|
||||||
|
Log.Out("Custom Explosion Manager cleanup...");
|
||||||
|
destroyAllParticles();
|
||||||
|
NextExplosionIndex = 0;
|
||||||
|
CleanUp?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void OnClientConnected(ClientInfo client)
|
||||||
|
{
|
||||||
|
var handler = ClientConnected;
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
uint count = (uint)ClientConnected.GetInvocationList().Length;
|
||||||
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
|
using (PooledBinaryWriter _bw = MemoryPools.poolBinaryWriter.AllocSync(false))
|
||||||
|
{
|
||||||
|
_bw.SetBaseStream(memoryStream);
|
||||||
|
_bw.Write(count);
|
||||||
|
handler(_bw);
|
||||||
|
if (HandleClientInfo != null)
|
||||||
|
HandleClientInfo(client);
|
||||||
|
}
|
||||||
|
byte[] data = memoryStream.ToArray();
|
||||||
|
client.SendPackage(NetPackageManager.GetPackage<NetPackageExplosionSyncOnConnect>().Setup(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CreatePropertyParsers()
|
||||||
|
{
|
||||||
|
var assemblies = ModManager.GetLoadedAssemblies();
|
||||||
|
string iname = nameof(IExplosionPropertyParser);
|
||||||
|
|
||||||
|
foreach (var assembly in assemblies)
|
||||||
|
{
|
||||||
|
var types = assembly.GetTypes();
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
if (type.GetInterface(iname) != null)
|
||||||
|
{
|
||||||
|
var parser = Activator.CreateInstance(type) as IExplosionPropertyParser;
|
||||||
|
list_parsers.Add(parser);
|
||||||
|
Log.Out("Found custom explosion property parser: " + type.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static GameObject InitializeParticle(ExplosionComponent component, Vector3 position, Quaternion rotation)
|
||||||
|
{
|
||||||
|
GameObject __result = UnityEngine.Object.Instantiate<GameObject>(component.Particle, position, rotation);
|
||||||
|
__result.AddComponent<NetSyncHelper>();
|
||||||
|
if (component.TemporaryObjectType != null)
|
||||||
|
__result.AddComponent(component.TemporaryObjectType);
|
||||||
|
if (component.ExplosionDamageAreaType != null)
|
||||||
|
__result.AddComponent(component.ExplosionDamageAreaType);
|
||||||
|
if (component.AudioPlayerType != null)
|
||||||
|
{
|
||||||
|
AudioPlayer audio_script = __result.AddComponent(component.AudioPlayerType) as AudioPlayer;
|
||||||
|
if (component.SoundName != null)
|
||||||
|
audio_script.soundName = component.SoundName;
|
||||||
|
if (component.AudioDuration >= 0)
|
||||||
|
audio_script.duration = component.AudioDuration;
|
||||||
|
}
|
||||||
|
if (component.List_CustomTypes.Count > 0)
|
||||||
|
foreach (Type customtype in component.List_CustomTypes)
|
||||||
|
if (customtype != null)
|
||||||
|
__result.AddComponent(customtype);
|
||||||
|
AutoRemove remove_script = __result.AddComponent<AutoRemove>();
|
||||||
|
CustomExplosionManager.addInitializedParticle(__result);
|
||||||
|
return __result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void PushLastInitComponent(ExplosionValue component)
|
||||||
|
{
|
||||||
|
last_init_components.Push(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void PopLastInitComponent()
|
||||||
|
{
|
||||||
|
if (last_init_components.Count > 0)
|
||||||
|
last_init_components.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool LoadParticleEffect(string fullpath, ExplosionData data, out ExplosionComponent component, string sound_name = null, float duration_audio = -1, List<Type> CustomScriptList = null)
|
||||||
|
{
|
||||||
|
component = null;
|
||||||
|
fullpath = fullpath.Trim();
|
||||||
|
if (!parsePathString(fullpath, out string path, out string assetname))
|
||||||
|
return false;
|
||||||
|
//check if asset is loaded
|
||||||
|
string path_asset = path + "?" + assetname;
|
||||||
|
bool flag = hash_assets.TryGetValue(path_asset, out GameObject obj);
|
||||||
|
if (!flag)
|
||||||
|
{
|
||||||
|
//load asset
|
||||||
|
string path_bundle = ModManager.PatchModPathString(path).TrimStart('#');
|
||||||
|
Log.Out("Bundle path: " + path_bundle);
|
||||||
|
AssetBundleManager.Instance.LoadAssetBundle(path_bundle);
|
||||||
|
obj = AssetBundleManager.Instance.Get<GameObject>(path_bundle, assetname);
|
||||||
|
if (obj == null)
|
||||||
|
Log.Error("Failed to load asset " + assetname);
|
||||||
|
else
|
||||||
|
hash_assets.Add(path_asset, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
Log.Error("Particle not loaded:" + path_asset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//pair particle with scripts
|
||||||
|
if (hash_components.Remove(fullpath))
|
||||||
|
Log.Out("Particle data already exists:" + fullpath + ", now overwriting");
|
||||||
|
component = new ExplosionComponent(obj, sound_name, duration_audio, data, CustomScriptList);
|
||||||
|
hash_components.Add(fullpath, component);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this should get a unique index for each particle
|
||||||
|
public static int getHashCode(string str)
|
||||||
|
{
|
||||||
|
int value = (PlatformIndependentHash.StringToUInt16(str));
|
||||||
|
|
||||||
|
while (hash_paths.TryGetValue(value, out string path))
|
||||||
|
{
|
||||||
|
if (path == str)
|
||||||
|
break;
|
||||||
|
if (value > Int16.MaxValue || (value >= 0 && value < WorldStaticData.prefabExplosions.Length))
|
||||||
|
value = WorldStaticData.prefabExplosions.Length;
|
||||||
|
else
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool parsePathString(string fullpath, out string path, out string assetname)
|
||||||
|
{
|
||||||
|
//get path to asset
|
||||||
|
path = null;
|
||||||
|
assetname = null;
|
||||||
|
if (fullpath == null)
|
||||||
|
{
|
||||||
|
Log.Error("Null fullpath parameter:" + fullpath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int index_path = fullpath.IndexOf('?');
|
||||||
|
if (index_path <= 0)
|
||||||
|
{
|
||||||
|
Log.Error("Particle path does not specify the asset name! fullpath:" + fullpath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
path = fullpath.Substring(0, index_path);
|
||||||
|
int index_postfix = fullpath.IndexOf('$');
|
||||||
|
if (index_postfix <= 0)
|
||||||
|
assetname = fullpath.Substring(index_path + 1);
|
||||||
|
else
|
||||||
|
assetname = fullpath.Substring(index_path + 1, index_postfix - index_path - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void getTypeListFromString(string str, out List<Type> list_types)
|
||||||
|
{
|
||||||
|
list_types = new List<Type>();
|
||||||
|
if (str == null || str == string.Empty)
|
||||||
|
return;
|
||||||
|
string[] array = str.Split(new char[] { '$' });
|
||||||
|
foreach (string typename in array)
|
||||||
|
{
|
||||||
|
if (typename != null)
|
||||||
|
{
|
||||||
|
Type type = Type.GetType(typename.Trim());
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
if (!list_types.Contains(type))
|
||||||
|
list_types.Add(type);
|
||||||
|
else
|
||||||
|
Log.Out("duplicated script type detected: " + type.AssemblyQualifiedName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log.Warning("CustomScriptType not found:" + typename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool parseParticleData(DynamicProperties _props, out ExplosionComponent component)
|
||||||
|
{
|
||||||
|
string str_index = null;
|
||||||
|
component = null;
|
||||||
|
_props.ParseString("Explosion.ParticleIndex", ref str_index);
|
||||||
|
if (str_index != null && str_index.StartsWith("#"))
|
||||||
|
{
|
||||||
|
Log.Out("Original path:" + str_index);
|
||||||
|
int hashed_index = getHashCode(str_index);
|
||||||
|
_props.Values["Explosion.ParticleIndex"] = hashed_index.ToString();
|
||||||
|
Log.Out("Hashed index:" + _props.Values["Explosion.ParticleIndex"]);
|
||||||
|
if (!hash_paths.ContainsKey(hashed_index))
|
||||||
|
hash_paths.Add(hashed_index, str_index);
|
||||||
|
bool overwrite = false;
|
||||||
|
_props.ParseBool("Explosion.Overwrite", ref overwrite);
|
||||||
|
if (overwrite || !GetCustomParticleComponents(hashed_index, out _))
|
||||||
|
{
|
||||||
|
string sound_name = null;
|
||||||
|
_props.ParseString("Explosion.AudioName", ref sound_name);
|
||||||
|
float duration_audio = -1;
|
||||||
|
_props.ParseFloat("Explosion.AudioDuration", ref duration_audio);
|
||||||
|
bool sync = false;
|
||||||
|
_props.ParseBool("Explosion.SyncOnConnect", ref sync);
|
||||||
|
bool observe = false;
|
||||||
|
_props.ParseBool("Explosion.IsChunkObserver", ref observe);
|
||||||
|
getTypeListFromString(_props.Values["Explosion.CustomScriptTypes"], out List<Type> list_customtypes);
|
||||||
|
bool flag = LoadParticleEffect(str_index, new ExplosionData(_props), out component, sound_name, duration_audio, list_customtypes);
|
||||||
|
if (flag && component != null)
|
||||||
|
{
|
||||||
|
component.SyncOnConnect = sync;
|
||||||
|
foreach (var parser in list_parsers)
|
||||||
|
if (list_customtypes.Contains(parser.MatchScriptType()) && parser.ParseProperty(_props, out var property))
|
||||||
|
component.AddCustomProperty(parser.Name(), property);
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void addInitializedParticle(GameObject obj)
|
||||||
|
{
|
||||||
|
hash_initialized.Add(obj);
|
||||||
|
//Log.Out("Particle initialized:" + obj.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void removeInitializedParticle(GameObject obj)
|
||||||
|
{
|
||||||
|
hash_initialized.Remove(obj);
|
||||||
|
//Log.Out("Particle removed on destroy:" + obj.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void destroyAllParticles()
|
||||||
|
{
|
||||||
|
foreach (GameObject obj in hash_initialized)
|
||||||
|
{
|
||||||
|
Log.Out("Active particle destroyed on disconnect:" + obj.name);
|
||||||
|
GameObject.Destroy(obj);
|
||||||
|
}
|
||||||
|
hash_initialized.Clear();
|
||||||
|
/*
|
||||||
|
foreach (var pair in hash_assets)
|
||||||
|
{
|
||||||
|
Log.Out("Loaded particle destroyed on disconnect:" + pair.Value.name);
|
||||||
|
GameObject.Destroy(pair.Value);
|
||||||
|
}
|
||||||
|
hash_assets.Clear();
|
||||||
|
hash_components.Clear();
|
||||||
|
Log.Out("Loaded particle data cleared on disconnect.");
|
||||||
|
*/
|
||||||
|
last_init_components.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool GetCustomParticleComponents(int index, out ExplosionComponent component)
|
||||||
|
{
|
||||||
|
component = null;
|
||||||
|
if (!hash_paths.TryGetValue(index, out string fullpath) || fullpath == null)
|
||||||
|
return false;
|
||||||
|
return hash_components.TryGetValue(fullpath, out component);
|
||||||
|
}
|
||||||
|
}
|
||||||
143
Scripts/Core/ExplosionComponent.cs
Normal file
143
Scripts/Core/ExplosionComponent.cs
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public struct ExplosionParams
|
||||||
|
{
|
||||||
|
public ExplosionParams(int _clrIdx, Vector3 _worldPos, Vector3i _blockPos, Quaternion _rotation, ExplosionData _explosionData, int _playerId, uint _explId)
|
||||||
|
{
|
||||||
|
this._clrIdx = _clrIdx;
|
||||||
|
this._worldPos = _worldPos;
|
||||||
|
this._blockPos = _blockPos;
|
||||||
|
this._rotation = _rotation;
|
||||||
|
this._explosionData = _explosionData;
|
||||||
|
this._playerId = _playerId;
|
||||||
|
this._explId = _explId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExplosionParams(byte[] _explosionParamsAsArr)
|
||||||
|
{
|
||||||
|
_clrIdx = 0;
|
||||||
|
_worldPos = Vector3.zero;
|
||||||
|
_blockPos = Vector3i.zero;
|
||||||
|
_rotation = Quaternion.identity;
|
||||||
|
_explosionData = default(ExplosionData);
|
||||||
|
_playerId = -1;
|
||||||
|
_explId = uint.MaxValue;
|
||||||
|
using (PooledBinaryReader pooledBinaryReader = MemoryPools.poolBinaryReader.AllocSync(false))
|
||||||
|
{
|
||||||
|
pooledBinaryReader.SetBaseStream(new MemoryStream(_explosionParamsAsArr));
|
||||||
|
read(pooledBinaryReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void read(PooledBinaryReader _br)
|
||||||
|
{
|
||||||
|
_clrIdx = (int)_br.ReadUInt16();
|
||||||
|
_worldPos = StreamUtils.ReadVector3(_br);
|
||||||
|
_blockPos = StreamUtils.ReadVector3i(_br);
|
||||||
|
_rotation = StreamUtils.ReadQuaterion(_br);
|
||||||
|
_explosionData.Read(_br);
|
||||||
|
_playerId = _br.ReadInt32();
|
||||||
|
_explId = _br.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(PooledBinaryWriter _bw)
|
||||||
|
{
|
||||||
|
_bw.Write((ushort)_clrIdx);
|
||||||
|
StreamUtils.Write(_bw, _worldPos);
|
||||||
|
StreamUtils.Write(_bw, _blockPos);
|
||||||
|
StreamUtils.Write(_bw, _rotation);
|
||||||
|
_explosionData.Write(_bw);
|
||||||
|
_bw.Write(_playerId);
|
||||||
|
_bw.Write(_explId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] ToByteArray()
|
||||||
|
{
|
||||||
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
|
using (PooledBinaryWriter pooledBinaryWriter = MemoryPools.poolBinaryWriter.AllocSync(false))
|
||||||
|
{
|
||||||
|
pooledBinaryWriter.SetBaseStream(memoryStream);
|
||||||
|
write(pooledBinaryWriter);
|
||||||
|
}
|
||||||
|
return memoryStream.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int _clrIdx;
|
||||||
|
public Vector3 _worldPos;
|
||||||
|
public Vector3i _blockPos;
|
||||||
|
public Quaternion _rotation;
|
||||||
|
public ExplosionData _explosionData;
|
||||||
|
public int _playerId;
|
||||||
|
public uint _explId;
|
||||||
|
}
|
||||||
|
public class ExplosionComponent
|
||||||
|
{
|
||||||
|
public ExplosionComponent(GameObject obj, string sound_name, float duration_audio, ExplosionData data, List<Type> CustomScriptTypes)
|
||||||
|
{
|
||||||
|
this.obj = obj;
|
||||||
|
this.list_custom = new List<Type>();
|
||||||
|
foreach (Type type in CustomScriptTypes)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
continue;
|
||||||
|
if ((type.IsSubclassOf(typeof(TemporaryObject)) || type == typeof(TemporaryObject)))
|
||||||
|
this.TempObjType = type;
|
||||||
|
else if ((type.IsSubclassOf(typeof(ExplosionDamageArea)) || type == typeof(ExplosionDamageArea)))
|
||||||
|
this.ExplAreaType = type;
|
||||||
|
else if ((type.IsSubclassOf(typeof(AudioPlayer)) || type == typeof(AudioPlayer)))
|
||||||
|
this.AudioType = AudioPlayerType;
|
||||||
|
else
|
||||||
|
this.list_custom.Add(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sound_name = sound_name;
|
||||||
|
this.duration_audio = duration_audio;
|
||||||
|
this.hash_custom_properties = new Dictionary<string, object>();
|
||||||
|
this.data = data;
|
||||||
|
if (this.sound_name != null && this.AudioPlayerType == null)
|
||||||
|
this.AudioType = typeof(AudioPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GameObject obj;
|
||||||
|
private Type TempObjType = null;
|
||||||
|
private Type ExplAreaType = null;
|
||||||
|
private Type AudioType = null;
|
||||||
|
private List<Type> list_custom;
|
||||||
|
private float duration_audio;
|
||||||
|
private string sound_name;
|
||||||
|
private ExplosionData data;
|
||||||
|
private Dictionary<string, object> hash_custom_properties;
|
||||||
|
|
||||||
|
public bool TryGetCustomProperty(string name, out object value)
|
||||||
|
{
|
||||||
|
return hash_custom_properties.TryGetValue(name, out value);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddCustomProperty(string name, object value)
|
||||||
|
{
|
||||||
|
if(hash_custom_properties.Remove(name))
|
||||||
|
Log.Out("Custom explosion component property already exists, overwriting: " + name);
|
||||||
|
hash_custom_properties.Add(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameObject Particle { get => obj; }
|
||||||
|
public Type TemporaryObjectType { get => TempObjType; }
|
||||||
|
public Type ExplosionDamageAreaType { get => ExplAreaType; }
|
||||||
|
public Type AudioPlayerType { get => AudioType; }
|
||||||
|
public List<Type> List_CustomTypes { get => list_custom; }
|
||||||
|
public float AudioDuration{ get => duration_audio; }
|
||||||
|
public string SoundName { get => sound_name; }
|
||||||
|
public ExplosionData BoundExplosionData { get => data; }
|
||||||
|
public ItemClass BoundItemClass { get; set; }
|
||||||
|
public bool SyncOnConnect { get; set; } = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExplosionValue
|
||||||
|
{
|
||||||
|
public ExplosionComponent Component { get; set; }
|
||||||
|
public ExplosionParams CurrentExplosionParams { get; set; }
|
||||||
|
public ItemValue CurrentItemValue { get; set; }
|
||||||
|
}
|
||||||
6
Scripts/Core/IExplosionProperty.cs
Normal file
6
Scripts/Core/IExplosionProperty.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
public interface IExplosionPropertyParser
|
||||||
|
{
|
||||||
|
bool ParseProperty(DynamicProperties _props, out object property);
|
||||||
|
System.Type MatchScriptType();
|
||||||
|
string Name();
|
||||||
|
}
|
||||||
103
Scripts/MinEventActions/MinEventActionRangedExplosion.cs
Normal file
103
Scripts/MinEventActions/MinEventActionRangedExplosion.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class MinEventActionRangedExplosion : MinEventActionBase
|
||||||
|
{
|
||||||
|
private ExplosionData _explosionData;
|
||||||
|
private int itemType = -1;
|
||||||
|
private ExplosionComponent _explosionComponent;
|
||||||
|
//private float delay = 0;
|
||||||
|
private bool _initialized = false;
|
||||||
|
private bool _useCustomParticle = false;
|
||||||
|
private int customParticleIndex;
|
||||||
|
private ItemValue ammoItem;
|
||||||
|
|
||||||
|
public override void Execute(MinEventParams _params)
|
||||||
|
{
|
||||||
|
bool hasEntity = _params.Self != null;
|
||||||
|
//int layer = 0;
|
||||||
|
// if (hasEntity)
|
||||||
|
// {
|
||||||
|
// layer = _params.Self.GetModelLayer();
|
||||||
|
// _params.Self.SetModelLayer(24, false);
|
||||||
|
// }
|
||||||
|
GameManager.Instance.ExplosionServer(0, _params.Position, World.worldToBlockPos(_params.Position), hasEntity ? _params.Self.qrotation : Quaternion.identity, _useCustomParticle ? _explosionComponent.BoundExplosionData : _explosionData, hasEntity ? _params.Self.entityId : -1, Delay, false, ammoItem ?? _params.ItemValue);
|
||||||
|
//if (hasEntity)
|
||||||
|
//{
|
||||||
|
// _params.Self.SetModelLayer(layer, false);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanExecute(MinEventTypes _eventType, MinEventParams _params)
|
||||||
|
{
|
||||||
|
if (!base.CanExecute(_eventType, _params))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!_initialized || !_useCustomParticle)
|
||||||
|
{
|
||||||
|
if (_useCustomParticle)
|
||||||
|
{
|
||||||
|
if (!CustomExplosionManager.GetCustomParticleComponents(customParticleIndex, out _explosionComponent))
|
||||||
|
return false;
|
||||||
|
if(_explosionComponent.BoundItemClass != null)
|
||||||
|
ammoItem = new ItemValue(_explosionComponent.BoundItemClass.Id, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_params.ItemValue == null)
|
||||||
|
return false;
|
||||||
|
if (_params.ItemValue.type == itemType)
|
||||||
|
return true;
|
||||||
|
ItemClass itemClass = _params.ItemValue.ItemClass;
|
||||||
|
string particleIndex = null;
|
||||||
|
itemClass.Properties.ParseString("Explosion.ParticleIndex", ref particleIndex);
|
||||||
|
if (string.IsNullOrEmpty(particleIndex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (int.TryParse(particleIndex, out int index))
|
||||||
|
{
|
||||||
|
_explosionData = new ExplosionData(itemClass.Properties);
|
||||||
|
itemType = itemClass.Id;
|
||||||
|
ammoItem = new ItemValue(itemType, false);
|
||||||
|
}
|
||||||
|
else if (CustomExplosionManager.GetCustomParticleComponents(CustomExplosionManager.getHashCode(particleIndex), out _explosionComponent))
|
||||||
|
{
|
||||||
|
itemType = itemClass.Id;
|
||||||
|
if(_explosionComponent.BoundItemClass != null)
|
||||||
|
ammoItem = new ItemValue(_explosionComponent.BoundItemClass.Id, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ParseXmlAttribute(XAttribute _attribute)
|
||||||
|
{
|
||||||
|
bool flag = base.ParseXmlAttribute(_attribute);
|
||||||
|
if (!flag)
|
||||||
|
{
|
||||||
|
string name = _attribute.Name.LocalName;
|
||||||
|
switch(name)
|
||||||
|
{
|
||||||
|
case "particle_index":
|
||||||
|
customParticleIndex = CustomExplosionManager.getHashCode(_attribute.Value);
|
||||||
|
_useCustomParticle = true;
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
//case "delay":
|
||||||
|
// float.TryParse(_attribute.Value, out delay);
|
||||||
|
// flag = true;
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
Scripts/MonoBehaviours/AutoRemove.cs
Normal file
44
Scripts/MonoBehaviours/AutoRemove.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class AutoRemove : TrackedBehaviourBase
|
||||||
|
{
|
||||||
|
public float lifetime = -1;
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
ExplosionValue value = CustomExplosionManager.LastInitializedComponent;
|
||||||
|
lifetime = value.CurrentExplosionParams._explosionData.Duration;
|
||||||
|
if(lifetime > 0)
|
||||||
|
syncOnConnect = value.Component.SyncOnConnect;
|
||||||
|
base.Awake();
|
||||||
|
if (lifetime > 0)
|
||||||
|
Destroy(gameObject, lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if(lifetime > 0)
|
||||||
|
lifetime -= Time.deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDestroy()
|
||||||
|
{
|
||||||
|
base.OnDestroy();
|
||||||
|
CustomExplosionManager.removeInitializedParticle(gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClientConnected(PooledBinaryWriter _bw)
|
||||||
|
{
|
||||||
|
_bw.Write(lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnConnectedToServer(PooledBinaryReader _br)
|
||||||
|
{
|
||||||
|
lifetime = _br.ReadSingle();
|
||||||
|
if (lifetime > 0)
|
||||||
|
Destroy(gameObject, lifetime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
97
Scripts/MonoBehaviours/NetSyncHelper.cs
Normal file
97
Scripts/MonoBehaviours/NetSyncHelper.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class NetSyncHelper : MonoBehaviour
|
||||||
|
{
|
||||||
|
public event Action<PooledBinaryWriter> ClientConnected
|
||||||
|
{
|
||||||
|
add { list_connect_server_handlers.Add(value); }
|
||||||
|
remove { list_connect_server_handlers.Remove(value); }
|
||||||
|
}
|
||||||
|
public event Action<PooledBinaryReader> ConnectedToServer
|
||||||
|
{
|
||||||
|
add { list_connect_client_handlers.Add(value); }
|
||||||
|
remove { list_connect_client_handlers.Remove(value); }
|
||||||
|
}
|
||||||
|
public event Action<PooledBinaryWriter> ExplosionServerInit
|
||||||
|
{
|
||||||
|
add { list_init_server_handlers.Add(value); }
|
||||||
|
remove { list_init_server_handlers.Remove(value); }
|
||||||
|
}
|
||||||
|
public event Action<PooledBinaryReader> ExplosionClientInit
|
||||||
|
{
|
||||||
|
add { list_init_client_handlers.Add(value); }
|
||||||
|
remove { list_init_client_handlers.Remove(value); }
|
||||||
|
}
|
||||||
|
private List<Action<PooledBinaryWriter>> list_connect_server_handlers = new List<Action<PooledBinaryWriter>>();
|
||||||
|
private List<Action<PooledBinaryReader>> list_connect_client_handlers = new List<Action<PooledBinaryReader>>();
|
||||||
|
private List<Action<PooledBinaryWriter>> list_init_server_handlers = new List<Action<PooledBinaryWriter>>();
|
||||||
|
private List<Action<PooledBinaryReader>> list_init_client_handlers = new List<Action<PooledBinaryReader>>();
|
||||||
|
public ExplosionParams explParams;
|
||||||
|
public ItemValue explValue;
|
||||||
|
public uint explId;
|
||||||
|
private static Dictionary<uint, NetSyncHelper> hash_helpers = new Dictionary<uint, NetSyncHelper>();
|
||||||
|
|
||||||
|
static NetSyncHelper()
|
||||||
|
{
|
||||||
|
CustomExplosionManager.CleanUp += hash_helpers.Clear;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Awake()
|
||||||
|
{
|
||||||
|
hash_helpers.Add((explId = CustomExplosionManager.LastInitializedComponent.CurrentExplosionParams._explId), this);
|
||||||
|
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer && CustomExplosionManager.LastInitializedComponent.Component.SyncOnConnect)
|
||||||
|
{
|
||||||
|
explParams = CustomExplosionManager.LastInitializedComponent.CurrentExplosionParams;
|
||||||
|
explValue = CustomExplosionManager.LastInitializedComponent.CurrentItemValue?.Clone();
|
||||||
|
CustomExplosionManager.ClientConnected += OnClientConnected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetValue(uint id, out NetSyncHelper helper)
|
||||||
|
{
|
||||||
|
return hash_helpers.TryGetValue(id, out helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
CustomExplosionManager.ClientConnected -= OnClientConnected;
|
||||||
|
hash_helpers.Remove(explId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnClientConnected(PooledBinaryWriter _bw)
|
||||||
|
{
|
||||||
|
explParams._worldPos = transform.position + Origin.position;
|
||||||
|
explParams._rotation = transform.rotation;
|
||||||
|
byte[] array = explParams.ToByteArray();
|
||||||
|
_bw.Write((ushort)array.Length);
|
||||||
|
_bw.Write(array);
|
||||||
|
_bw.Write(explValue != null);
|
||||||
|
if (explValue != null)
|
||||||
|
{
|
||||||
|
explValue.Write(_bw);
|
||||||
|
}
|
||||||
|
foreach (var handler in list_connect_server_handlers)
|
||||||
|
handler(_bw);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnConnectedToServer(PooledBinaryReader _br)
|
||||||
|
{
|
||||||
|
foreach (var handler in list_connect_client_handlers)
|
||||||
|
handler(_br);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnExplosionServerInit(PooledBinaryWriter _bw)
|
||||||
|
{
|
||||||
|
foreach (var handler in list_init_server_handlers)
|
||||||
|
handler(_bw);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnExplosionClientInit(PooledBinaryReader _br)
|
||||||
|
{
|
||||||
|
foreach (var handler in list_init_client_handlers)
|
||||||
|
handler(_br);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
42
Scripts/MonoBehaviours/ReverseTrackedBehaviour.cs
Normal file
42
Scripts/MonoBehaviours/ReverseTrackedBehaviour.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class ReverseTrackedBehaviour<T> : TrackedBehaviourBase where T : ReverseTrackedBehaviour<T>
|
||||||
|
{
|
||||||
|
protected static Dictionary<object, Dictionary<uint, T>> hash_instances = new Dictionary<object, Dictionary<uint, T>>();
|
||||||
|
|
||||||
|
static ReverseTrackedBehaviour()
|
||||||
|
{
|
||||||
|
CustomExplosionManager.CleanUp += hash_instances.Clear;
|
||||||
|
}
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
track = true;
|
||||||
|
base.Awake();
|
||||||
|
}
|
||||||
|
protected override void addRef()
|
||||||
|
{
|
||||||
|
if (!hash_instances.ContainsKey(key))
|
||||||
|
hash_instances.Add(key, new Dictionary<uint, T>());
|
||||||
|
hash_instances[key].Add(explId, (T)this);
|
||||||
|
}
|
||||||
|
protected override void removeRef()
|
||||||
|
{
|
||||||
|
var dict = hash_instances[key];
|
||||||
|
if (dict != null)
|
||||||
|
{
|
||||||
|
dict.Remove(explId);
|
||||||
|
if (dict.Count <= 0)
|
||||||
|
hash_instances.Remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetValue(uint id, object key, out T controller)
|
||||||
|
{
|
||||||
|
controller = null;
|
||||||
|
if (hash_instances.TryGetValue(key, out var dict))
|
||||||
|
return dict.TryGetValue(id, out controller);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
124
Scripts/MonoBehaviours/Timer.cs
Normal file
124
Scripts/MonoBehaviours/Timer.cs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计时器
|
||||||
|
/// <para>ZhangYu 2018-04-08</para>
|
||||||
|
/// <para>code from: https://segmentfault.com/a/1190000015325310 </para>
|
||||||
|
/// </summary>
|
||||||
|
public class Timer : MonoBehaviour
|
||||||
|
{
|
||||||
|
// delay in second
|
||||||
|
public float delay = 0;
|
||||||
|
// interval in second
|
||||||
|
public float interval = 1;
|
||||||
|
// repeat count
|
||||||
|
public int repeatCount = 1;
|
||||||
|
// automatically start
|
||||||
|
public bool autoStart = false;
|
||||||
|
// automatically destroy
|
||||||
|
public bool autoDestory = true;
|
||||||
|
// current time
|
||||||
|
public float currentTime = 0;
|
||||||
|
// current count
|
||||||
|
public int currentCount = 0;
|
||||||
|
// event when interval reached
|
||||||
|
public UnityEvent onIntervalEvent;
|
||||||
|
// event when timer completed
|
||||||
|
public UnityEvent onCompleteEvent;
|
||||||
|
// callback delegate
|
||||||
|
public delegate void TimerCallback(Timer timer);
|
||||||
|
// last interval time
|
||||||
|
private float lastTime = 0;
|
||||||
|
// interval callback
|
||||||
|
private TimerCallback onIntervalCall;
|
||||||
|
// complete callback
|
||||||
|
private TimerCallback onCompleteCall;
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
enabled = autoStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixedUpdate()
|
||||||
|
{
|
||||||
|
if (!enabled) return;
|
||||||
|
addInterval(Time.deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> add interval </summary>
|
||||||
|
private void addInterval(float deltaTime)
|
||||||
|
{
|
||||||
|
currentTime += deltaTime;
|
||||||
|
if (currentTime < delay) return;
|
||||||
|
if (currentTime - lastTime >= interval)
|
||||||
|
{
|
||||||
|
currentCount++;
|
||||||
|
lastTime = currentTime;
|
||||||
|
if (repeatCount <= 0)
|
||||||
|
{
|
||||||
|
// repeate forever
|
||||||
|
if (currentCount == int.MaxValue) reset();
|
||||||
|
if (onIntervalCall != null) onIntervalCall(this);
|
||||||
|
if (onIntervalEvent != null) onIntervalEvent.Invoke();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (currentCount < repeatCount)
|
||||||
|
{
|
||||||
|
if (onIntervalCall != null) onIntervalCall(this);
|
||||||
|
if (onIntervalEvent != null) onIntervalEvent.Invoke();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
if (onCompleteCall != null) onCompleteCall(this);
|
||||||
|
if (onCompleteEvent != null) onCompleteEvent.Invoke();
|
||||||
|
if (autoDestory && !enabled) Destroy(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
enabled = autoStart = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(float time, TimerCallback onComplete)
|
||||||
|
{
|
||||||
|
start(time, 1, null, onComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(float interval, int repeatCount, TimerCallback onComplete)
|
||||||
|
{
|
||||||
|
start(interval, repeatCount, null, onComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(float interval, int repeatCount, TimerCallback onInterval, TimerCallback onComplete)
|
||||||
|
{
|
||||||
|
this.interval = interval;
|
||||||
|
this.repeatCount = repeatCount;
|
||||||
|
onIntervalCall = onInterval;
|
||||||
|
onCompleteCall = onComplete;
|
||||||
|
reset();
|
||||||
|
enabled = autoStart = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop()
|
||||||
|
{
|
||||||
|
enabled = autoStart = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
lastTime = currentTime = currentCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restart()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
43
Scripts/MonoBehaviours/TrackedBehaviour.cs
Normal file
43
Scripts/MonoBehaviours/TrackedBehaviour.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class TrackedBehaviour<T> : TrackedBehaviourBase where T : TrackedBehaviour<T>
|
||||||
|
{
|
||||||
|
protected static Dictionary<uint, Dictionary<object, T>> hash_instances = new Dictionary<uint, Dictionary<object, T>>();
|
||||||
|
|
||||||
|
static TrackedBehaviour()
|
||||||
|
{
|
||||||
|
CustomExplosionManager.CleanUp += hash_instances.Clear;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
track = true;
|
||||||
|
base.Awake();
|
||||||
|
}
|
||||||
|
protected override void addRef()
|
||||||
|
{
|
||||||
|
if (!hash_instances.ContainsKey(explId))
|
||||||
|
hash_instances.Add(explId, new Dictionary<object, T>());
|
||||||
|
hash_instances[explId].Add(key, (T)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void removeRef()
|
||||||
|
{
|
||||||
|
var dict = hash_instances[explId];
|
||||||
|
if (dict != null)
|
||||||
|
{
|
||||||
|
dict.Remove(key);
|
||||||
|
if (dict.Count <= 0)
|
||||||
|
hash_instances.Remove(explId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetValue(uint id, object key, out T controller)
|
||||||
|
{
|
||||||
|
controller = null;
|
||||||
|
if (hash_instances.TryGetValue(id, out var dict))
|
||||||
|
return dict.TryGetValue(key, out controller);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
96
Scripts/MonoBehaviours/TrackedBehaviourBase.cs
Normal file
96
Scripts/MonoBehaviours/TrackedBehaviourBase.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class TrackedBehaviourBase : MonoBehaviour
|
||||||
|
{
|
||||||
|
protected uint explId;
|
||||||
|
protected bool isServer;
|
||||||
|
protected object key = null;
|
||||||
|
protected bool syncOnConnect = false;
|
||||||
|
protected bool syncOnInit = false;
|
||||||
|
protected bool track = false;
|
||||||
|
protected bool handleClientInfo = false;
|
||||||
|
protected NetSyncHelper helper = null;
|
||||||
|
|
||||||
|
protected virtual void Awake()
|
||||||
|
{
|
||||||
|
explId = CustomExplosionManager.LastInitializedComponent.CurrentExplosionParams._explId;
|
||||||
|
if (track)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
Log.Error("TrackedBehaviourBase: key is not initialized before addRef!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addRef();
|
||||||
|
}
|
||||||
|
bool flag = NetSyncHelper.TryGetValue(explId, out helper);
|
||||||
|
isServer = SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer;
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
if (syncOnConnect)
|
||||||
|
{
|
||||||
|
if (isServer)
|
||||||
|
helper.ClientConnected += OnClientConnected;
|
||||||
|
else
|
||||||
|
helper.ConnectedToServer += OnConnectedToServer;
|
||||||
|
}
|
||||||
|
if (syncOnInit)
|
||||||
|
{
|
||||||
|
if (isServer)
|
||||||
|
helper.ExplosionServerInit += OnExplosionInitServer;
|
||||||
|
else
|
||||||
|
helper.ExplosionClientInit += OnExplosionInitClient;
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
Log.Error("NetSyncHelper not initialized: explId: " + explId);
|
||||||
|
if (handleClientInfo)
|
||||||
|
CustomExplosionManager.HandleClientInfo += OnHandleClientInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnDestroy()
|
||||||
|
{
|
||||||
|
if (helper != null)
|
||||||
|
{
|
||||||
|
if (syncOnConnect)
|
||||||
|
{
|
||||||
|
if (isServer)
|
||||||
|
helper.ClientConnected -= OnClientConnected;
|
||||||
|
else
|
||||||
|
helper.ConnectedToServer -= OnConnectedToServer;
|
||||||
|
}
|
||||||
|
if (syncOnInit)
|
||||||
|
{
|
||||||
|
if (isServer)
|
||||||
|
helper.ExplosionServerInit -= OnExplosionInitServer;
|
||||||
|
else
|
||||||
|
helper.ExplosionClientInit -= OnExplosionInitClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (handleClientInfo)
|
||||||
|
CustomExplosionManager.HandleClientInfo -= OnHandleClientInfo;
|
||||||
|
if (track)
|
||||||
|
removeRef();
|
||||||
|
}
|
||||||
|
protected virtual void addRef()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected virtual void removeRef()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected virtual void OnClientConnected(PooledBinaryWriter _bw)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected virtual void OnConnectedToServer(PooledBinaryReader _br)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected virtual void OnExplosionInitServer(PooledBinaryWriter _bw)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected virtual void OnExplosionInitClient(PooledBinaryReader _br)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected virtual void OnHandleClientInfo(ClientInfo info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
158
Scripts/NetPackages/NetPackageExplosionParams.cs
Normal file
158
Scripts/NetPackages/NetPackageExplosionParams.cs
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class NetPackageExplosionParams : NetPackage
|
||||||
|
{
|
||||||
|
public NetPackageExplosionParams Setup(int _clrIdx, Vector3 _worldPos, Vector3i _blockPos, Quaternion _rotation, ExplosionData _explosionData, int _entityId, uint _explId, ItemValue _itemValueExplosive, List<BlockChangeInfo> explosionChanges, GameObject particle)
|
||||||
|
{
|
||||||
|
clrIdx = _clrIdx;
|
||||||
|
worldPos = _worldPos;
|
||||||
|
blockPos = _blockPos;
|
||||||
|
rotation = _rotation;
|
||||||
|
explosionData = _explosionData;
|
||||||
|
entityId = _entityId;
|
||||||
|
explosionId = _explId;
|
||||||
|
itemValueExplosive = null;
|
||||||
|
if(_itemValueExplosive != null)
|
||||||
|
itemValueExplosive = _itemValueExplosive.Clone();
|
||||||
|
this.explosionChanges.Clear();
|
||||||
|
this.explosionChanges.AddRange(explosionChanges);
|
||||||
|
if(particle != null)
|
||||||
|
{
|
||||||
|
if(particle.TryGetComponent<NetSyncHelper>(out var helper))
|
||||||
|
{
|
||||||
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
|
using (PooledBinaryWriter _bw = MemoryPools.poolBinaryWriter.AllocSync(false))
|
||||||
|
{
|
||||||
|
_bw.SetBaseStream(memoryStream);
|
||||||
|
helper.OnExplosionServerInit(_bw);
|
||||||
|
}
|
||||||
|
dataToSync = memoryStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void read(PooledBinaryReader _br)
|
||||||
|
{
|
||||||
|
clrIdx = (int)_br.ReadUInt16();
|
||||||
|
worldPos = StreamUtils.ReadVector3(_br);
|
||||||
|
blockPos = StreamUtils.ReadVector3i(_br);
|
||||||
|
rotation = StreamUtils.ReadQuaterion(_br);
|
||||||
|
int count = (int)_br.ReadUInt16();
|
||||||
|
explosionData = new ExplosionData(_br.ReadBytes(count));
|
||||||
|
entityId = _br.ReadInt32();
|
||||||
|
explosionId = _br.ReadUInt32();
|
||||||
|
int num = (int)_br.ReadUInt16();
|
||||||
|
explosionChanges = new List<BlockChangeInfo>(num);
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
BlockChangeInfo blockChangeInfo = new BlockChangeInfo();
|
||||||
|
blockChangeInfo.Read(_br);
|
||||||
|
explosionChanges.Add(blockChangeInfo);
|
||||||
|
}
|
||||||
|
if (_br.ReadBoolean())
|
||||||
|
{
|
||||||
|
itemValueExplosive = new ItemValue();
|
||||||
|
itemValueExplosive.Read(_br);
|
||||||
|
}
|
||||||
|
ushort bytes = _br.ReadUInt16();
|
||||||
|
if (bytes > 0)
|
||||||
|
dataToSync = _br.ReadBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void write(PooledBinaryWriter _bw)
|
||||||
|
{
|
||||||
|
base.write(_bw);
|
||||||
|
_bw.Write((ushort)clrIdx);
|
||||||
|
StreamUtils.Write(_bw, worldPos);
|
||||||
|
StreamUtils.Write(_bw, blockPos);
|
||||||
|
StreamUtils.Write(_bw, rotation);
|
||||||
|
byte[] array = explosionData.ToByteArray();
|
||||||
|
_bw.Write((ushort)array.Length);
|
||||||
|
_bw.Write(array);
|
||||||
|
_bw.Write(entityId);
|
||||||
|
_bw.Write(explosionId);
|
||||||
|
_bw.Write((ushort)explosionChanges.Count);
|
||||||
|
for (int i = 0; i < explosionChanges.Count; i++)
|
||||||
|
{
|
||||||
|
explosionChanges[i].Write(_bw);
|
||||||
|
}
|
||||||
|
_bw.Write(itemValueExplosive != null);
|
||||||
|
if (itemValueExplosive != null)
|
||||||
|
{
|
||||||
|
itemValueExplosive.Write(_bw);
|
||||||
|
}
|
||||||
|
if (dataToSync != null && dataToSync.Length > 0)
|
||||||
|
{
|
||||||
|
_bw.Write((ushort)dataToSync.Length);
|
||||||
|
_bw.Write(dataToSync);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_bw.Write((ushort)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ProcessPackage(World _world, GameManager _callbacks)
|
||||||
|
{
|
||||||
|
if (_world == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool isCustom = false;
|
||||||
|
if(explosionData.ParticleIndex >= WorldStaticData.prefabExplosions.Length)
|
||||||
|
{
|
||||||
|
isCustom = CustomExplosionManager.GetCustomParticleComponents(explosionData.ParticleIndex, out ExplosionComponent component) && component != null;
|
||||||
|
if (isCustom)
|
||||||
|
{
|
||||||
|
ExplosionValue value = new ExplosionValue()
|
||||||
|
{
|
||||||
|
Component = component,
|
||||||
|
CurrentExplosionParams = new ExplosionParams(clrIdx, worldPos, blockPos, rotation, explosionData, entityId, explosionId),
|
||||||
|
CurrentItemValue = itemValueExplosive?.Clone()
|
||||||
|
};
|
||||||
|
CustomExplosionManager.PushLastInitComponent(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject result = _callbacks.ExplosionClient(clrIdx, worldPos, rotation, explosionData.ParticleIndex, explosionData.BlastPower, (float)explosionData.EntityRadius, (float)explosionData.BlockDamage, entityId, explosionChanges);
|
||||||
|
if (isCustom)
|
||||||
|
{
|
||||||
|
NetSyncHelper helper = result?.GetComponent<NetSyncHelper>();
|
||||||
|
if (helper != null && dataToSync != null)
|
||||||
|
{
|
||||||
|
using (PooledBinaryReader _br = MemoryPools.poolBinaryReader.AllocSync(false))
|
||||||
|
{
|
||||||
|
_br.SetBaseStream(new MemoryStream(dataToSync));
|
||||||
|
helper.OnExplosionClientInit(_br);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CustomExplosionManager.PopLastInitComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override NetPackageDirection PackageDirection
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return NetPackageDirection.ToClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetLength()
|
||||||
|
{
|
||||||
|
return 80 + explosionChanges.Count * 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int clrIdx;
|
||||||
|
private Vector3 worldPos;
|
||||||
|
private Vector3i blockPos;
|
||||||
|
private Quaternion rotation;
|
||||||
|
private ExplosionData explosionData;
|
||||||
|
private int entityId;
|
||||||
|
private uint explosionId;
|
||||||
|
private ItemValue itemValueExplosive;
|
||||||
|
private List<BlockChangeInfo> explosionChanges = new List<BlockChangeInfo>();
|
||||||
|
private byte[] dataToSync = null;
|
||||||
|
}
|
||||||
|
|
||||||
77
Scripts/NetPackages/NetPackageExplosionSyncOnConnect.cs
Normal file
77
Scripts/NetPackages/NetPackageExplosionSyncOnConnect.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
using XMLData.Item;
|
||||||
|
|
||||||
|
public class NetPackageExplosionSyncOnConnect : NetPackage
|
||||||
|
{
|
||||||
|
public NetPackageExplosionSyncOnConnect Setup(byte[] data)
|
||||||
|
{
|
||||||
|
this.data = data != null ? data : new byte[0];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void read(PooledBinaryReader _br)
|
||||||
|
{
|
||||||
|
int bytes = _br.ReadInt32();
|
||||||
|
data = _br.ReadBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void write(PooledBinaryWriter _bw)
|
||||||
|
{
|
||||||
|
base.write(_bw);
|
||||||
|
_bw.Write(data.Length);
|
||||||
|
_bw.Write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ProcessPackage(World _world, GameManager _callbacks)
|
||||||
|
{
|
||||||
|
if (_world == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (PooledBinaryReader _br = MemoryPools.poolBinaryReader.AllocSync(false))
|
||||||
|
{
|
||||||
|
_br.SetBaseStream(new MemoryStream(data));
|
||||||
|
uint count = _br.ReadUInt32();
|
||||||
|
for(int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
int bytes = (int)_br.ReadUInt16();
|
||||||
|
ExplosionParams explParams = new ExplosionParams(_br.ReadBytes(bytes));
|
||||||
|
ItemValue explValue = null;
|
||||||
|
if (_br.ReadBoolean())
|
||||||
|
{
|
||||||
|
explValue = new ItemValue();
|
||||||
|
explValue.Read(_br);
|
||||||
|
}
|
||||||
|
CustomExplosionManager.GetCustomParticleComponents(explParams._explosionData.ParticleIndex, out ExplosionComponent component);
|
||||||
|
|
||||||
|
ExplosionValue value = new ExplosionValue()
|
||||||
|
{
|
||||||
|
Component = component,
|
||||||
|
CurrentExplosionParams = explParams,
|
||||||
|
CurrentItemValue = explValue?.Clone()
|
||||||
|
};
|
||||||
|
CustomExplosionManager.PushLastInitComponent(value);
|
||||||
|
GameObject obj = CustomExplosionManager.InitializeParticle(component, explParams._worldPos - Origin.position, explParams._rotation);
|
||||||
|
obj.GetComponent<NetSyncHelper>().OnConnectedToServer(_br);
|
||||||
|
}
|
||||||
|
CustomExplosionManager.PopLastInitComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override NetPackageDirection PackageDirection
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return NetPackageDirection.ToClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetLength()
|
||||||
|
{
|
||||||
|
return 8 + data.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] data;
|
||||||
|
}
|
||||||
22
Scripts/Utilities/PlatformIndependentHash.cs
Normal file
22
Scripts/Utilities/PlatformIndependentHash.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public static class PlatformIndependentHash
|
||||||
|
{
|
||||||
|
public static int StringToInt32(string str)
|
||||||
|
{
|
||||||
|
byte[] encoded = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(str));
|
||||||
|
return BitConverter.ToInt32(encoded, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UInt16 StringToUInt16(string str)
|
||||||
|
{
|
||||||
|
byte[] encoded = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(str));
|
||||||
|
return (UInt16)BitConverter.ToUInt32(encoded, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
31
Scripts/Utilities/StreamUtilsCompressed.cs
Normal file
31
Scripts/Utilities/StreamUtilsCompressed.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public static class StreamUtilsCompressed
|
||||||
|
{
|
||||||
|
public static void Write(BinaryWriter _bw, Vector3 vec)
|
||||||
|
{
|
||||||
|
_bw.Write(Mathf.FloatToHalf(vec.x));
|
||||||
|
_bw.Write(Mathf.FloatToHalf(vec.y));
|
||||||
|
_bw.Write(Mathf.FloatToHalf(vec.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 ReadHalfVector3(BinaryReader _br)
|
||||||
|
{
|
||||||
|
return new Vector3(Mathf.HalfToFloat(_br.ReadUInt16()), Mathf.HalfToFloat(_br.ReadUInt16()), Mathf.HalfToFloat(_br.ReadUInt16()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(BinaryWriter _bw, Quaternion rot)
|
||||||
|
{
|
||||||
|
_bw.Write(Mathf.FloatToHalf(rot.x));
|
||||||
|
_bw.Write(Mathf.FloatToHalf(rot.y));
|
||||||
|
_bw.Write(Mathf.FloatToHalf(rot.z));
|
||||||
|
_bw.Write(Mathf.FloatToHalf(rot.w));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion ReadHalfQuaternion(BinaryReader _br)
|
||||||
|
{
|
||||||
|
return new Quaternion(Mathf.HalfToFloat(_br.ReadUInt16()), Mathf.HalfToFloat(_br.ReadUInt16()), Mathf.HalfToFloat(_br.ReadUInt16()), Mathf.HalfToFloat(_br.ReadUInt16()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BIN
editbin.exe
Normal file
BIN
editbin.exe
Normal file
Binary file not shown.
Reference in New Issue
Block a user