feat: scaffold ClaimLinkVisualizer, client-side buffer-zone highlighting

This commit is contained in:
2026-07-29 07:39:48 +02:00
commit 0056b443e4
13 changed files with 1129 additions and 0 deletions
@@ -0,0 +1,46 @@
using System.Collections.Generic;
using ProtoBuf;
namespace ClaimLinkVisualizer;
[ProtoContract]
public class ClaimLinkBufferRequest { }
[ProtoContract]
public class BufferCuboidDto
{
[ProtoMember(1)]
public int MinX;
[ProtoMember(2)]
public int MinY;
[ProtoMember(3)]
public int MinZ;
[ProtoMember(4)]
public int MaxX;
[ProtoMember(5)]
public int MaxY;
[ProtoMember(6)]
public int MaxZ;
}
[ProtoContract]
public class ClaimLinkBufferEntryDto
{
[ProtoMember(1)]
public int GroupId;
[ProtoMember(2)]
public List<BufferCuboidDto> Cuboids = new();
}
[ProtoContract]
public class ClaimLinkBufferResponse
{
[ProtoMember(1)]
public List<ClaimLinkBufferEntryDto> Entries = new();
}
@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<OutputPath>bin\$(Configuration)\Mods\mod</OutputPath>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Reference Include="VintagestoryAPI">
<HintPath>$(VINTAGE_STORY)/VintagestoryAPI.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="protobuf-net">
<HintPath>$(VINTAGE_STORY)/Lib/protobuf-net.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ClaimLink">
<HintPath>$(CLAIMLINK)/ClaimLink.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="modinfo.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="modicon.png" Condition="Exists('modicon.png')">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
@@ -0,0 +1,106 @@
using System.Collections.Generic;
using Vintagestory.API.Client;
using Vintagestory.API.Common;
using Vintagestory.API.MathTools;
namespace ClaimLinkVisualizer;
internal static class ClaimLinkVisualizerClient
{
private const int HighlightSlotId = 8341;
private static ICoreClientAPI capi = null!;
private static bool visible;
internal static void Start(ICoreClientAPI api)
{
capi = api;
api.Network
.RegisterChannel(ClaimLinkVisualizerModSystem.ChannelName)
.RegisterMessageType<ClaimLinkBufferRequest>()
.RegisterMessageType<ClaimLinkBufferResponse>()
.SetMessageHandler<ClaimLinkBufferResponse>(OnBufferResponse);
api.Input.RegisterHotKey(
"claimlinkvisualizertoggle",
"Toggle ClaimLink buffer visualization",
GlKeys.J,
HotkeyType.CharacterControls,
ctrlPressed: true
);
api.Input.SetHotKeyHandler("claimlinkvisualizertoggle", OnToggle);
}
private static bool OnToggle(KeyCombination comb)
{
visible = !visible;
if (visible)
capi.Network
.GetChannel(ClaimLinkVisualizerModSystem.ChannelName)
.SendPacket(new ClaimLinkBufferRequest());
else
Clear();
return true;
}
private static void OnBufferResponse(ClaimLinkBufferResponse response)
{
if (!visible)
return;
List<BlockPos> positions = new();
List<int> colors = new();
foreach (ClaimLinkBufferEntryDto entry in response.Entries)
{
int color = HashToColor(entry.GroupId);
foreach (BufferCuboidDto cuboid in entry.Cuboids)
foreach (BlockPos corner in Corners(cuboid))
{
positions.Add(corner);
colors.Add(color);
}
}
capi.World.HighlightBlocks(
capi.World.Player,
HighlightSlotId,
positions,
colors,
EnumHighlightBlocksMode.Absolute,
EnumHighlightShape.Arbitrary
);
}
private static void Clear() =>
capi.World.HighlightBlocks(
capi.World.Player,
HighlightSlotId,
new List<BlockPos>(),
new List<int>()
);
private static IEnumerable<BlockPos> Corners(BufferCuboidDto c)
{
yield return new BlockPos(c.MinX, c.MinY, c.MinZ);
yield return new BlockPos(c.MaxX, c.MinY, c.MinZ);
yield return new BlockPos(c.MinX, c.MaxY, c.MinZ);
yield return new BlockPos(c.MinX, c.MinY, c.MaxZ);
yield return new BlockPos(c.MaxX, c.MaxY, c.MinZ);
yield return new BlockPos(c.MaxX, c.MinY, c.MaxZ);
yield return new BlockPos(c.MinX, c.MaxY, c.MaxZ);
yield return new BlockPos(c.MaxX, c.MaxY, c.MaxZ);
}
private static int HashToColor(int groupId)
{
unchecked
{
uint h = (uint)groupId * 2654435761u;
int r = (byte)(h >> 16);
int g = (byte)(h >> 8);
int b = (byte)h;
return ColorUtil.ColorFromRgba(r, g, b, 255);
}
}
}
@@ -0,0 +1,16 @@
using Vintagestory.API.Client;
using Vintagestory.API.Common;
using Vintagestory.API.Server;
namespace ClaimLinkVisualizer;
public class ClaimLinkVisualizerModSystem : ModSystem
{
internal const string ChannelName = "claimlinkvisualizer";
public override void StartServerSide(ICoreServerAPI api) =>
ClaimLinkVisualizerServer.Start(api);
public override void StartClientSide(ICoreClientAPI api) =>
ClaimLinkVisualizerClient.Start(api);
}
@@ -0,0 +1,47 @@
using System.Collections.Generic;
using ClaimLink;
using Vintagestory.API.MathTools;
using Vintagestory.API.Server;
namespace ClaimLinkVisualizer;
internal static class ClaimLinkVisualizerServer
{
internal static void Start(ICoreServerAPI api)
{
api.Network
.RegisterChannel(ClaimLinkVisualizerModSystem.ChannelName)
.RegisterMessageType<ClaimLinkBufferRequest>()
.RegisterMessageType<ClaimLinkBufferResponse>()
.SetMessageHandler<ClaimLinkBufferRequest>((fromPlayer, _) =>
SendBuffers(api, fromPlayer)
);
}
private static void SendBuffers(ICoreServerAPI api, IServerPlayer toPlayer)
{
ClaimLinkBufferResponse response = new();
foreach (var (groupId, cuboids) in ClaimLinkAPI.BufferMap)
{
ClaimLinkBufferEntryDto entry = new() { GroupId = groupId };
foreach (Cuboidi cuboid in cuboids)
entry.Cuboids.Add(
new BufferCuboidDto
{
MinX = cuboid.MinX,
MinY = cuboid.MinY,
MinZ = cuboid.MinZ,
MaxX = cuboid.MaxX,
MaxY = cuboid.MaxY,
MaxZ = cuboid.MaxZ,
}
);
response.Entries.Add(entry);
}
api.Network
.GetChannel(ClaimLinkVisualizerModSystem.ChannelName)
.SendPacket(response, toPlayer);
}
}
@@ -0,0 +1,16 @@
{
"profiles": {
"Client": {
"commandName": "Executable",
"executablePath": "dotnet",
"commandLineArgs": "\"$(VINTAGE_STORY)/Vintagestory.dll\" --tracelog --addModPath \"$(ProjectDir)/bin/$(Configuration)/Mods\" --addOrigin \"$(ProjectDir)/assets\"",
"workingDirectory": "$(VINTAGE_STORY)"
},
"Server": {
"commandName": "Executable",
"executablePath": "dotnet",
"commandLineArgs": "\"$(VINTAGE_STORY)/VintagestoryServer.dll\" --tracelog --addModPath \"$(ProjectDir)/bin/$(Configuration)/Mods\" --addOrigin \"$(ProjectDir)/assets\"",
"workingDirectory": "$(VINTAGE_STORY)"
}
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"$schema": "https://moddbcdn.vintagestory.at/schema/modinfo.latest.json",
"type": "Code",
"modid": "claimlinkvisualizer",
"name": "ClaimLinkVisualizer",
"side": "Universal",
"authors": [
"anth64"
],
"description": "Visualizes ClaimLink buffer zones client-side.",
"version": "0.0.1",
"dependencies": {
"game": "1.22.5",
"claimlink": "0.1.0"
}
}