Pixi/Pixi/Robots/CubeUtility.cs
2020-05-19 22:03:20 -04:00

418 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using RobocraftX.Common;
using Newtonsoft.Json;
using Unity.Mathematics;
using GamecraftModdingAPI.Blocks;
using GamecraftModdingAPI.Utility;
namespace Pixi.Robots
{
public static class CubeUtility
{
private static Dictionary<uint, string> map = null;
public static RobotStruct? ParseRobotInfo(string robotInfo)
{
try
{
return JsonConvert.DeserializeObject<RobotStruct>(robotInfo);
}
catch (Exception e)
{
Logging.MetaLog(e);
return null;
}
}
public static CubeInfo[] ParseCubes(RobotStruct robot)
{
return ParseCubes(robot.cubeData, robot.colourData);
}
public static CubeInfo[] ParseCubes(string cubeData, string colourData)
{
BinaryBufferReader cubes = new BinaryBufferReader(Convert.FromBase64String(cubeData), 0);
BinaryBufferReader colours = new BinaryBufferReader(Convert.FromBase64String(colourData), 0);
uint cubeCount = cubes.ReadUint();
uint colourCount = colours.ReadUint();
if (cubeCount != colourCount)
{
Logging.MetaLog("Something is fucking broken");
return null;
}
Logging.MetaLog($"Detected {cubeCount} cubes");
CubeInfo[] result = new CubeInfo[cubeCount];
for (int cube = 0; cube < cubeCount; cube++)
{
result[cube] = TranslateSpacialEnumerations(
cubes.ReadUint(),
cubes.ReadByte(),
cubes.ReadByte(),
cubes.ReadByte(),
cubes.ReadByte(),
colours.ReadByte(),
colours.ReadByte(),
colours.ReadByte(),
colours.ReadByte()
);
}
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static CubeInfo TranslateSpacialEnumerations(uint cubeId, byte x, byte y, byte z, byte rotation, byte colour, byte colour_x, byte colour_y, byte colour_z)
{
if (x != colour_x || z != colour_z || y != colour_y) return default;
CubeInfo result = new CubeInfo { visible = true };
TranslateBlockColour(colour, ref result);
TranslateBlockPosition(x, y, z, ref result);
TranslateBlockRotation(rotation, ref result);
TranslateBlockId(cubeId, ref result);
#if DEBUG
Logging.MetaLog($"Cube {cubeId} ({x}, {y}, {z}) rot:{rotation} decoded as {result.block} {result.position} rot: {result.rotation} color: {result.color} {result.darkness}");
#endif
return result;
}
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void TranslateBlockRotation(byte rotation, ref CubeInfo result)
{
// face refers to the face of the block connected to the bottom of the current one
// nvm, they're all incorrect
switch (rotation)
{
case 0:
result.rotation = new float3(0, 0, 0); // top face, forwards
break;
case 1:
result.rotation = new float3(0, 0, 90); // left face, forwards
break;
case 2:
result.rotation = new float3(0, 0, 180); // bottom face, forwards
break;
case 3:
result.rotation = new float3(0, 0, -90); // front face, down
break;
case 4:
result.rotation = new float3(0, 90, 0); // top face, right
break;
case 5:
result.rotation = new float3(0, 90, 90); // front face, right
break;
case 6:
result.rotation = new float3(-90, -90, 0); // right face, backwards
break;
case 7:
result.rotation = new float3(0, 90, -90); // back face, right
break;
case 8:
result.rotation = new float3(0, -90, 90); // back face, left
break;
case 9:
result.rotation = new float3(0, -90, -90); // front face, left
break;
case 10:
result.rotation = new float3(90, -90, 0); // left face, down
break;
case 11:
result.rotation = new float3(90, 90, 0); // right face, forwards
break;
case 12:
result.rotation = new float3(-90, 90, 0); // left face, up
break;
case 13:
result.rotation = new float3(0, 90, 180); // bottom face, right
break;
case 14:
result.rotation = new float3(0, 180, 0); // top face, backwards
break;
case 15:
result.rotation = new float3(0, 180, 90); // right face, up
break;
case 16:
result.rotation = new float3(0, 180, 180); // bottom face, backwards
break;
case 17:
result.rotation = new float3(0, 180, -90); // left face, backwards
break;
case 18:
result.rotation = new float3(0, -90, 0); // top face, left
break;
case 19:
result.rotation = new float3(0, -90, 180); // bottom face, left
break;
case 20:
result.rotation = new float3(90, 0, 0); // front face, down
break;
case 21:
result.rotation = new float3(90, 180, 0); // back face, down
break;
case 22:
result.rotation = new float3(-90, 0, 0); // back face, up
break;
case 23:
result.rotation = new float3(-90, 180, 0); // front face, up
break;
default:
#if DEBUG
Logging.MetaLog($"Unknown rotation {rotation.ToString("X2")}");
#endif
result.rotation = float3.zero;
break;
}
// my brain hurts after figuring out all of those rotations
// I wouldn't recommend trying to redo this
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void TranslateBlockPosition(byte x, byte y, byte z, ref CubeInfo result)
{
// for some reason, z is forwards in garage bays
result.position = new float3(x, y, z);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void TranslateBlockColour(byte colour, ref CubeInfo result)
{
// I hope these colours are accurate, I just guessed
// TODO colour accuracy (lol that won't ever happen)
switch (colour)
{
case 0:
result.color = BlockColors.White;
result.darkness = 0;
break;
case 1:
result.color = BlockColors.White;
result.darkness = 5;
break;
case 2:
result.color = BlockColors.Orange;
result.darkness = 0;
break;
case 3:
result.color = BlockColors.Blue;
result.darkness = 2;
break;
case 4:
result.color = BlockColors.White;
result.darkness = 8;
break;
case 5:
result.color = BlockColors.Red;
result.darkness = 0;
break;
case 6:
result.color = BlockColors.Yellow;
result.darkness = 0;
break;
case 7:
result.color = BlockColors.Green;
result.darkness = 0;
break;
case 8:
result.color = BlockColors.Purple;
result.darkness = 0;
break;
case 9:
result.color = BlockColors.Blue;
result.darkness = 7;
break;
case 10:
result.color = BlockColors.Purple;
result.darkness = 5;
break;
case 11:
result.color = BlockColors.Orange;
result.darkness = 7;
break;
case 12:
result.color = BlockColors.Green;
result.darkness = 3;
break;
case 13:
result.color = BlockColors.Green;
result.darkness = 2;
break;
case 14:
result.color = BlockColors.Pink;
result.darkness = 3;
break;
case 15:
result.color = BlockColors.Pink;
result.darkness = 2;
break;
case 16:
result.color = BlockColors.Red;
result.darkness = 2;
break;
case 17:
result.color = BlockColors.Orange;
result.darkness = 8;
break;
case 18:
result.color = BlockColors.Red;
result.darkness = 7;
break;
case 19:
result.color = BlockColors.Pink;
result.darkness = 0;
break;
case 20:
result.color = BlockColors.Yellow;
result.darkness = 2;
break;
case 21:
result.color = BlockColors.Green;
result.darkness = 7;
break;
case 22:
result.color = BlockColors.Green;
result.darkness = 8;
break;
case 23:
result.color = BlockColors.Blue;
result.darkness = 8;
break;
case 24:
result.color = BlockColors.Aqua;
result.darkness = 7;
break;
case 25:
result.color = BlockColors.Blue;
result.darkness = 6;
break;
case 26:
result.color = BlockColors.Aqua;
result.darkness = 5;
break;
case 27:
result.color = BlockColors.Blue;
result.darkness = 4;
break;
case 28:
result.color = BlockColors.Aqua;
result.darkness = 3;
break;
case 29:
result.color = BlockColors.Blue;
result.darkness = 5;
break;
case 30:
result.color = BlockColors.Purple;
result.darkness = 3;
break;
case 31:
result.color = BlockColors.Purple;
result.darkness = 1;
break;
default:
result.color = BlockColors.Aqua;
result.darkness = 0;
break;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void TranslateBlockId(uint cubeId, ref CubeInfo result)
{
if (map == null)
{
StreamReader cubemap = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Pixi.cubes-id.json"));
map = JsonConvert.DeserializeObject<Dictionary<uint, string>>(cubemap.ReadToEnd());
}
if (!map.ContainsKey(cubeId))
{
result.block = BlockIDs.TextBlock;
result.placeholder = "Unknown cube #" + cubeId.ToString();
//result.rotation = float3.zero;
#if DEBUG
Logging.MetaLog($"Unknown cubeId {cubeId}");
#endif
}
string cubeName = map[cubeId];
if (cubeName.Contains("cube"))
{
result.block = BlockIDs.AluminiumCube;
result.rotation = float3.zero;
}
else if (cubeName.Contains("prism") || cubeName.Contains("edge"))
{
if (cubeName.Contains("round"))
{
if (cubeName.Contains("glass") || cubeName.Contains("windshield"))
{
result.block = BlockIDs.GlassRoundedSlope;
} else
result.block = BlockIDs.AluminiumRoundedSlope;
}
else
{
if (cubeName.Contains("glass") || cubeName.Contains("windshield"))
{
result.block = BlockIDs.GlassSlope;
} else
result.block = BlockIDs.AluminiumSlope;
}
}
else if (cubeName.Contains("inner"))
{
if (cubeName.Contains("round"))
{
if (cubeName.Contains("glass") || cubeName.Contains("windshield"))
{
result.block = BlockIDs.GlassRoundedSlicedCube;
} else
result.block = BlockIDs.AluminiumRoundedSlicedCube;
}
else
{
if (cubeName.Contains("glass") || cubeName.Contains("windshield"))
{
result.block = BlockIDs.GlassSlicedCube;
} else
result.block = BlockIDs.AluminiumSlicedCube;
}
}
else if (cubeName.Contains("tetra") || cubeName.Contains("corner"))
{
if (cubeName.Contains("round"))
{
if (cubeName.Contains("glass") || cubeName.Contains("windshield"))
{
result.block = BlockIDs.GlassRoundedCorner;
} else
result.block = BlockIDs.AluminiumRoundedCorner;
}
else
{
if (cubeName.Contains("glass") || cubeName.Contains("windshield"))
{
result.block = BlockIDs.GlassCorner;
} else
result.block = BlockIDs.AluminiumCorner;
}
}
else if (cubeName.Contains("pyramid"))
{
result.block = BlockIDs.AluminiumPyramidSegment;
}
else if (cubeName.Contains("cone"))
{
result.block = BlockIDs.AluminiumConeSegment;
}
else
{
result.block = BlockIDs.TextBlock;
result.placeholder = cubeName;
}
}
}
}