public override void Initialize(ICoreAPI api) { base.Initialize(api); inv.LateInitialize(InventoryClassName + "-" + Pos, api); capi = api as ICoreClientAPI; if (api.Side == EnumAppSide.Client) { RegisterGameTickListener(onClientTick50ms, 50); } else { RegisterGameTickListener(onServerTick1s, 1000); } ms = Block.Attributes["multiblockStructure"].AsObject <MultiblockStructure>(); msOpp = Block.Attributes["multiblockStructure"].AsObject <MultiblockStructure>(); int rotYDeg = 0; int rotYDegOpp = 180; if (Block.Variant["side"] == "east") //BlockStoneCoffin only has a BE on north and east variants { rotYDeg = 270; rotYDegOpp = 90; } ms.InitForUse(rotYDeg); msOpp.InitForUse(rotYDegOpp); blockScs = Block as BlockStoneCoffinSection; updateSelectiveElements(); particlePositions[0] = Pos.DownCopy(2); particlePositions[1] = particlePositions[0].AddCopy(blockScs.Orientation.Opposite); particlePositions[2] = Pos.AddCopy(blockScs.Orientation.GetCW()); particlePositions[3] = Pos.AddCopy(blockScs.Orientation.GetCCW()); particlePositions[4] = Pos.AddCopy(blockScs.Orientation.GetCW()).Add(blockScs.Orientation.Opposite); particlePositions[5] = Pos.AddCopy(blockScs.Orientation.GetCCW()).Add(blockScs.Orientation.Opposite); particlePositions[6] = Pos.UpCopy(1).Add(blockScs.Orientation.Opposite); inv.SetSecondaryPos(Pos.AddCopy(blockScs.Orientation.Opposite)); }
public override void Initialize(ICoreAPI api) { base.Initialize(api); inv.LateInitialize(InventoryClassName + "-" + Pos, api); capi = api as ICoreClientAPI; structure = Block.Attributes["multiBlockStructure"].AsObject <MultiblockStructure>(); structure.InitForUse(0); if (processing && !processComplete && api.Side == EnumAppSide.Server) { tickListener = RegisterGameTickListener(onServerTick3s, 3000); } }
private void GenMarkedMultiblockCode(IServerPlayer player) { BlockPos centerPos = player.CurrentBlockSelection.Position; OrderedDictionary <int, int> blocks = new OrderedDictionary <int, int>(); List <Vec4i> offsets = new List <Vec4i>(); MultiblockStructure ms = new MultiblockStructure(); sapi.World.BlockAccessor.WalkBlocks(workspace.StartMarker, workspace.EndMarker, (block, x, y, z) => { if (block.Id == 0) { return; } int blockNum = ms.GetOrCreateBlockNumber(block); BlockOffsetAndNumber offset = new BlockOffsetAndNumber(x - centerPos.X, y - centerPos.Y, z - centerPos.Z, blockNum); ms.Offsets.Add(offset); }, true); StringBuilder sb = new StringBuilder(); sb.AppendLine("multiblockStructure: {"); sb.AppendLine("\tblockNumbers: {"); foreach (var val in ms.BlockNumbers) { sb.AppendLine(string.Format("\t\t\"{0}\": {1},", val.Key.ToShortString(), val.Value)); } sb.AppendLine("\t},"); sb.AppendLine("\toffsets: ["); foreach (var val in ms.Offsets) { sb.AppendLine(string.Format("\t\t{{ x: {0}, y: {1}, z: {2}, w: {3} }},", val.X, val.Y, val.Z, val.W)); } sb.AppendLine("\t]"); sb.AppendLine("}"); sapi.World.Logger.Notification("Multiblockstructure centered around {0}:\n{1}", centerPos, sb.ToString()); Good("Json code written to server-main.txt"); }
void NatureCreation(Chunk chunk) { byte x = (byte)(Random.value * (Chunk.CHUNK_SIZE - 2) + 1); byte z = (byte)(Random.value * (Chunk.CHUNK_SIZE - 2) + 1); x = (byte)(Chunk.CHUNK_SIZE / 2); z = (byte)(Chunk.CHUNK_SIZE / 2); //surface[x,z].ReplaceMaterial(PoolMaster.grass_material); //chunk.SpreadBlocks(x,z, PoolMaster.GRASS_ID); MultiblockStructure ms = null; if (Random.value > 0.5f) { ms = Structure.GetStructureByID(Structure.TREE_OF_LIFE_ID) as MultiblockStructure; } else { ms = Structure.GetStructureByID(Structure.LIFESTONE_ID) as MultiblockStructure; } SurfaceBlock sb = chunk.GetSurfaceBlock(x, z); ms.SetBasement(sb, PixelPosByte.zero); chunk.GenerateNature(ms.transform.position); }
private void onServerTick3s(float dt) { BlockPos coalPilePos = Pos.DownCopy(2); BlockPos othercoalPilePos = coalPilePos.AddCopy(blockScs.Orientation.Opposite); bool beforeReceiveHeat = receivesHeat; bool beforeStructureComplete = structureComplete; if (!receivesHeat) { totalHoursLastUpdate = Api.World.Calendar.TotalHours; } BlockEntityCoalPile becp = Api.World.BlockAccessor.GetBlockEntity(coalPilePos) as BlockEntityCoalPile; float leftHeatHoursLeft = (becp != null && becp.IsBurning) ? becp.GetHoursLeft(totalHoursLastUpdate) : 0f; becp = Api.World.BlockAccessor.GetBlockEntity(othercoalPilePos) as BlockEntityCoalPile; float rightHeatHoursLeft = (becp != null && becp.IsBurning) ? becp.GetHoursLeft(totalHoursLastUpdate) : 0f; receivesHeat = leftHeatHoursLeft > 0 && rightHeatHoursLeft > 0; if (processComplete || !IsFull || !hasLid()) { return; } MultiblockStructure msInUse = null; BlockPos posInUse = null; structureComplete = false; if (ms.InCompleteBlockCount(Api.World, Pos) == 0) { msInUse = ms; posInUse = Pos; structureComplete = true; } else if (msOpp.InCompleteBlockCount(Api.World, Pos.AddCopy(blockScs.Orientation.Opposite)) == 0) { msInUse = msOpp; posInUse = Pos.AddCopy(blockScs.Orientation.Opposite); structureComplete = true; } if (beforeReceiveHeat != receivesHeat || beforeStructureComplete != structureComplete) { MarkDirty(); } if (receivesHeat) { if (!structureComplete) { return; } double hoursPassed = Api.World.Calendar.TotalHours - totalHoursLastUpdate; double heatHoursReceived = Math.Max(0, Math.Min(hoursPassed, Math.Min(leftHeatHoursLeft, rightHeatHoursLeft))); progress += heatHoursReceived / 160f; totalHoursLastUpdate = Api.World.Calendar.TotalHours; MarkDirty(); } if (progress >= 1.0) { int stacksize = inv[1].Itemstack.StackSize; JsonItemStack jstack = inv[1].Itemstack.ItemAttributes?["carburizableProps"]["carburizedOutput"].AsObject <JsonItemStack>(null, Block.Code.Domain); if (jstack.Resolve(Api.World, "carburizable output")) { inv[0].Itemstack.StackSize -= 8; inv[1].Itemstack = jstack.ResolvedItemstack.Clone(); inv[1].Itemstack.StackSize = stacksize; } MarkDirty(); msInUse.WalkMatchingBlocks(Api.World, posInUse, (block, pos) => { float resis = block.Attributes?["heatResistance"].AsFloat(1) ?? 1; if (Api.World.Rand.NextDouble() > resis) { Block nowblock = Api.World.GetBlock(block.CodeWithVariant("state", "damaged")); Api.World.BlockAccessor.SetBlock(nowblock.Id, pos); } }); processComplete = true; } }
public bool Interact(IPlayer byPlayer, bool preferThis) { bool sneaking = byPlayer.WorldData.EntityControls.Sneak; int damagedTiles = 0; int wrongTiles = 0; int incompleteCount = 0; BlockPos posMain = Pos; // set up incompleteCount (etc) for both orientations and pick whichever is more complete if (sneaking) { int ic = 0; int icOpp = int.MaxValue; int dt = 0; int wt = 0; int dtOpp = 0; int wtOpp = 0; ic = ms.InCompleteBlockCount(Api.World, Pos, (haveBlock, wantLoc) => { if (haveBlock.FirstCodePart() == "refractorybricks" && haveBlock.Variant["state"] == "damaged") { dt++; } else { wt++; } } ); if (ic > 0 && blockScs.IsCompleteCoffin(Pos)) { icOpp = msOpp.InCompleteBlockCount(Api.World, Pos.AddCopy(blockScs.Orientation.Opposite), (haveBlock, wantLoc) => { if (haveBlock.FirstCodePart() == "refractorybricks" && haveBlock.Variant["state"] == "damaged") { dtOpp++; } else { wtOpp++; } } ); } // This logic aims to figure out which structure to show - if one is almost complete (3 wrong tiles or less) that one will be shown; preferThis has a preference if both are equally incomplete (newly placed stonecoffin) or if one is not much more complete than the other (allows for building errors of 1-3 tiles before the shown structure flips) if (wtOpp <= 3 && wt < wtOpp || wtOpp > 3 && wt < wtOpp - 3 || preferThis && wt <= wtOpp || preferThis && wt > 3 && wt <= wtOpp + 3) { incompleteCount = ic; damagedTiles = dt; wrongTiles = wt; if (ic > 0) { msHighlighted = ms; } } else { incompleteCount = icOpp; damagedTiles = dtOpp; wrongTiles = wtOpp; msHighlighted = msOpp; posMain = Pos.AddCopy(blockScs.Orientation.Opposite); } } if (sneaking && incompleteCount > 0) { if (wrongTiles > 0 && damagedTiles > 0) { capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, {0} blocks are missing or wrong, {1} tiles are damaged!", wrongTiles, damagedTiles)); } else { if (wrongTiles > 0) { capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, {0} blocks are missing or wrong!", wrongTiles)); } else { if (damagedTiles == 1) { capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, {0} tile is damaged!", damagedTiles)); } else { capi?.TriggerIngameError(this, "incomplete", Lang.Get("Structure is not complete, {0} tiles are damaged!", damagedTiles)); } } } if (Api.Side == EnumAppSide.Client) { msHighlighted.HighlightIncompleteParts(Api.World, byPlayer, posMain); } return(false); } else { if (Api.Side == EnumAppSide.Client) { msHighlighted?.ClearHighlights(Api.World, byPlayer); } } if (!sneaking) { return(false); } if (!blockScs.IsCompleteCoffin(Pos)) { capi?.TriggerIngameError(this, "incomplete", Lang.Get("Cannot fill an incomplete coffin, place the other half first")); return(false); } ItemSlot slot = byPlayer.InventoryManager.ActiveHotbarSlot; if (!slot.Empty) { if (IngotCount / 4 >= CoalLayerCount) { return(AddCoal(slot)); } else { return(AddIngot(slot)); } } return(true); }