using System.Runtime.InteropServices; using Minecraft.Server.FourKit.Entity; using Minecraft.Server.FourKit.Inventory; namespace Minecraft.Server.FourKit; /// /// Represents a world, which may contain entities, chunks and blocks. /// public class World { private readonly int _dimensionId; private readonly string _name; internal World(int dimensionId, string name) { _dimensionId = dimensionId; _name = name; } /// /// Gets the dimension ID of this world. /// /// Dimension ID of this world. public int getDimensionId() => _dimensionId; /// /// Gets the unique name of this world. /// /// Name of this world. public string getName() => _name; /// /// Gets the Block at the given coordinates. /// /// X-coordinate of the block. /// Y-coordinate of the block. /// Z-coordinate of the block. /// Block at the given coordinates. public Block.Block getBlockAt(int x, int y, int z) { return new Block.Block(this, x, y, z); } /// /// Gets the Block at the given Location. /// /// Location of the block. /// Block at the given location. public Block.Block getBlockAt(Location location) { return getBlockAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); } /// /// Gets the block type ID at the given coordinates. /// /// X-coordinate of the block. /// Y-coordinate of the block. /// Z-coordinate of the block. /// Type ID of the block. public int getBlockTypeIdAt(int x, int y, int z) { if (NativeBridge.GetTileId != null) return NativeBridge.GetTileId(_dimensionId, x, y, z); return 0; } /// /// Gets the block type ID at the given Location. /// /// Location of the block. /// Type ID of the block. public int getBlockTypeIdAt(Location location) { return getBlockTypeIdAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); } /// /// Gets the highest non-air coordinate at the given coordinates. /// /// X-coordinate. /// Z-coordinate. /// The Y-coordinate of the highest non-air block. public int getHighestBlockYAt(int x, int z) { if (NativeBridge.GetHighestBlockY != null) return NativeBridge.GetHighestBlockY(_dimensionId, x, z); return 0; } /// /// Gets the highest non-air coordinate at the given Location. /// /// Location to check. /// The Y-coordinate of the highest non-air block. public int getHighestBlockYAt(Location location) { return getHighestBlockYAt(location.getBlockX(), location.getBlockZ()); } /// /// Gets the highest non-empty block at the given coordinates. /// /// X-coordinate. /// Z-coordinate. /// Highest non-empty block. public Block.Block getHighestBlockAt(int x, int z) { int y = getHighestBlockYAt(x, z); return getBlockAt(x, y, z); } /// /// Gets the highest non-empty block at the given Location. /// /// Coordinates to get the highest block at. /// Highest non-empty block. public Block.Block getHighestBlockAt(Location location) { return getHighestBlockAt(location.getBlockX(), location.getBlockZ()); } private double[] GetWorldInfoSnapshot() { double[] buf = new double[7]; if (NativeBridge.GetWorldInfo != null) { var gh = GCHandle.Alloc(buf, GCHandleType.Pinned); try { NativeBridge.GetWorldInfo(_dimensionId, gh.AddrOfPinnedObject()); } finally { gh.Free(); } } return buf; } /// /// Gets the default spawn Location of this world. /// /// The spawn location of this world. public Location getSpawnLocation() { double[] info = GetWorldInfoSnapshot(); return new Location(this, info[0], info[1], info[2], 0f, 0f); } /// /// Sets the spawn location of the world. /// /// X-coordinate. /// Y-coordinate. /// Z-coordinate. /// True if the spawn was set successfully. public bool setSpawnLocation(int x, int y, int z) { if (NativeBridge.SetSpawnLocation != null) return NativeBridge.SetSpawnLocation(_dimensionId, x, y, z) != 0; return false; } /// /// Gets the Seed for this world. /// /// This world's Seed. public long getSeed() { double[] info = GetWorldInfoSnapshot(); return (long)info[3]; } /// /// Gets the relative in-game time of this world. /// /// The current relative time. public long getTime() { double[] info = GetWorldInfoSnapshot(); return (long)info[4]; } /// /// Sets the relative in-game time on the server. /// /// The new relative time to set the in-game time to. public void setTime(long time) { NativeBridge.SetWorldTime?.Invoke(_dimensionId, time); } /// /// Sets the in-game time on the server. /// /// The new absolute time to set this world to. public void setFullTime(long time) { NativeBridge.SetWorldTime?.Invoke(_dimensionId, time); } /// /// Set whether there is a storm. /// /// Whether there is rain and snow. public void setStorm(bool hasStorm) { NativeBridge.SetWeather?.Invoke(_dimensionId, hasStorm ? 1 : 0, -1, -1); } /// /// Set whether it is thundering. /// /// Whether it is thundering. public void setThundering(bool thundering) { NativeBridge.SetWeather?.Invoke(_dimensionId, -1, thundering ? 1 : 0, -1); } /// /// Set the thundering duration. /// /// Duration in ticks. public void setThunderDuration(int duration) { NativeBridge.SetWeather?.Invoke(_dimensionId, -1, -1, duration); } /// /// Get a list of all players in this World. /// /// A list of all Players currently residing in this world. public List getPlayers() { var all = FourKit.getOnlinePlayers(); var result = new List(); foreach (var p in all) { var loc = p.getLocation(); if (loc?.LocationWorld == this) result.Add(p); } return result; } /// /// Creates explosion at given coordinates with given power. /// /// X-coordinate. /// Y-coordinate. /// Z-coordinate. /// The power of explosion, where 4F is TNT. /// false if explosion was canceled, otherwise true. public bool createExplosion(double x, double y, double z, float power) { return createExplosion(x, y, z, power, false, true); } /// /// Creates explosion at given coordinates with given power and optionally /// setting blocks on fire. /// /// X-coordinate. /// Y-coordinate. /// Z-coordinate. /// The power of explosion, where 4F is TNT. /// Whether or not to set blocks on fire. /// false if explosion was canceled, otherwise true. public bool createExplosion(double x, double y, double z, float power, bool setFire) { return createExplosion(x, y, z, power, setFire, true); } /// /// Creates explosion at given coordinates with given power and optionally /// setting blocks on fire or breaking blocks. /// /// X-coordinate. /// Y-coordinate. /// Z-coordinate. /// The power of explosion, where 4F is TNT. /// Whether or not to set blocks on fire. /// Whether or not to have blocks be destroyed. /// false if explosion was canceled, otherwise true. public bool createExplosion(double x, double y, double z, float power, bool setFire, bool breakBlocks) { if (NativeBridge.CreateExplosion != null) return NativeBridge.CreateExplosion(_dimensionId, x, y, z, power, setFire ? 1 : 0, breakBlocks ? 1 : 0) != 0; return false; } /// /// Creates explosion at given coordinates with given power and optionally /// setting blocks on fire or breaking blocks. /// /// Location to blow up. /// The power of explosion, where 4F is TNT. /// Whether or not to set blocks on fire. /// Whether or not to have blocks be destroyed. /// false if explosion was canceled, otherwise true. public bool createExplosion(Location loc, float power, bool setFire, bool breakBlocks) { if (NativeBridge.CreateExplosion != null) return NativeBridge.CreateExplosion(_dimensionId, loc.X, loc.Y, loc.Z, power, setFire ? 1 : 0, breakBlocks ? 1 : 0) != 0; return false; } /// /// Creates explosion at given coordinates with given power. /// /// Location to blow up. /// The power of explosion, where 4F is TNT. /// false if explosion was canceled, otherwise true. public bool createExplosion(Location loc, float power) { return createExplosion(loc.X, loc.Y, loc.Z, power); } /// /// Creates explosion at given coordinates with given power and optionally /// setting blocks on fire. /// /// Location to blow up. /// The power of explosion, where 4F is TNT. /// Whether or not to set blocks on fire. /// false if explosion was canceled, otherwise true. public bool createExplosion(Location loc, float power, bool setFire) { return createExplosion(loc.X, loc.Y, loc.Z, power, setFire); } /// /// Strikes lightning at the given Location. /// /// The location to strike lightning. /// true if lightning was successfully summoned. public bool strikeLightning(Location loc) { if (NativeBridge.StrikeLightning != null) return NativeBridge.StrikeLightning(_dimensionId, loc.X, loc.Y, loc.Z, 0) != 0; return false; } /// /// Strikes lightning at the given Location without doing damage. /// /// The location to strike lightning. /// true if lightning was successfully summoned. public bool strikeLightningEffect(Location loc) { if (NativeBridge.StrikeLightning != null) return NativeBridge.StrikeLightning(_dimensionId, loc.X, loc.Y, loc.Z, 1) != 0; return false; } /// /// Drops an item at the specified Location. /// /// Location to drop the item. /// ItemStack to drop. public void dropItem(Location location, ItemStack item) { NativeBridge.DropItem?.Invoke(_dimensionId, location.X, location.Y, location.Z, item.getTypeId(), item.getAmount(), item.getDurability(), 0); } /// /// Drops an item at the specified Location with a random offset. /// /// Location to drop the item. /// ItemStack to drop. public void dropItemNaturally(Location location, ItemStack item) { NativeBridge.DropItem?.Invoke(_dimensionId, location.X, location.Y, location.Z, item.getTypeId(), item.getAmount(), item.getDurability(), 1); } }