diff --git a/Minecraft.Server.FourKit/Block/Block.cs b/Minecraft.Server.FourKit/Block/Block.cs
index ab427c715..8c19e6bcf 100644
--- a/Minecraft.Server.FourKit/Block/Block.cs
+++ b/Minecraft.Server.FourKit/Block/Block.cs
@@ -89,7 +89,19 @@ public class Block
/// Whether the change was successful.
public bool setTypeId(int type)
{
- NativeBridge.SetTile?.Invoke(_world.getDimensionId(), _x, _y, _z, type, 0);
+ return setTypeId(type, true);
+ }
+
+ ///
+ /// Sets the type ID of this block.
+ ///
+ /// Type ID to change this block to.
+ /// False to cancel physics on the changed block.
+ /// Whether the block was changed.
+ public bool setTypeId(int type, bool applyPhysics)
+ {
+ int flags = applyPhysics ? 3 : 2;
+ NativeBridge.SetTile?.Invoke(_world.getDimensionId(), _x, _y, _z, type, 0, flags);
return true;
}
@@ -108,7 +120,43 @@ public class Block
/// New block specific metadata.
public void setData(byte data)
{
- NativeBridge.SetTileData?.Invoke(_world.getDimensionId(), _x, _y, _z, data);
+ setData(data, true);
+ }
+
+ ///
+ /// Sets the metadata for this block.
+ ///
+ /// New block specific metadata.
+ /// False to cancel physics from the changed block.
+ public void setData(byte data, bool applyPhysics)
+ {
+ int flags = applyPhysics ? 3 : 2;
+ NativeBridge.SetTileData?.Invoke(_world.getDimensionId(), _x, _y, _z, data, flags);
+ }
+
+ ///
+ /// Sets the type ID and data of this block.
+ ///
+ /// Type ID to change this block to.
+ /// The data value to change this block to.
+ /// Whether the block was changed.
+ public bool setTypeIdAndData(int type, byte data)
+ {
+ return setTypeIdAndData(type, data, true);
+ }
+
+ ///
+ /// Sets the type ID and data of this block.
+ ///
+ /// Type ID to change this block to.
+ /// The data value to change this block to.
+ /// False to cancel physics on the changed block.
+ /// Whether the block was changed.
+ public bool setTypeIdAndData(int type, byte data, bool applyPhysics)
+ {
+ int flags = applyPhysics ? 3 : 2;
+ NativeBridge.SetTile?.Invoke(_world.getDimensionId(), _x, _y, _z, type, data, flags);
+ return true;
}
///
diff --git a/Minecraft.Server.FourKit/Block/BlockState.cs b/Minecraft.Server.FourKit/Block/BlockState.cs
index 8420064c4..33d3493aa 100644
--- a/Minecraft.Server.FourKit/Block/BlockState.cs
+++ b/Minecraft.Server.FourKit/Block/BlockState.cs
@@ -200,7 +200,7 @@ public class BlockState
if (!force && currentType != _typeId)
return false;
- NativeBridge.SetTile(_world.getDimensionId(), _x, _y, _z, _typeId, _data);
+ NativeBridge.SetTile(_world.getDimensionId(), _x, _y, _z, _typeId, _data, applyPhysics ? 3 : 2);
return true;
}
diff --git a/Minecraft.Server.FourKit/ChatColor.cs b/Minecraft.Server.FourKit/ChatColor.cs
new file mode 100644
index 000000000..cbfb066a0
--- /dev/null
+++ b/Minecraft.Server.FourKit/ChatColor.cs
@@ -0,0 +1,173 @@
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Minecraft.Server.FourKit;
+
+///
+/// All supported color values for chat.
+///
+public class ChatColor
+{
+ ///
+ /// The special character which prefixes all chat colour codes.
+ ///
+ public static readonly char COLOR_CHAR = '\u00A7'; // F
+
+ private static readonly Regex STRIP_COLOR_PATTERN =
+ new Regex("(?i)" + COLOR_CHAR + "[0-9A-FK-OR]", RegexOptions.Compiled);
+
+ private static readonly Dictionary BY_CHAR = new();
+
+ /// Represents black.
+ public static readonly ChatColor BLACK = new('0', false);
+ /// Represents dark blue.
+ public static readonly ChatColor DARK_BLUE = new('1', false);
+ /// Represents dark green.
+ public static readonly ChatColor DARK_GREEN = new('2', false);
+ /// Represents dark blue (aqua).
+ public static readonly ChatColor DARK_AQUA = new('3', false);
+ /// Represents dark red.
+ public static readonly ChatColor DARK_RED = new('4', false);
+ /// Represents dark purple.
+ public static readonly ChatColor DARK_PURPLE = new('5', false);
+ /// Represents gold.
+ public static readonly ChatColor GOLD = new('6', false);
+ /// Represents gray.
+ public static readonly ChatColor GRAY = new('7', false);
+ /// Represents dark gray.
+ public static readonly ChatColor DARK_GRAY = new('8', false);
+ /// Represents blue.
+ public static readonly ChatColor BLUE = new('9', false);
+ /// Represents green.
+ public static readonly ChatColor GREEN = new('a', false);
+ /// Represents aqua.
+ public static readonly ChatColor AQUA = new('b', false);
+ /// Represents red.
+ public static readonly ChatColor RED = new('c', false);
+ /// Represents light purple.
+ public static readonly ChatColor LIGHT_PURPLE = new('d', false);
+ /// Represents yellow.
+ public static readonly ChatColor YELLOW = new('e', false);
+ /// Represents white.
+ public static readonly ChatColor WHITE = new('f', false);
+ /// Resets all previous chat colors or formats.
+ public static readonly ChatColor RESET = new('r', false);
+
+ private readonly char _code;
+ private readonly bool _isFormat;
+ private readonly string _toString;
+
+ private ChatColor(char code, bool isFormat)
+ {
+ _code = code;
+ _isFormat = isFormat;
+ _toString = new string(new[] { COLOR_CHAR, code });
+ BY_CHAR[code] = this;
+ }
+
+ ///
+ /// Gets the char value associated with this color.
+ ///
+ /// A char value of this color code.
+ public char getChar() => _code;
+
+ ///
+ /// Checks if this code is a format code as opposed to a color code.
+ ///
+ /// true if this is a format code.
+ public bool isFormat() => _isFormat;
+
+ ///
+ /// Checks if this code is a color code as opposed to a format code.
+ ///
+ /// true if this is a color code.
+ public bool isColor() => !_isFormat && this != RESET;
+
+ ///
+ /// Gets the color represented by the specified color code.
+ ///
+ /// Code to check.
+ /// Associative ChatColor with the given code, or null if it doesn't exist.
+ public static ChatColor? getByChar(char code)
+ {
+ return BY_CHAR.TryGetValue(char.ToLower(code), out var color) ? color : null;
+ }
+
+ ///
+ /// Gets the color represented by the specified color code.
+ ///
+ /// Code to check.
+ /// Associative ChatColor with the given code, or null if it doesn't exist.
+ public static ChatColor? getByChar(string code)
+ {
+ if (string.IsNullOrEmpty(code)) return null;
+ return getByChar(code[0]);
+ }
+
+ ///
+ /// Strips the given message of all color codes.
+ ///
+ /// String to strip of color.
+ /// A copy of the input string, without any coloring.
+ public static string? stripColor(string? input)
+ {
+ if (input == null) return null;
+ return STRIP_COLOR_PATTERN.Replace(input, "");
+ }
+
+ ///
+ /// Translates a string using an alternate color code character into a string
+ /// that uses the internal color code character.
+ /// The alternate color code character will only be replaced if it is immediately
+ /// followed by 0-9, A-F, a-f, K-O, k-o, R or r.
+ ///
+ /// The alternate color code character to replace. Ex: &
+ /// Text containing the alternate color code character.
+ /// Text containing the color code character.
+ public static string translateAlternateColorCodes(char altColorChar, string textToTranslate)
+ {
+ char[] b = textToTranslate.ToCharArray();
+ for (int i = 0; i < b.Length - 1; i++)
+ {
+ if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".IndexOf(b[i + 1]) > -1)
+ {
+ b[i] = COLOR_CHAR;
+ }
+ }
+ return new string(b);
+ }
+
+ ///
+ /// Gets the ChatColors used at the end of the given input string.
+ ///
+ /// Input string to retrieve the colors from.
+ /// Any remaining ChatColors to pass onto the next line.
+ public static string getLastColors(string input)
+ {
+ var result = new StringBuilder();
+ int length = input.Length;
+
+ for (int index = length - 1; index > -1; index--)
+ {
+ char section = input[index];
+ if (section == COLOR_CHAR && index < length - 1)
+ {
+ char c = input[index + 1];
+ ChatColor? color = getByChar(c);
+ if (color != null)
+ {
+ result.Insert(0, color.ToString());
+ if (color.isColor() || color == RESET)
+ break;
+ }
+ }
+ }
+
+ return result.ToString();
+ }
+
+ public static string operator +(ChatColor color, string text) => color.ToString() + text;
+
+ ///
+ public override string ToString() => _toString;
+}
diff --git a/Minecraft.Server.FourKit/NativeBridge.cs b/Minecraft.Server.FourKit/NativeBridge.cs
index 753cf898b..b936e390e 100644
--- a/Minecraft.Server.FourKit/NativeBridge.cs
+++ b/Minecraft.Server.FourKit/NativeBridge.cs
@@ -43,10 +43,10 @@ internal static class NativeBridge
internal delegate int NativeGetTileDataDelegate(int dimId, int x, int y, int z);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate void NativeSetTileDelegate(int dimId, int x, int y, int z, int tileId, int data);
+ internal delegate void NativeSetTileDelegate(int dimId, int x, int y, int z, int tileId, int data, int flags);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate void NativeSetTileDataDelegate(int dimId, int x, int y, int z, int data);
+ internal delegate void NativeSetTileDataDelegate(int dimId, int x, int y, int z, int data, int flags);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int NativeBreakBlockDelegate(int dimId, int x, int y, int z);
diff --git a/Minecraft.Server/FourKitNatives.cpp b/Minecraft.Server/FourKitNatives.cpp
index a79d53f36..f60658268 100644
--- a/Minecraft.Server/FourKitNatives.cpp
+++ b/Minecraft.Server/FourKitNatives.cpp
@@ -309,20 +309,20 @@ int __cdecl NativeGetTileData(int dimId, int x, int y, int z)
return level->getData(x, y, z);
}
-void __cdecl NativeSetTile(int dimId, int x, int y, int z, int tileId, int data)
+void __cdecl NativeSetTile(int dimId, int x, int y, int z, int tileId, int data, int flags)
{
ServerLevel *level = GetLevel(dimId);
if (!level)
return;
- level->setTileAndData(x, y, z, tileId, data, Tile::UPDATE_ALL);
+ level->setTileAndData(x, y, z, tileId, data, flags);
}
-void __cdecl NativeSetTileData(int dimId, int x, int y, int z, int data)
+void __cdecl NativeSetTileData(int dimId, int x, int y, int z, int data, int flags)
{
ServerLevel *level = GetLevel(dimId);
if (!level)
return;
- level->setData(x, y, z, data, Tile::UPDATE_ALL);
+ level->setData(x, y, z, data, flags);
}
int __cdecl NativeBreakBlock(int dimId, int x, int y, int z)
diff --git a/Minecraft.Server/FourKitNatives.h b/Minecraft.Server/FourKitNatives.h
index fb1050343..ae241e862 100644
--- a/Minecraft.Server/FourKitNatives.h
+++ b/Minecraft.Server/FourKitNatives.h
@@ -18,8 +18,8 @@ namespace FourKitBridge
// World
int __cdecl NativeGetTileId(int dimId, int x, int y, int z);
int __cdecl NativeGetTileData(int dimId, int x, int y, int z);
- void __cdecl NativeSetTile(int dimId, int x, int y, int z, int tileId, int data);
- void __cdecl NativeSetTileData(int dimId, int x, int y, int z, int data);
+ void __cdecl NativeSetTile(int dimId, int x, int y, int z, int tileId, int data, int flags);
+ void __cdecl NativeSetTileData(int dimId, int x, int y, int z, int data, int flags);
int __cdecl NativeBreakBlock(int dimId, int x, int y, int z);
int __cdecl NativeGetHighestBlockY(int dimId, int x, int z);
void __cdecl NativeGetWorldInfo(int dimId, double *outBuf);