W.I.P. extra Effects II: Almost...

This commit is contained in:
melchior 2022-07-24 20:41:19 -04:00
parent b0c6c8ef6b
commit 1f65f75ca5
8 changed files with 258 additions and 46 deletions

View file

@ -86,7 +86,7 @@
<Compile Include="Harmony\GenericItemMortalityDetector.cs" />
<Compile Include="Data\AMR_Config.cs" />
<Compile Include="Data\RecoveryEntryTable.cs" />
<Compile Include="CollectableBehaviors\DirectSprayCooler_Behavior.cs" />
<Compile Include="Blocks\BlockWateringCanPlus.cs" />
</ItemGroup>
<ItemGroup>
<None Include="modinfo.json">
@ -127,7 +127,6 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="assets\fma\patches\wateringcan_behavior.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
@ -151,6 +150,9 @@
<Folder Include="Items\" />
<Folder Include="Harmony\" />
<Folder Include="CollectableBehaviors\" />
<Folder Include="Blocks\" />
<Folder Include="assets\fma\sounds\" />
<Folder Include="assets\fma\sounds\sfx\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,124 @@
using System;
using System.Text;
using Vintagestory.API.Client;
using Vintagestory.API.Common;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.Config;
using Vintagestory.API.MathTools;
using Vintagestory.API.Server;
using Vintagestory.GameContent;
namespace AnvilMetalRecovery
{
public class BlockWateringCanPlus : BlockWateringCan
{
private const float coolRateDefault = 5.0f;
protected ICoreAPI CoreAPI { get { return this.api; } }
protected ICoreServerAPI ServerAPI { get { return this.api as ICoreServerAPI; } }
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 AssetLocation TargetCode = new AssetLocation(@"game", @"wateringcan-burned");
/// <summary>
/// DO OnHeldInteractStep
/// </summary>
/// <returns>The held interact step.</returns>
/// <param name="secondsUsed">Seconds used.</param>
/// <param name="slot">Slot.</param>
/// <param name="byEntity">By entity.</param>
/// <param name="blockSel">Block sel.</param>
/// <param name="entitySel">Entity sel.</param>
/// <remarks>
/// Had to do it this way the base class _NEVER_ invokes the block-behavior virtual...
/// </remarks>
public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
{
this.api.Logger.VerboseDebug("BlockWateringCanPlus::OnHeldInteractStep");
var result = base.OnHeldInteractStep(secondsUsed, slot, byEntity, blockSel, entitySel);
PerformBlockCooling(secondsUsed, slot, byEntity, blockSel, entitySel);
return result;
}
private void PerformBlockCooling(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
{
if (blockSel == null) return;
if (byEntity.Controls.Sneak) return;
BlockPos targetPos = blockSel.Position;
if (this.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 = CoreAPI.World.BlockAccessor.GetBlockEntity(targetPos);
if (someBlockEntity is BlockEntityIngotMold) {
var ingotMold = someBlockEntity as BlockEntityIngotMold;
if (ingotMold.fillSide && ingotMold.fillLevelRight > 0 && ingotMold.IsLiquidRight) {
if (server) CoolContents(ingotMold.contentsRight); else GenerateSpecialEffects(blockSel.HitPosition);
}
else if (ingotMold.fillLevelLeft > 0 && ingotMold.IsLiquidLeft) {
if (server) CoolContents(ingotMold.contentsLeft); else GenerateSpecialEffects(blockSel.HitPosition);
}
return;
}
if (someBlockEntity is BlockEntityToolMold) {
var toolMold = someBlockEntity as BlockEntityToolMold;
if (toolMold.fillLevel > 0 && toolMold.IsLiquid) {
if (server) CoolContents(toolMold.metalContent); else GenerateSpecialEffects(blockSel.HitPosition);
}
return;
}
}
}
}
internal void GenerateSpecialEffects(Vec3d here)
{
var steamParticles = new SimpleParticleProperties {
MinPos = here,
AddPos = here.AddCopy(0.1,0.1,0.1),
MinQuantity = 8,
AddQuantity = 24,
Color = ColorUtil.ToRgba(100, 225, 225, 225),
GravityEffect = -0.015f,
WithTerrainCollision = 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,
//VertexFlags = 32
};
ClientAPI.World.SpawnParticles(steamParticles );
ClientAPI.World.PlaySoundAt(CoolSoundEffect, here.X,here.Y,here.Z, null, false, 16 );
}
internal void CoolContents(ItemStack itemStack)
{
var temperature = itemStack.Collectible.GetTemperature(CoreAPI.World, itemStack);
if (temperature > 25f)//TODO: USE local AMBIENT Temp
itemStack.Collectible.SetTemperature(CoreAPI.World, itemStack, (temperature - coolRateDefault), false);
#if DEBUG
CoreAPI.Logger.VerboseDebug("Reduced Molten metal temp: {0:F1} ", temperature);
#endif
}
}
}

View file

@ -1,8 +1,10 @@
using System;
using Vintagestory.API.Common;
using Vintagestory.API.Config;
using Vintagestory.API.Datastructures;
using Vintagestory.API.MathTools;
using Vintagestory.API.Server;
using Vintagestory.GameContent;
using Vintagestory.Server;
@ -13,77 +15,90 @@ namespace AnvilMetalRecovery
/// Direct spray cooler collectable behavior.
/// </summary>
/// <remarks>*TSSSSS!*</remarks>
public class DirectSprayCooler_Behavior : BlockBehavior
public class DirectSprayCooler_Behavior : CollectibleBehavior
{
public const string ClassName = @"directspraycooler";
private const string coolRateKey = @"coolRate";
private const float coolRateDefault = 0.5f;
private BlockWateringCan WateringCan;
protected ICoreAPI CoreAPI { get; set; }
protected ICoreAPI CoreAPI { get; private set;}
protected ICoreServerAPI ServerAPI { get; private set;}
public const string ClassName = @"directspraycooler";
public float CoolRate { get; private set;}
public DirectSprayCooler_Behavior(Block block) : base(block)
{
public DirectSprayCooler_Behavior(CollectibleObject collecta) : base(collecta)
{
}
public override void Initialize(JsonObject properties)
{
base.Initialize(properties);
CoolRate = properties[coolRateKey].AsFloat(coolRateDefault);
}
public override void OnLoaded(ICoreAPI api)
{
#if DEBUG
api.Logger.VerboseDebug("DirectSprayCooler_Behavior::OnLoaded...");
#endif
base.OnLoaded(api);
CoreAPI = api;
WateringCan = block as BlockWateringCan;
if (WateringCan == null) { throw new InvalidOperationException(string.Format("Block with code '{0}' does not inherit from BlockWateringCan, which is required", block.Code)); }
#if DEBUG
api.Logger.VerboseDebug("DirectSprayCooler_Behavior::OnLoaded...");
#endif
WateringCan = this.collObj as BlockWateringCan;
if (WateringCan == null) { throw new InvalidOperationException(string.Format("Block with code '{0}' does not inherit from BlockWateringCan, which is required", collObj.Code)); }
}
public override void GetHeldItemInfo(ItemSlot inSlot, System.Text.StringBuilder dsc, IWorldAccessor world, bool withDebugInfo)
{
dsc.Append(Lang.Get("fma:spray_cooler_text"));
}
public override void Initialize(JsonObject properties)
public override void OnHeldInteractStart(ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handHandling, ref EnumHandling handling)
{
#if DEBUG
CoreAPI.Logger.VerboseDebug("DirectSprayCooler_Behavior::Initialize...");
byEntity.World.Logger.VerboseDebug("DirectSprayCooler_Behavior::OnHeldInteractStart...");
#endif
CoolRate = properties[coolRateKey].AsFloat(coolRateDefault);
base.Initialize(properties);
handHandling = EnumHandHandling.PreventDefault;
handling = EnumHandling.PassThrough; //EnumHandling.PreventDefault;
}
internal void coolContents(ItemStack itemStack)
public override void OnHeldInteractStop(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, ref EnumHandling handling)
{
var temperature = itemStack.Collectible.GetTemperature(CoreAPI.World, itemStack);
if (temperature > 25f)//TODO: USE local AMBIENT Temp
itemStack.Collectible.SetTemperature(CoreAPI.World, itemStack, (temperature - CoolRate), false);
#if DEBUG
CoreAPI.Logger.VerboseDebug("Reduced Molten metal temp: {0:F1} ", temperature);
byEntity.World.Logger.VerboseDebug("DirectSprayCooler_Behavior::OnHeldInteractStop...");
#endif
handling = EnumHandling.PassThrough;
}
public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, ref EnumHandling handling)
{
#if DEBUG
CoreAPI.Logger.VerboseDebug("DirectSprayCooler_Behavior::OnHeldInteractStep...");
byEntity.World.Logger.VerboseDebug("DirectSprayCooler_Behavior::OnHeldInteractStep...");
#endif
handling = EnumHandling.PassThrough;
CoreAPI = byEntity.World.Api;
if (blockSel == null) return false;
if (byEntity.Controls.Sneak) return false;
if (CoreAPI.World.Side.IsServer( ))
{
{
ServerAPI = byEntity.World.Api as ICoreServerAPI;;
if (WateringCan.GetRemainingWateringSeconds(slot.Itemstack) >= 0.5f) {
BlockPos targetPos = blockSel.Position;
var someBlock = CoreAPI.World.BlockAccessor.GetBlock(targetPos);
var someBlock = ServerAPI.World.BlockAccessor.GetBlock(targetPos);
if (someBlock != null
&& someBlock.BlockMaterial == EnumBlockMaterial.Ceramic
&& (someBlock.Class == @"BlockIngotMold" || someBlock.Class == @"BlockToolMold"))
{
BlockEntityIngotMold ingotBE = CoreAPI.World.BlockAccessor.GetBlockEntity(targetPos) as BlockEntityIngotMold;
BlockEntityIngotMold ingotBE = ServerAPI.World.BlockAccessor.GetBlockEntity(targetPos) as BlockEntityIngotMold;
if (ingotBE != null)
{
@ -91,11 +106,11 @@ namespace AnvilMetalRecovery
{ coolContents(ingotBE.contentsRight); }
else if (ingotBE.IsLiquidLeft)
{ coolContents(ingotBE.contentsLeft); }
return false;
handling = EnumHandling.PreventDefault;//?
return true;
}
BlockEntityToolMold toolBE = CoreAPI.World.BlockAccessor.GetBlockEntity(targetPos) as BlockEntityToolMold;
BlockEntityToolMold toolBE = ServerAPI.World.BlockAccessor.GetBlockEntity(targetPos) as BlockEntityToolMold;
if (toolBE != null)
{
if (toolBE.IsLiquid) { coolContents(toolBE.metalContent); }
@ -104,13 +119,24 @@ namespace AnvilMetalRecovery
}
}
}
}
handling = EnumHandling.PassThrough;
return false;
}
internal void coolContents(ItemStack itemStack)
{
var temperature = itemStack.Collectible.GetTemperature(CoreAPI.World, itemStack);
if (temperature > 25f)//TODO: USE local AMBIENT Temp
itemStack.Collectible.SetTemperature(CoreAPI.World, itemStack, (temperature - CoolRate), false);
#if DEBUG
CoreAPI.Logger.VerboseDebug("Reduced Molten metal temp: {0:F1} ", temperature);
#endif
}
}
}

View file

@ -4,6 +4,7 @@ using System.Linq;
using Vintagestory.API.Common;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.Server;
using Vintagestory.API.Util;
using Vintagestory.Common;
using Vintagestory.Server;
@ -11,6 +12,39 @@ namespace AnvilMetalRecovery
{
internal static class Helpers
{
internal static void AddBlockBehavior(this ICoreAPI coreAPI, AssetLocation assetName, string behaviorCode, Type blockBehaviorType)
{
if (assetName.Valid && assetName.IsWildCard == false)
{
var targetBlock = coreAPI.World.GetBlock(assetName);
var newBlockBehavior = coreAPI.ClassRegistry.CreateBlockBehavior(targetBlock, behaviorCode);
if (targetBlock != null && newBlockBehavior != null)
{
targetBlock.BlockBehaviors = targetBlock.BlockBehaviors.Append(newBlockBehavior);
targetBlock.CollectibleBehaviors = targetBlock.CollectibleBehaviors.Append(newBlockBehavior);
}
else {
coreAPI.Logger.Warning($"Could not append new BLOCK BEHAVIOR ({blockBehaviorType.Name}): '{behaviorCode}' to block [{assetName}]!");
}
}
}
internal static void AddCollectableBehavior(this ICoreAPI coreAPI, AssetLocation assetName, string behaviorCode, Type blockBehaviorType)
{
if (assetName.Valid && assetName.IsWildCard == false) {
var targetBlock = coreAPI.World.GetBlock(assetName);
var newCollectableBehavior = coreAPI.ClassRegistry.CreateCollectibleBehavior(targetBlock, behaviorCode);
if (targetBlock != null && newCollectableBehavior != null) {
targetBlock.CollectibleBehaviors = targetBlock.CollectibleBehaviors.Append(newCollectableBehavior);
}
else {
coreAPI.Logger.Warning($"Could not append new COLLECTABLE BEHAVIOR ({blockBehaviorType.Name}): '{behaviorCode}' to something [{assetName}]!");
}
}
}
internal static void ReplaceBlockEntityType(this ClassRegistry registry, string className, Type blockentity)
{
if (registry.blockEntityClassnameToTypeMapping.ContainsKey(className)) {
@ -28,6 +62,14 @@ namespace AnvilMetalRecovery
}
}
internal static void ReplaceBlockClassType(this ClassRegistry registry, string className, Type replacer)
{
if (registry.BlockClassToTypeMapping.ContainsKey(className)) {
//replace it
registry.BlockClassToTypeMapping[className] = replacer;
}
}
internal static int? Hitpoints(this ItemStack itemStack)
{
if (itemStack == null || itemStack.Attributes == null) return null;

View file

@ -30,8 +30,6 @@ namespace AnvilMetalRecovery
public const float IngotVoxelDefault = 2.38f;
public const string ItemDamageChannelName = @"ItemDamageEvents";
internal IServerNetworkChannel _ConfigDownlink;
internal IClientNetworkChannel _ConfigUplink;
@ -110,7 +108,8 @@ namespace AnvilMetalRecovery
this.CoreAPI = api;
RegisterItemMappings( );
RegisterBlockBehaviors( );
//RegisterBlockBehaviors( );
#if DEBUG
//Harmony.DEBUG = true;
@ -137,10 +136,11 @@ namespace AnvilMetalRecovery
PrepareDownlinkChannel( );
ServerAPI.Event.PlayerJoin += SendClientConfigMessage;
ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.Shutdown, PersistServersideConfig);
ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.GameReady, MaterialDataGathering);
ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.RunGame, CacheRecoveryDataTable);
ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.GameReady, MaterialDataGathering);
PerformBlockClassSwaps();
ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.RunGame, CacheRecoveryDataTable);
SetupGeneralObservers( );
SetupGeneralObservers( );
Mod.Logger.VerboseDebug("Anvil Metal Recovery - should be installed...");
@ -163,6 +163,9 @@ namespace AnvilMetalRecovery
}
ListenForServerConfigMessage( );
//ClientCore.Event.RegisterCallback(PerformBlockClassSwaps, 0);
PerformBlockClassSwaps();
Mod.Logger.VerboseDebug("Anvil Metal Recovery - should be installed...");
}
@ -178,7 +181,21 @@ namespace AnvilMetalRecovery
#if DEBUG
Mod.Logger.Debug("RegisterBlockBehaviors");
#endif
this.CoreAPI.RegisterBlockBehaviorClass(DirectSprayCooler_Behavior.ClassName, typeof(DirectSprayCooler_Behavior));
//this.CoreAPI.RegisterBlockBehaviorClass(DirectSprayCooler_Behavior.ClassName, typeof(DirectSprayCooler_Behavior));
//this.CoreAPI.RegisterCollectibleBehaviorClass(DirectSprayCooler_Behavior.ClassName, typeof(DirectSprayCooler_Behavior));
}
private void PerformBlockClassSwaps(float delta = 0.0f)
{
PerformBlockClassSwaps( );
}
private void PerformBlockClassSwaps()
{
if (CoreAPI.Side == EnumAppSide.Server)
this.ServerCore.ClassRegistryNative.ReplaceBlockClassType(BlockWateringCanPlus.BlockClassName, typeof(BlockWateringCanPlus));
else
this.ClientCore.ClassRegistryNative.ReplaceBlockClassType(BlockWateringCanPlus.BlockClassName, typeof(BlockWateringCanPlus));
}
private void SetupGeneralObservers( ){
@ -247,7 +264,7 @@ namespace AnvilMetalRecovery
#endif
if (networkMessage != null) {
Mod.Logger.Debug("Message value; Recover Broken Tools:{0}, VoxelEquiv#{1:F2}, Blacklist #{2}", networkMessage.ToolFragmentRecovery, networkMessage.VoxelEquivalentValue, networkMessage.BlackList.Count);
Mod.Logger.Debug("Message value; Recover Broken Tools:{0}, VoxelEquiv:{1:F2}, Tool Recovery {3:P0}, Blacklisted:{2}", networkMessage.ToolFragmentRecovery, networkMessage.VoxelEquivalentValue, networkMessage.BlackList.Count, networkMessage.ToolRecoveryRate);
this.CachedConfiguration = networkMessage;
}
}

View file

@ -127,7 +127,7 @@ namespace AnvilMetalRecovery
RecoveryEntry rec = itemToVoxelLookup[hotbarData.ItemCode];
#if DEBUG
Mod.Logger.VerboseDebug("broken-item {0} WORTH: {1:F1}*{2} units", hotbarData.ItemCode.ToString( ), (rec.Quantity * CachedConfiguration.VoxelEquivalentValue), rec.IngotCode.ToShortString( ));
Mod.Logger.VerboseDebug("broken-item {0} abs. WORTH: {1:F1}*{2} units", hotbarData.ItemCode.ToString( ), (rec.Quantity * CachedConfiguration.VoxelEquivalentValue), rec.IngotCode.ToShortString( ));
#endif
if (String.IsNullOrEmpty(hotbarData.PlayerUID) || String.IsNullOrEmpty(hotbarData.InventoryID)) return;

View file

@ -26,4 +26,5 @@
"fma:item-metal_fragments":"Broken metal fragments.",
"fma:itemdesc-item-metal_fragments": "Try, chopping it apart with a Chisel...",
"fma:metal_worth":"Worth {0} units of {1}.",
"fma:spray_cooler_text":"\n...mabey it can cool off hot things, too?",
}

View file

@ -4,7 +4,7 @@
"path": "/behaviorsByType/*-burned",
"value": [
{
name: "directspraycooler", properties: { coolRate: 1.0 }
name: "directspraycooler", properties: { "coolRate": 1.0 }
}
],
"file": "game:blocktypes/clay/wateringcan.json"