Re-work Wateringcan+ to be Harmony patch

This commit is contained in:
melchior 2022-09-02 20:50:48 -04:00
parent 3ce516f1d4
commit 795dcf2d46
5 changed files with 219 additions and 26 deletions

View file

@ -86,8 +86,8 @@
<Compile Include="Harmony\GenericItemMortalityDetector.cs" />
<Compile Include="Data\AMR_Config.cs" />
<Compile Include="Data\RecoveryEntryTable.cs" />
<Compile Include="Blocks\BlockWateringCanPlus.cs" />
<Compile Include="BlockBehaviors\MoldDestructionRecovererBehavior.cs" />
<Compile Include="Harmony\WateringCanDaptor.cs" />
</ItemGroup>
<ItemGroup>
<None Include="modinfo.json">
@ -129,6 +129,7 @@
</None>
<None Include="assets\fma\patches\wateringcan_behavior.json">
</None>
<None Include="Blocks\BlockWateringCanPlus.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="assets\" />

View file

@ -43,7 +43,7 @@ namespace AnvilMetalRecovery
protected ICoreClientAPI ClientAPI { get { return this.api as ICoreClientAPI; } }
public readonly AssetLocation CoolSoundEffect = new AssetLocation(@"game", @"sounds/sizzle");
public static readonly string BlockClassName = @"BlockWateringCan";
public static readonly string BlockClassName = @"BlockWateringCanPlus";
public static readonly AssetLocation TargetCode = new AssetLocation(@"game", @"wateringcan-burned");
/// <summary>

View file

@ -0,0 +1,177 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using HarmonyLib;
using Vintagestory.API.Client;
using Vintagestory.API.Common;
using Vintagestory.API.Config;
using Vintagestory.API.Datastructures;
using Vintagestory.API.MathTools;
using Vintagestory.API.Server;
using Vintagestory.GameContent;
namespace AnvilMetalRecovery.Patches
{
/// <summary>
/// Harmony patcher class to wrap Watering-can class
///</summary>
[HarmonyPatch(typeof(BlockWateringCan))]
public class WateringCanDaptor
{
[HarmonyPrepare]
private static bool DeduplicatePatching(MethodBase original, Harmony harmony)
{
if (original != null) {
foreach (var patched in harmony.GetPatchedMethods( )) {
if (patched.Name == original.Name) return false; //SKIPS PATCHING, its already there
}
}
return true;//patch all other methods
}
[HarmonyPostfix]
[HarmonyPatch(nameof(BlockWateringCan.OnHeldInteractStep))]
public static void OnHeldInteractStep(ref bool __result, float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, BlockWateringCan __instance)
{
var coreAPI = byEntity.Api;
#if DEBUG
coreAPI.Logger.VerboseDebug("BlockWateringCanPlus::OnHeldInteractStep");
#endif
var wc = new WateringCanAssist(__instance, byEntity.Api);
wc.PerformBlockCooling(secondsUsed, slot, byEntity, blockSel, entitySel);
}
}
public class WateringCanAssist
{
private ICoreAPI CoreAPI { get; set; }
private ICoreServerAPI ServerAPI { get { return CoreAPI as ICoreServerAPI; } }
private ICoreClientAPI ClientAPI { get { return CoreAPI as ICoreClientAPI; } }
private BlockWateringCan Original { get; set; }
private const float coolRateDefault = 0.0075f;
private const float flashPointTemp = 100f;
private SimpleParticleProperties steamParticles = new SimpleParticleProperties {
MinPos = new Vec3d( ),
AddPos = new Vec3d( ),
MinQuantity = 6,
AddQuantity = 12,
Color = ColorUtil.ToRgba(100, 225, 225, 225),
OpacityEvolve = new EvolvingNatFloat(EnumTransformFunction.LINEAR, 1.0f),
GravityEffect = -0.015f,
WithTerrainCollision = false,
ShouldDieInLiquid = true,
ParticleModel = EnumParticleModel.Quad,
LifeLength = 2.0f,
MinVelocity = new Vec3f(-0.25f, 0.1f, -0.25f),
AddVelocity = new Vec3f(0.25f, 0.1f, 0.25f),
MinSize = 0.075f,
MaxSize = 0.1f,
WindAffected = true,
WindAffectednes = 0.4f,
};
public readonly AssetLocation CoolSoundEffect = new AssetLocation(@"game", @"sounds/sizzle");
public WateringCanAssist(BlockWateringCan original, ICoreAPI api)
{
this.CoreAPI = api;
this.Original = original;
}
public void PerformBlockCooling(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
{
if (blockSel == null) return;
if (byEntity.Controls.Sneak) return;
if ((DateTime.Now.Millisecond / 100) % 2 == 1) return;
BlockPos targetPos = blockSel.Position;
if (!slot.Empty && Original.GetRemainingWateringSeconds(slot.Itemstack) >= 0.1f) {
var server = (CoreAPI.World.Side.IsServer( ));
var someBlock = CoreAPI.World.BlockAccessor.GetBlock(targetPos);
if (someBlock != null
&& someBlock.BlockMaterial == EnumBlockMaterial.Ceramic
&& (someBlock.Class == @"BlockIngotMold" || someBlock.Class == @"BlockToolMold")) {
var someBlockEntity = server ? ServerAPI.World.BlockAccessor.GetBlockEntity(targetPos) : ClientAPI.World.BlockAccessor.GetBlockEntity(targetPos);
#if DEBUG
CoreAPI.Logger.VerboseDebug("Ok, its an Tool/Ingot mold.: {0}", someBlockEntity);
#endif
if (someBlockEntity is BlockEntityIngotMold) {
var rightSide = AimAtRight(blockSel.HitPosition);
var ingotMold = someBlockEntity as BlockEntityIngotMold;
if (rightSide && (ingotMold.fillLevelRight > 0 && ingotMold.TemperatureRight > flashPointTemp)) {
if (server) CoolContents(ingotMold.contentsRight); else GenerateSpecialEffects(blockSel.Position, blockSel.HitPosition, byEntity as EntityPlayer);
ingotMold.MarkDirty( );
}
else if (ingotMold.fillLevelLeft > 0 && ingotMold.TemperatureLeft > flashPointTemp) {
if (server) CoolContents(ingotMold.contentsLeft); else GenerateSpecialEffects(blockSel.Position, blockSel.HitPosition, byEntity as EntityPlayer);
ingotMold.MarkDirty( );
}
return;
}
if (someBlockEntity is BlockEntityToolMold) {
var toolMold = someBlockEntity as BlockEntityToolMold;
if (toolMold.fillLevel > 0 && toolMold.Temperature > flashPointTemp) {
if (server) CoolContents(toolMold.metalContent); else GenerateSpecialEffects(blockSel.Position, blockSel.HitPosition, byEntity as EntityPlayer);
toolMold.MarkDirty( );
}
return;
}
}
}
}
internal void GenerateSpecialEffects(BlockPos blockLoc, Vec3d aimPoint, EntityPlayer playerEntity)
{
if ((DateTime.Now.Millisecond / 333) % 2 == 1) return;
steamParticles.MinPos = blockLoc.ToVec3d( ).AddCopy(aimPoint);
steamParticles.AddPos = new Vec3d(0.05f, 0f, 0.05f);
#if DEBUG
CoreAPI.Logger.VerboseDebug("Generate steam particles");
#endif
ClientAPI.World.SpawnParticles(steamParticles, playerEntity.Player);
ClientAPI.World.PlaySoundAt(CoolSoundEffect, playerEntity, playerEntity.Player, randomizePitch: false, volume: 0.5f);
}
internal void CoolContents(ItemStack itemStack)
{
var temperature = itemStack.Collectible.GetTemperature(CoreAPI.World, itemStack);
if (temperature > 20f)//TODO: USE local AMBIENT Temp
itemStack.Collectible.SetTemperature(CoreAPI.World, itemStack, temperature - (temperature * coolRateDefault), false);
(itemStack.Attributes["temperature"] as ITreeAttribute)?.SetFloat("cooldownSpeed", 400);
#if DEBUG
CoreAPI.Logger.VerboseDebug("Cooled Molten metal, temp: {0:F1} ", temperature);
#endif
}
internal bool AimAtRight(Vec3d hitPosition)
{
return hitPosition.X >= 0.5f;
}
}
}

View file

@ -14,9 +14,9 @@ using Vintagestory.GameContent;
using Vintagestory.Server;
/* IDEAS / ISSUES
* # Watering Can (molten-metal state) Ingot Cooling *Tssss*
* # Ingot breaks -> Metal fragments / bits (or a blob?)
* # Tool-break configurable ratio
* # DONE: Watering Can (molten-metal state) Ingot Cooling *Tssss*
* # WIP : Ingot breaks -> Metal fragments / bits (or a blob?)
* # DONE: Tool-break configurable ratio
*/
namespace AnvilMetalRecovery
{
@ -108,19 +108,19 @@ namespace AnvilMetalRecovery
{
this.CoreAPI = api;
RegisterItemMappings( );
RegisterItemClassMappings( );
//RegisterBlockClassMappings( );
RegisterBlockBehaviors( );
if (api.Side.IsServer())
{
if (api is ServerCoreAPI) {
ServerCore = api as ServerCoreAPI;
}
ServerCore.Event.AssetsFinalizers += AttachExtraBlockBehaviors;
}
else
{
ClientCore = api as ClientCoreAPI;
ClientCore.Event.LevelFinalize += PerformBlockClassSwaps;
ClientCore = api as ClientCoreAPI;
}
#if DEBUG
@ -133,8 +133,7 @@ namespace AnvilMetalRecovery
}
public override void StartServerSide(ICoreServerAPI api)
{
{
PrepareServersideConfig( );
PrepareDownlinkChannel( );
ServerCore.Event.PlayerJoin += SendClientConfigMessage;
@ -144,7 +143,7 @@ namespace AnvilMetalRecovery
SetupGeneralObservers( );
Mod.Logger.VerboseDebug("Anvil Metal Recovery - should be installed...");
Mod.Logger.VerboseDebug("Anvil Metal Recovery - should be running...");
#if DEBUG
ServerCore.RegisterCommand("durability", "edit durability of item", " (Held tool) and #", EditDurability, Privilege.give);
@ -156,18 +155,29 @@ namespace AnvilMetalRecovery
{
base.StartClientSide(api);
ListenForServerConfigMessage( );
ListenForServerConfigMessage( );
Mod.Logger.VerboseDebug("Anvil Metal Recovery - should be installed...");
Mod.Logger.VerboseDebug("Anvil Metal Recovery - should be running...");
#if DEBUG
//ClientCore.Event.LevelFinalize += DebugStuffs;
#endif
}
public override void AssetsLoaded(ICoreAPI api)
{
if (api.Side.IsServer( )) { PerformBlockClassSwaps( );}
Mod.Logger.VerboseDebug("AssetsLoaded");
}
private void RegisterItemMappings( )
public override void AssetsFinalize(ICoreAPI api)
{
Mod.Logger.VerboseDebug("AssetsFinalize");
//PerformBlockClassSwaps( );
AttachExtraBlockBehaviors( );
}
private void RegisterItemClassMappings( )
{
this.CoreAPI.RegisterItemClass(@"VariableMetalItem", typeof(VariableMetalItem));
this.CoreAPI.RegisterItemClass(@"SmartSmeltableItem", typeof(SmartSmeltableItem));
@ -180,19 +190,27 @@ namespace AnvilMetalRecovery
#endif
this.CoreAPI.RegisterBlockBehaviorClass(MoldDestructionRecovererBehavior.BehaviorClassName, typeof(MoldDestructionRecovererBehavior));
this.CoreAPI.RegisterCollectibleBehaviorClass(MoldDestructionRecovererBehavior.BehaviorClassName, typeof(MoldDestructionRecovererBehavior));
}
}
/*
private void PerformBlockClassSwaps()
{
#if DEBUG
Mod.Logger.Debug("PerformBlockClassSwaps");
#endif
if (CoreAPI.Side == EnumAppSide.Server)
this.ServerCore.ClassRegistryNative.ReplaceBlockClassType(BlockWateringCanPlus.BlockClassName, typeof(BlockWateringCanPlus));
else
this.ClientCore.ClassRegistryNative.ReplaceBlockClassType(BlockWateringCanPlus.BlockClassName, typeof(BlockWateringCanPlus));
if (ServerCore.World is ServerMain) {
var serverMain = ServerCore.World as ServerMain;
var wateringCanBlock = serverMain.GetBlock(BlockWateringCanPlus.TargetCode);
#if DEBUG
Mod.Logger.VerboseDebug("Change class from {0} to {1}", wateringCanBlock.Class, BlockWateringCanPlus.BlockClassName);
#endif
wateringCanBlock.Class = BlockWateringCanPlus.BlockClassName;
ServerCore.World.Blocks[wateringCanBlock.BlockId] = wateringCanBlock;//Mabey redundant?
}
}*/
private void AttachExtraBlockBehaviors()
{
Collection<AssetLocation> mold_behaviorsAppendList = new Collection<AssetLocation>( ) {
@ -310,7 +328,4 @@ namespace AnvilMetalRecovery
ServerCore.ObjectCache.Add(itemFilterListCacheKey, itemToVoxelLookup);
}
}
}
}

View file

@ -4,7 +4,7 @@
"description" : "Get back smithing discards, broken tool scrap, failed molds; and MORE!",
"authors": ["Melchior"],
"ModID":"metalrecovery",
"version": "0.1.18-rc.2",
"version": "0.1.18-rc.8",
"dependencies": {
"game": "1.17.0-rc.0",
"survival": ""