Skip to content

Commit

Permalink
Merge pull request #8 from jonathan-robertson/types
Browse files Browse the repository at this point in the history
Improve Entity Recovery, Skip Falling Blocks, Trees, and Supply Plane/Crate
  • Loading branch information
jonathan-robertson authored Dec 31, 2024
2 parents 3bde678 + a72909f commit e8b884b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 14 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.4] - 2024-12-30

- pile entities if present at destination
- skip falling blocks, trees, supply plane/crate
- snap recovered entity to center of tile

## [0.1.3] - 2024-12-30

- further reduce and refine logging
Expand Down
2 changes: 1 addition & 1 deletion ModInfo.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<config>
<Name value="kanaverum-off-world-fix" />
<DisplayName value="Off World Fix" />
<Version value="0.1.3" />
<Version value="0.1.4" />
<Description value="Fix 'entities have fallen off the world' warning by moving those entities to the surface." />
<Author value="Jonathan Robertson (Kanaverum)" />
<Website value="https://github.com/jonathan-robertson/off-world-fix" />
Expand Down
Binary file modified OffWorldFix.dll
Binary file not shown.
56 changes: 43 additions & 13 deletions src/Patches/Entity.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using HarmonyLib;
using OffWorldFix.Utilities;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace OffWorldFix.Patches
{
[HarmonyPatch(typeof(Entity), nameof(Entity.MarkToUnload))]
internal class Entity_MarkToUnload_Patches
{
private static readonly ModLog<Entity_MarkToUnload_Patches> _log = new ModLog<Entity_MarkToUnload_Patches>();
private static readonly Vector3 BLOCK_CENTER = new Vector3(0.5f, 0, 0.5f);

/// <summary>
///
Expand All @@ -30,27 +33,44 @@ public static bool Prefix(Entity __instance)
return true;
}

// TODO: check ownership... maybe teleport backpacks directly in front of player, for instance?

//switch (__instance.GetType())
//{
// // TODO: check more
// default:
// _log.Trace($"detected type: {__instance.GetType()}");
// // TODO: do more
// break;
//}
switch (__instance)
{
// case EntityDrone _: // try to recover
// case EntityBackpack _: // try to recover
// TODO: check ownership... maybe teleport backpacks directly in front of player, for instance?
case EntityFallingBlock _:
case EntityFallingTree _:
case EntitySupplyCrate _:
case EntitySupplyPlane _:
return true; // immediately return for removal
}

if (!IsWithinWorldBoundsY(__instance.position))
{
var newPos = __instance.position;
newPos.y = GameManager.Instance.World.GetHeightAt(__instance.position.x, __instance.position.z);
var newPos = __instance.GetBlockPosition() + BLOCK_CENTER;
var entitySize = new Vector3(__instance.width, __instance.height, __instance.depth);

// find new y position based on height
newPos.y = GameManager.Instance.World.GetHeightAt(__instance.position.x, __instance.position.z) + entitySize.y;
if (!IsWithinWorldBoundsY(newPos))
{
_log.Trace($"A valid position could not be determined to recover {__instance.entityId}; allowing entity unload.");
return true;
}
while (GetEntitiesAt(newPos, entitySize).Count > 0 && newPos.y < ModApi.MAP_MAX.y)
{
newPos.y += entitySize.y;
}
if (newPos.y >= ModApi.MAP_MAX.y)
{
_log.Trace($"A valid position was crawled but could not be determined to recover {__instance.entityId} due to too many entities at each possible vertical respawn destination; allowing entity unload.");
return true; // TODO: test!
}

// move entity
_log.Info($"Detected {__instance.entityType} entity {__instance.entityId} ({__instance.GetType()} // {__instance.GetDebugName()}) fell out of bottom of world; repositioning from {__instance.position.ToCultureInvariantString()} to {newPos.ToCultureInvariantString()}");
__instance.SetVelocity(Vector3.zero);
__instance.SetPosition(newPos);
ConnectionManager.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageEntityTeleport>().Setup(__instance), false, -1, -1, -1, __instance.position, 192);
return false;
Expand All @@ -63,18 +83,28 @@ public static bool Prefix(Entity __instance)
return true;
}

private static bool IsWithinWorldBoundsXAndZ(UnityEngine.Vector3 position)
private static bool IsWithinWorldBoundsXAndZ(Vector3 position)
{
return position.x > ModApi.MAP_MIN.x
&& position.z > ModApi.MAP_MIN.z
&& position.x <= ModApi.MAP_MAX.x
&& position.z <= ModApi.MAP_MAX.z;
}

private static bool IsWithinWorldBoundsY(UnityEngine.Vector3 position)
private static bool IsWithinWorldBoundsY(Vector3 position)
{
return position.y > ModApi.MAP_MIN.y
&& position.y <= ModApi.MAP_MAX.y;
}

/// <summary>
/// Retrieve all entities currently within the given block position.
/// </summary>
/// <param name="blockPos">Vector3i block position to check for entities within.</param>
/// <returns>List of entities currently within the provided block position.</returns>
private static List<EntityAlive> GetEntitiesAt(Vector3 pos, Vector3 entitySize)
{
return GameManager.Instance.World.GetLivingEntitiesInBounds(null, new Bounds(pos, entitySize));
}
}
}

0 comments on commit e8b884b

Please sign in to comment.