public static List <Vector3Int> MakeFloors(WorldEdit.AreaSelection area, int border = 1) { List <Vector3Int> affected = new List <Vector3Int>(); int minY = area.posA.y; int maxY = area.posB.y; Vector3Int relative; for (int x = area.cornerB.x; x >= area.cornerA.x; x--) { for (int y = area.cornerB.y; y >= area.cornerA.y; y--) { for (int z = area.cornerB.z; z >= area.cornerA.z; z--) { relative = new Vector3Int(x, y, z); if (relative.y > (maxY - border) || relative.y < (minY + border)) { affected.Add(new Vector3Int(x, y, z) + area.posA); } } } } return(affected); }
// update/set the jail position in the world public static void setJailPosition(Players.Player causedBy, uint range = DEFAULT_RANGE) { // if an old jail position existed remove its protection area if (validJail) { Pipliz.Vector3Int oldPos = new Pipliz.Vector3Int(jailPosition); CustomProtectionArea oldJail = null; foreach (CustomProtectionArea area in AntiGrief.CustomAreas) { if (area.Equals(oldPos, range)) { oldJail = area; } } if (oldJail != null) { AntiGrief.RemoveCustomArea(oldJail); Chat.Send(causedBy, String.Format("Removed old jail protection area at {0} {1}", (int)jailPosition.x, (int)jailPosition.z)); } } jailPosition.x = causedBy.Position.x; jailPosition.y = causedBy.Position.y + 1; // one block higher to prevent clipping jailPosition.z = causedBy.Position.z; jailRange = range; validJail = true; Save(); Pipliz.Vector3Int playerPos = new Pipliz.Vector3Int(causedBy.Position); AntiGrief.AddCustomArea(new CustomProtectionArea(playerPos, (int)range, (int)range)); Chat.Send(causedBy, "Created new custom protection area"); return; }
public static void OnSendAreaHighlights(Players.Player causedBy, List <AreaJobTracker.AreaHighlight> jobs, List <ushort> activeTypes) { if (!IsShowAllActive(causedBy)) { return; } Pipliz.Vector3Int playerPos = causedBy.VoxelPosition; foreach (KeyValuePair <Colony, List <IAreaJob> > kvp in allAreaJobs) { if (kvp.Key == causedBy.ActiveColony) { continue; } BannerTracker.Banner closestBanner = kvp.Key.GetClosestBanner(playerPos); if (Math.ManhattanDistance(closestBanner.Position, playerPos) > MaxDistance) { continue; } foreach (IAreaJob job in kvp.Value) { jobs.Add(new AreaJobTracker.AreaHighlight(job.Minimum, job.Maximum, job.AreaTypeMesh, job.AreaType)); } } return; }
public static List <Vector3Int> MakeLine(Vector3Int pos1, Vector3Int pos2) { List <Vector3Int> affected = new List <Vector3Int>(); bool notdrawn = true; int x1 = pos1.x; int y1 = pos1.x; int z1 = pos1.x; int x2 = pos2.x; int y2 = pos2.y; int z2 = pos2.z; int tipx = x1; int tipy = y1; int tipz = z1; int dx = Math.Abs(x2 - x1); int dy = Math.Abs(y2 - y1); int dz = Math.Abs(z2 - z1); if (dx + dy + dz == 0) { affected.Add(pos2 + new Vector3Int(tipx, tipy, tipz)); notdrawn = false; } if (Math.Max(Math.Max(dx, dy), dz) == dx && notdrawn) { for (int domstep = 0; domstep <= dx; domstep++) { tipx = x1 + domstep * (x2 - x1 > 0 ? 1 : -1); tipy = (int)Math.Round(y1 + domstep * (((double)dy) / ((double)dx)) * (y2 - y1 > 0 ? 1 : -1)); tipz = (int)Math.Round(z1 + domstep * (((double)dz) / ((double)dx)) * (z2 - z1 > 0 ? 1 : -1)); affected.Add(new Vector3Int(tipx, tipy, tipz)); } notdrawn = false; } if (Math.Max(Math.Max(dx, dy), dz) == dy && notdrawn) { for (int domstep = 0; domstep <= dx; domstep++) { tipx = x1 + domstep * (x2 - x1 > 0 ? 1 : -1); tipy = (int)Math.Round(y1 + domstep * ((double)dy) / ((double)dx) * (y2 - y1 > 0 ? 1 : -1)); tipz = (int)Math.Round(z1 + domstep * ((double)dz) / ((double)dx) * (z2 - z1 > 0 ? 1 : -1)); affected.Add(new Vector3Int(tipx, tipy, tipz)); } notdrawn = false; } if (Math.Max(Math.Max(dx, dy), dz) == dz && notdrawn) { for (int domstep = 0; domstep <= dz; domstep++) { tipz = z1 + domstep * (z2 - z1 > 0 ? 1 : -1); tipy = (int)Math.Round(y1 + domstep * ((double)dy) / ((double)dz) * (y2 - y1 > 0 ? 1 : -1)); tipx = (int)Math.Round(x1 + domstep * ((double)dx) / ((double)dz) * (x2 - x1 > 0 ? 1 : -1)); affected.Add(pos2 + new Vector3Int(tipx, tipy, tipz)); } } return(affected); }
public static List <Vector3Int> MakePyramid(Vector3Int pos, int size, bool filled) { List <Vector3Int> affected = new List <Vector3Int>(); int height = size; for (int y = 0; y <= height; y++) { size--; for (int x = 0; x <= size; x++) { for (int z = 0; z <= size; z++) { if ((filled && z <= size && x <= size) || z == size || x == size) { affected.Add(new Vector3Int(x, y, z) + pos); affected.Add(new Vector3Int(-x, y, z) + pos); affected.Add(new Vector3Int(x, y, -z) + pos); affected.Add(new Vector3Int(-x, y, -z) + pos); } } } } return(affected); }
public static void LoadJSON() { try { JSONNode array; if (Pipliz.JSON.JSON.Deserialize(GetJSONPath(), out array, false)) { if (array != null) { int chunksloaded = 0; foreach (JSONNode node in array.LoopArray()) { try { // recapture location Pipliz.Vector3Int location = new Pipliz.Vector3Int(); location = (Pipliz.Vector3Int)node["location"]; // recapture instance class string chunkID = node["chunkID"].GetAs <string>(); ChunkData instanceclass; bool owned = node["owned"].GetAs <bool>(); ulong playerID = node["playerID"].GetAs <ulong>(); if (playerID > 0) { instanceclass = new ChunkData(location, owned, new NetworkID(new CSteamID(playerID))); ChunkDataList.Add(chunkID, instanceclass); chunksloaded += 1; } } catch (Exception exception) { Utilities.WriteLog("Exception loading a wheat block;" + exception.Message); } } Utilities.WriteLog("Loaded Chunk Data (" + chunksloaded + " chunks)"); } else { Utilities.WriteLog("Loading Chunk Data Returned 0 results"); } } else { Utilities.WriteLog("Found no chunk data (read error?)"); } } catch (Exception exception2) { Utilities.WriteLog("Exception in loading all Chunk Data:" + exception2.Message); } worldManagerLoaded = true; }
// Track a crop public static void trackCrop(Pipliz.Vector3Int location, GrowableType classInstance, bool save = false) { long nextUpdate = (long)(Pipliz.Time.MillisecondsSinceStart + classInstance.maxGrowth * Pipliz.Random.NextFloat(classInstance.growthMultiplierMin, classInstance.growthMultiplierMax) * 60000); string cropLocString = ColonyAPI.Managers.WorldManager.XYZPositionToString(location); CropTracker.Add(cropLocString, location); // add it to the update list if (CropUpdateHolder.ContainsKey(nextUpdate)) { // other crops are set to update at this time too, so add this to the list CropUpdateHolder[nextUpdate].Add(cropLocString); } else { // no crops are currently setup to update at this time, make a new list CropUpdateHolder.Add(nextUpdate, new List <string>() { cropLocString }); } if (save == true) { SaveCropTracker(); } }
public static List <Vector3Int> MakeWalls(WorldEdit.AreaSelection area, int border = 1) { List <Vector3Int> affected = new List <Vector3Int>(); int minX = Math.Min(area.posA.x, area.posB.x); int maxX = Math.Max(area.posA.x, area.posB.x); int minZ = Math.Min(area.posA.z, area.posB.z); int maxZ = Math.Max(area.posA.z, area.posB.z); Vector3Int relative; for (int x = area.cornerB.x; x >= area.cornerA.x; x--) { for (int y = area.cornerB.y; y >= area.cornerA.y; y--) { for (int z = area.cornerB.z; z >= area.cornerA.z; z--) { relative = new Vector3Int(x, y, z); if (relative.x > (maxX - border) || relative.x < (minX + border) || relative.z > (maxZ - border) || relative.z < (minZ + border)) { affected.Add(relative); } } } } return(affected); }
public void PerformGoal(ref NPCBase.NPCState state) { Pipliz.Vector3Int position = GuardJob.Position; state.SetCooldown(1); state.JobIsDone = true; if (!Job.NPC.Inventory.Contains(GuardSettings.ShootItem)) { Shop(Job, ref Job.NPC.state); return; } if (GuardJob.HasTarget) { UnityEngine.Vector3 npcPos = position.Add(0, 1, 0).Vector; UnityEngine.Vector3 targetPos = GuardJob.Target.PositionToAimFor; if (VoxelPhysics.CanSee(npcPos, targetPos)) { GuardJob.NPC.LookAt(targetPos); ShootAtTarget(GuardJob, ref state); return; } } GuardJob.Target = MonsterTracker.Find(position.Add(0, 1, 0), GuardSettings.Range, GuardSettings.Damage); if (GuardJob.HasTarget) { GuardJob.NPC.LookAt(GuardJob.Target.PositionToAimFor); ShootAtTarget(GuardJob, ref state); return; } state.SetCooldown(GuardSettings.CooldownSearchingTarget * Pipliz.Random.NextFloat(0.9f, 1.1f)); UnityEngine.Vector3 pos = GuardJob.NPC.Position.Vector; if (GuardSettings.BlockTypes.ContainsByReference(GuardJob.BlockType, out int index)) { switch (index) { case 1: pos.x += 1f; break; case 2: pos.x -= 1f; break; case 3: pos.z += 1f; break; case 4: pos.z -= 1f; break; } } GuardJob.NPC.LookAt(pos); }
// Update a block public static void updateBlock(Pipliz.Vector3Int location, string newblocktype) { // Find the block ID ushort newBlockID = ItemTypes.IndexLookup.GetIndex(newblocktype); // Set the block, don't send a causedby ID ServerManager.TryChangeBlock(location, newBlockID); }
private static bool HasCollisionHelper(ref VoxelRay centerRay, Pipliz.Vector3Int pos, RayCastType type, ref RayHit.VoxelHit hit) { ushort hitType = default(ushort); if (!World.TryGetTypeAt(pos, out hitType)) { return(true); } if (hitType == 0) { return(false); } if (hitType == BuiltinBlocks.Indices.water) { return(false); } if ((type & RayCastType.HitBoxesSelection) != 0) { ItemTypes.ItemType itemType = ItemTypes.GetType(hitType); if (itemType.BoxColliders != null && itemType.CollideSelection) { Vector3 vector = pos.Vector; List <BoundsPip> boxes = itemType.BoxColliders; for (int i = 0; i < boxes.Count; i++) { BoundsPip bounds2 = boxes[i]; bounds2.Shift(pos.Vector); if (centerRay.Intersects(bounds2, out float hitDist2, out VoxelSide hitSides2) && hitDist2 < hit.Distance) { hit.TypeHit = hitType; hit.Distance = hitDist2; hit.VoxelPositionHit = pos; hit.VoxelSideHit = hitSides2; hit.BoundsHit = new RotatedBounds(boxes[i], Quaternion.identity); hit.BoundsCenter = pos.Vector; } } return(false); } } if ((type & RayCastType.HitNonSolidAsSolid) == 0 && !ItemTypes.Solids[hitType]) { return(false); } BoundsPip bounds = default(BoundsPip); bounds.SetCenterSize(pos.Vector, Vector3.one); if (centerRay.Intersects(bounds, out float hitDist, out VoxelSide hitSides) && hitDist < hit.Distance) { hit.TypeHit = hitType; hit.Distance = hitDist; hit.VoxelPositionHit = pos; hit.VoxelSideHit = hitSides; hit.BoundsHit = new RotatedBounds(Vector3.zero, Vector3.one, Quaternion.identity); hit.BoundsCenter = pos.Vector; } return(false); }
public bool TryGetPath(int maxRecycled, Vector3Int goal, float maxSpawnWalkDistance, out Path path) { if (PathCaches.TryGetValue(goal, out PathCacheGoal cache)) { return(cache.TryGetPath(maxRecycled, maxSpawnWalkDistance, out path)); } path = null; return(false); }
public static Vector3Int NodeToVector3Int(JSONNode node) { int x = node["x"].GetAs <int>(); int y = node["y"].GetAs <int>(); int z = node["z"].GetAs <int>(); Pipliz.Vector3Int ret = new Pipliz.Vector3Int(x, y, z); return(ret); }
public static void LoadCropTracker() { try { JSONNode array; if (Pipliz.JSON.JSON.Deserialize(GetJSONPath(), out array, false)) { if (array != null) { foreach (JSONNode node in array.LoopArray()) { try { // recapture location Pipliz.Vector3Int location = new Pipliz.Vector3Int(); location = (Pipliz.Vector3Int)node["location"]; // recapture instance class string typename; typename = node["typename"].GetAs <string>(); if (CropTypes.ContainsKey(typename)) { loadTrackCrop(location, CropTypes[typename]); } } catch (Exception exception) { ColonyAPI.Helpers.Utilities.WriteLog("ColonyPlusPlus-Core", "Exception loading a wheat block;" + exception.Message); } } ColonyAPI.Helpers.Utilities.WriteLog("ColonyPlusPlus-Core", "Loaded Crop Saves"); SaveCropTracker(); } else { ColonyAPI.Helpers.Utilities.WriteLog("ColonyPlusPlus-Core", "Loading Crop Saves Returned 0 results"); } } else { ColonyAPI.Helpers.Utilities.WriteLog("ColonyPlusPlus-Core", "Found no crop saves (read error?)"); } } catch (Exception exception2) { ColonyAPI.Helpers.Utilities.WriteLog("ColonyPlusPlus-Core", "Exception in saving all UpdatableBlocks:" + exception2.Message); } cropsLoaded = true; }
static void ForeachBanner(Vector3Int position, Banner banner, ref Data data) { Colony colony = banner.Colony; if (colony == null) { return; } if (colony.FollowerCount == 0) { colony.OnZombieSpawn(true); return; } IColonyDifficultySetting difficultyColony = colony.DifficultySetting; ColonyState colonyState = ColonyState.GetColonyState(colony); if (!difficultyColony.ShouldSpawnZombies(colony) || !colonyState.MonstersEnabled) { colony.OnZombieSpawn(true); return; } double nextZombieSpawnTime = Extensions.GetValueOrDefault(data.NextZombieSpawnTimes, colony, 0.0); if (nextZombieSpawnTime > ServerTime.SecondsSinceStart) { return; } if (colony.InSiegeMode) { if (ServerTime.SecondsSinceStart - colony.LastSiegeModeSpawn < SIEGEMODE_COOLDOWN_SECONDS) { return; } else { colony.LastSiegeModeSpawn = ServerTime.SecondsSinceStart; } } if (ServerTime.SecondsSinceStart - nextZombieSpawnTime > MONSTERS_DELAY_THRESHOLD_SECONDS) { // lagging behind, or no cooldown set: teleport closer to current time data.NextZombieSpawnTimes[colony] = ServerTime.SecondsSinceStart - MONSTERS_DELAY_THRESHOLD_SECONDS; } data.ColoniesRequiringZombies.AddIfUnique(colony); }
public VoxelRay(Vector3 source, Vector3 direction) { this.source = source; SourceVoxel = new Pipliz.Vector3Int(source); NextVoxel = SourceVoxel; dirNormalized = direction; tDelta.x = ((dirNormalized.x != 0f) ? Pipliz.Math.Abs(1f / dirNormalized.x) : 1E+07f); tDelta.y = ((dirNormalized.y != 0f) ? Pipliz.Math.Abs(1f / dirNormalized.y) : 1E+07f); tDelta.z = ((dirNormalized.z != 0f) ? Pipliz.Math.Abs(1f / dirNormalized.z) : 1E+07f); tMax.x = tMaxHelper(source.x, dirNormalized.x); tMax.y = tMaxHelper(source.y, dirNormalized.y); tMax.z = tMaxHelper(source.z, dirNormalized.z); LastDirMin = VoxelSide.None; }
// Stop tracking a crop public static void untrackCrop(Pipliz.Vector3Int location, GrowableType classInstance, bool save = false) { // check if it's being tracked, if so remove it string cropLocString = ColonyAPI.Managers.WorldManager.XYZPositionToString(location); if (CropTracker.ContainsKey(cropLocString)) { CropTracker.Remove(cropLocString); } if (save == true) { SaveCropTracker(); } }
public bool TryGetPath(int maxRecycled, float maxSpawnWalkDistance, out Path path) { while (true) { if (storage.Count == 0) { path = default; return(false); } double minKey = storage.PeekKeyAtIndex(0); double timeSinceUsable = ServerTime.SecondsSinceStart - minKey; if (timeSinceUsable < minKey) { path = default; return(false); } (Path cachedPath, int useCount) = storage.ExtractValueMin(); if (timeSinceUsable > PATH_CACHE_REUSE_COOLDOWN_MAX * 10) { Path.Return(cachedPath); continue; } Vector3Int pathStart = cachedPath.Start; Vector3Int pathGoal = cachedPath.Goal; if (Math.Abs(pathStart.x - pathGoal.x) + Math.Abs(pathStart.z - pathGoal.z) > maxSpawnWalkDistance) { Path.Return(cachedPath); continue; } if (useCount >= maxRecycled) { path = cachedPath; } else { path = cachedPath.DeepCopy(); storage.Add(ServerTime.SecondsSinceStart + GetCooldown(), (cachedPath, useCount + 1)); } return(true); } }
public void OnNPCGathered(IJob job, Pipliz.Vector3Int pos, List <ItemTypes.ItemTypeDrops> items) { if (job == null || job.NPC == null || job.NPC.Colony == null || items == null) { return; } ColonyStatistics stats = GetColonyStats(job.NPC.Colony); foreach (var item in items) { var itemStat = stats.GetTimedItemStats(item.Type); itemStat.Produce(item.Amount); itemStat.AddProducer(job.NPC.ID); } }
public static List <Vector3Int> MakeOutline(WorldEdit.AreaSelection area, int border = 1) { List <Vector3Int> affected = new List <Vector3Int>(); int minX = Math.Min(area.posA.x, area.posB.x); int maxX = Math.Max(area.posA.x, area.posB.x); int minY = Math.Min(area.posA.y, area.posB.y); int maxY = Math.Max(area.posA.y, area.posB.y); int minZ = Math.Min(area.posA.z, area.posB.z); int maxZ = Math.Max(area.posA.z, area.posB.z); Vector3Int relative; List <bool> truth; for (int x = area.cornerB.x; x >= area.cornerA.x; x--) { for (int y = area.cornerB.y; y >= area.cornerA.y; y--) { for (int z = area.cornerB.z; z >= area.cornerA.z; z--) { relative = new Vector3Int(x, y, z); { truth = new List <bool> { relative.y >= (maxY - border), relative.y <= (minY + border), relative.x >= (maxX - border), relative.x <= (minX + border), relative.z >= (maxZ - border), relative.z <= (minZ + border) }; Log.Write($"{truth.FindAll(i => i == true).ToList().Count}"); if (truth.Where(i => i == true).ToList().Count >= 2) { affected.Add(relative); } } } } } return(affected); }
private static bool OutofSpawn(Pipliz.Vector3Int block, Players.Player p) { if (Helpers.Player.ExactPermission(p, ultimatepermission)) { return(true); } if (Helpers.Player.ExactPermission(p, permission)) { return(true); } int dx = System.Math.Abs((int)spawnlocation.x - block.x); int dz = System.Math.Abs((int)spawnlocation.z - block.z); if (dx < spawnprotectionrange && dz < spawnprotectionrange) { return(false); } return(true); }
public static List <Vector3Int> MakeCuboid(WorldEdit.AreaSelection area, int border = 1, bool hollow = false) { List <Vector3Int> affected = new List <Vector3Int>(); int minX = Math.Min(area.posA.x, area.posB.x); int maxX = Math.Max(area.posA.x, area.posB.x); int minY = Math.Min(area.posA.y, area.posB.y); int maxY = Math.Max(area.posA.y, area.posB.y); int minZ = Math.Min(area.posA.z, area.posB.z); int maxZ = Math.Max(area.posA.z, area.posB.z); Vector3Int relative; for (int x = area.cornerB.x; x >= area.cornerA.x; x--) { for (int y = area.cornerB.y; y >= area.cornerA.y; y--) { for (int z = area.cornerB.z; z >= area.cornerA.z; z--) { relative = new Vector3Int(x, y, z); if (hollow) { if (!(relative.y > (maxY - border) || relative.y < (minY + border) || relative.x > (maxX - border) || x < (minX + border) || relative.z > (maxZ - border) || relative.z < (minZ + border))) { affected.Add(relative); } } else { if (relative.y > (maxY - border) || relative.y < (minY + border) || relative.x > (maxX - border) || x < (minX + border) || relative.z > (maxZ - border) || relative.z < (minZ + border)) { affected.Add(relative); } } } } } return(affected); }
public static bool OutofBannerRange(ItemTypes.ItemType itemType, Pipliz.Vector3Int position, Players.Player player, out BlockEntities.Implementations.BannerTracker.Banner banner) { banner = null; if (Helpers.Player.ExactPermission(player, ultimatepermission)) { return(true); } if (Helpers.Player.ExactPermission(player, permission)) { return(true); } if (itemType == ItemTypes.GetType("banner")) { foreach (var item in ServerManager.ColonyTracker.ColoniesByID.Values) { if (Vector3.Distance(new Vector3(position.x, position.y, position.z), new Vector3(item.Banners[0].Position.x, item.Banners[0].Position.y, item.Banners[0].Position.z)) < GetBannerRadius()) { if (item.Owners[0] != player) { return(false); } } } return(true); } if (ServerManager.BlockEntityTracker.BannerTracker.TryGetClosest(position, out banner, GetBannerRadius())) { if (banner.Colony.Owners.ContainsByReference(player) == false) { return(false); } } return(true); }
public static void Init() { if (ConfigManager.GetConfigBooleanOrDefault(NewColonyAPIEntry.ModName, "antigrief.enabled", false) == true) { antigrief = true; ultimatepermission = ConfigManager.GetConfigStringOrDefault(NewColonyAPIEntry.ModName, "antigrief.ultimatepermission", "debug"); permission = ConfigManager.GetConfigStringOrDefault(NewColonyAPIEntry.ModName, "antigrief.permission", "admin"); bannerbonusrange = ConfigManager.GetConfigIntOrDefault(NewColonyAPIEntry.ModName, "antigrief.bannerbonusradius", 50); if (bannerbonusrange < 0) { bannerbonusrange = 0; } if (ConfigManager.GetConfigBooleanOrDefault(NewColonyAPIEntry.ModName, "antigrief.spawnprotection", false) == true) { spawnprotection = true; spawnprotectionrange = ConfigManager.GetConfigIntOrDefault(NewColonyAPIEntry.ModName, "antigrief.spawnradius", 300); if (spawnprotectionrange < 0) { spawnprotectionrange = 0; } spawnlocation = ServerManager.TerrainGenerator.GetDefaultSpawnLocation(); } Helpers.Logging.WriteLog( NewColonyAPIEntry.ModName, string.Format( "[AntiGrief] Banner Protection: {0} with {1} range, Spawn Protection: {2} with {3} range", antigrief ? "Enabled" : "Disabled", GetBannerRadius(), spawnprotection ? "Enabled" : "Disabled", spawnprotectionrange), Helpers.Logging.LogType.Loading, true); } }
public AngryGuardJobInstance(IBlockJobSettings settings, Pipliz.Vector3Int position, ItemTypes.ItemType type, Colony colony) : base(settings, position, type, colony) { this.eyePosition = position.Vector; this.eyePosition[1] += 1; }
public AngryGuardJobInstance(IBlockJobSettings settings, Pipliz.Vector3Int position, ItemTypes.ItemType type, ByteReader reader) : base(settings, position, type, reader) { this.eyePosition = position.Vector; this.eyePosition[1] += 1; }
public Artificer(IBlockJobSettings settings, Pipliz.Vector3Int position, ItemTypes.ItemType type, Colony colony) : base(settings, position, type, colony) { }
public Artificer(IBlockJobSettings settings, Pipliz.Vector3Int position, ItemTypes.ItemType type, ByteReader reader) : base(settings, position, type, reader) { }
public MachinistNight(IBlockJobSettings settings, Pipliz.Vector3Int position, ItemTypes.ItemType type, Colony colony) : base(settings, position, type, colony) { }
public MachinistNight(IBlockJobSettings settings, Pipliz.Vector3Int position, ItemTypes.ItemType type, ByteReader reader) : base(settings, position, type, reader) { }