internal void UpdateVoxel(IPlayer byPlayer, Vec3i voxelPos, BlockFacing facing, bool isBreak) { Vec3i addAtPos = voxelPos.Clone().Add(facing); if (!isBreak) { if (addAtPos.X >= 0 && addAtPos.X < 16 && addAtPos.Y >= 0 && addAtPos.Y < 16 && addAtPos.Z >= 0 && addAtPos.Z < 16) { Voxels[addAtPos.X, addAtPos.Y, addAtPos.Z] = true; } } else { Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] = false; } if (api.Side == EnumAppSide.Client) { RegenMesh(); } RegenSelectionBoxes(); MarkDirty(true); // Send a custom network packet for server side, because // serverside blockselection index is inaccurate if (api.Side == EnumAppSide.Client) { SendUseOverPacket(byPlayer, voxelPos, facing, isBreak); } }
private Vec3i getClosestBfs(Vec3i voxelPos, BlockFacing towardsFace, int maxDist) { Queue <Vec3i> nodesToVisit = new Queue <Vec3i>(); HashSet <Vec3i> nodesVisited = new HashSet <Vec3i>(); nodesToVisit.Enqueue(voxelPos); while (nodesToVisit.Count > 0) { Vec3i node = nodesToVisit.Dequeue(); for (int i = 0; i < BlockFacing.HORIZONTALS.Length; i++) { BlockFacing face = BlockFacing.HORIZONTALS[i]; Vec3i nnode = node.Clone().Add(face); if (nnode.X < 0 || nnode.X >= 16 || nnode.Y < 0 || nnode.Y >= 6 || nnode.Z < 0 || nnode.Z >= 16) { continue; } if (nodesVisited.Contains(nnode)) { continue; } nodesVisited.Add(nnode); double x = nnode.X - voxelPos.X; double z = nnode.Z - voxelPos.Z; double len = GameMath.Sqrt(x * x + z * z); if (len > maxDist) { continue; } x /= len; z /= len; if (towardsFace == null || Math.Abs((float)Math.Acos(towardsFace.Normalf.X * x + towardsFace.Normalf.Z * z)) < 25 * GameMath.DEG2RAD) { if (Voxels[nnode.X, nnode.Y, nnode.Z] == (byte)EnumVoxelMaterial.Empty) { return(nnode); } } if (Voxels[nnode.X, nnode.Y, nnode.Z] == (byte)EnumVoxelMaterial.Metal) { nodesToVisit.Enqueue(nnode); } } } return(null); }
public void OnUseOver(IPlayer byPlayer, Vec3i voxelHitPos, Vec3i voxelBoxPos, BlockFacing facing, ItemStack itemStack, bool mouseBreakMode) { Item heldItem = itemStack?.Item; if (heldItem?.Code?.ToString() == "signals:el_wire") { if (mouseBreakMode) { if (wiring.OnRemove(voxelHitPos)) { AvailableWireVoxels++; if (AvailableWireVoxels >= 25) { byPlayer.InventoryManager.TryGiveItemstack(new ItemStack(heldItem)); AvailableWireVoxels = 0; } } return; } if (canPlaceWireAt(voxelHitPos.AddCopy(facing))) { if (AvailableWireVoxels == 0) { AvailableWireVoxels = 25; //slot.TakeOut(1); //slot.MarkDirty(); } wiring.OnAdd(voxelHitPos.AddCopy(facing)); AvailableWireVoxels--; } return; } CircuitComponent comp = SignalsUtils.GetCircuitComponentFromItem(api, heldItem); if (comp != null) { comp.Pos = voxelBoxPos.Clone(); comp.myCircuit = this; comp.Initialize(api, this); components.Add(comp); } }
internal void UpdateVoxel(IPlayer byPlayer, ItemSlot itemslot, Vec3i voxelPos, BlockFacing facing, bool isBreak) { int mode = ChiselMode(byPlayer); if (mode == 5) { IClientWorldAccessor clientWorld = (IClientWorldAccessor)api.World; string prevName = blockName; GuiDialogBlockEntityTextInput dlg = new GuiDialogBlockEntityTextInput(Lang.Get("Block name"), pos, blockName, api as ICoreClientAPI); dlg.OnTextChanged = (text) => blockName = text; dlg.OnCloseCancel = () => blockName = prevName; dlg.TryOpen(); } bool wasChanged = false; if (mode == 4) { RotateModel(byPlayer, isBreak); wasChanged = true; } else { int size = ChiselSize(byPlayer); Vec3i addAtPos = voxelPos.Clone().Add(size * facing.Normali.X, size * facing.Normali.Y, size * facing.Normali.Z); if (isBreak) { wasChanged = SetVoxel(voxelPos, false, byPlayer); } else { if (addAtPos.X >= 0 && addAtPos.X < 16 && addAtPos.Y >= 0 && addAtPos.Y < 16 && addAtPos.Z >= 0 && addAtPos.Z < 16) { wasChanged = SetVoxel(addAtPos, true, byPlayer); } } } if (!wasChanged) { return; } if (api.Side == EnumAppSide.Client) { RegenMesh(); } RegenSelectionBoxes(byPlayer); MarkDirty(true); // Send a custom network packet for server side, because // serverside blockselection index is inaccurate if (api.Side == EnumAppSide.Client) { SendUseOverPacket(byPlayer, voxelPos, facing, isBreak); } double posx = pos.X + voxelPos.X / 16f; double posy = pos.Y + voxelPos.Y / 16f; double posz = pos.Z + voxelPos.Z / 16f; api.World.PlaySoundAt(new AssetLocation("sounds/player/knap" + (api.World.Rand.Next(2) > 0 ? 1 : 2)), posx, posy, posz, byPlayer, true, 12, 1); if (byPlayer.WorldData.CurrentGameMode != EnumGameMode.Creative) { itemslot.Itemstack?.Collectible.DamageItem(api.World, byPlayer.Entity, itemslot); } if (VoxelCuboids.Count == 0) { api.World.BlockAccessor.SetBlock(0, pos); return; } }
public virtual void OnHit(Vec3i voxelPos) { if (Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] != (byte)EnumVoxelMaterial.Metal) { return; } if (voxelPos.Y > 0) { int voxelsMoved = 0; for (int dx = -1; dx <= 1; dx++) { for (int dz = -1; dz <= 1; dz++) { if (dx == 0 && dz == 0) { continue; } if (voxelPos.X + dx < 0 || voxelPos.X + dx >= 16 || voxelPos.Z + dz < 0 || voxelPos.Z + dz >= 16) { continue; } if (Voxels[voxelPos.X + dx, voxelPos.Y, voxelPos.Z + dz] == (byte)EnumVoxelMaterial.Metal) { voxelsMoved += moveVoxelDownwards(voxelPos.Clone().Add(dx, 0, dz), null, 1) ? 1 : 0; } } } if (Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] == (byte)EnumVoxelMaterial.Metal) { voxelsMoved += moveVoxelDownwards(voxelPos.Clone(), null, 1) ? 1 : 0; } if (voxelsMoved == 0) { Vec3i emptySpot = null; for (int dx = -1; dx <= 1; dx++) { for (int dz = -1; dz <= 1; dz++) { if (dx == 0 && dz == 0) { continue; } if (voxelPos.X + 2 * dx < 0 || voxelPos.X + 2 * dx >= 16 || voxelPos.Z + 2 * dz < 0 || voxelPos.Z + 2 * dz >= 16) { continue; } bool spotEmpty = Voxels[voxelPos.X + 2 * dx, voxelPos.Y, voxelPos.Z + 2 * dz] == (byte)EnumVoxelMaterial.Empty; if (Voxels[voxelPos.X + dx, voxelPos.Y, voxelPos.Z + dz] == (byte)EnumVoxelMaterial.Metal && spotEmpty) { Voxels[voxelPos.X + dx, voxelPos.Y, voxelPos.Z + dz] = (byte)EnumVoxelMaterial.Empty; if (Voxels[voxelPos.X + 2 * dx, voxelPos.Y - 1, voxelPos.Z + 2 * dz] == (byte)EnumVoxelMaterial.Empty) { Voxels[voxelPos.X + 2 * dx, voxelPos.Y - 1, voxelPos.Z + 2 * dz] = (byte)EnumVoxelMaterial.Metal; } else { Voxels[voxelPos.X + 2 * dx, voxelPos.Y, voxelPos.Z + 2 * dz] = (byte)EnumVoxelMaterial.Metal; } } else { if (spotEmpty) { emptySpot = voxelPos.Clone().Add(dx, 0, dz); } } } } if (emptySpot != null && Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] == (byte)EnumVoxelMaterial.Metal) { Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] = (byte)EnumVoxelMaterial.Empty; if (Voxels[emptySpot.X, emptySpot.Y - 1, emptySpot.Z] == (byte)EnumVoxelMaterial.Empty) { Voxels[emptySpot.X, emptySpot.Y - 1, emptySpot.Z] = (byte)EnumVoxelMaterial.Metal; } else { Voxels[emptySpot.X, emptySpot.Y, emptySpot.Z] = (byte)EnumVoxelMaterial.Metal; } } } } }
public virtual void OnUpset(Vec3i voxelPos, BlockFacing towardsFace) { if (Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] != (byte)EnumVoxelMaterial.Metal) { return; } Vec3i npos = voxelPos.Clone().Add(towardsFace); Vec3i opFaceDir = towardsFace.Opposite.Normali; if (npos.X < 0 || npos.X >= 16 || npos.Y < 0 || npos.Y >= 6 || npos.Z < 0 || npos.Z >= 16) { return; } if (voxelPos.Y > 0) { if (Voxels[npos.X, npos.Y, npos.Z] == (byte)EnumVoxelMaterial.Empty && Voxels[npos.X, npos.Y - 1, npos.Z] != (byte)EnumVoxelMaterial.Empty) { if (npos.X < 0 || npos.X >= 16 || npos.Y < 0 || npos.Y >= 6 || npos.Z < 0 || npos.Z >= 16) { return; } Voxels[npos.X, npos.Y, npos.Z] = (byte)EnumVoxelMaterial.Metal; Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] = 0; return; } else { npos.Y++; if (npos.Y < 6 && Voxels[npos.X, npos.Y, npos.Z] == (byte)EnumVoxelMaterial.Empty && Voxels[npos.X, npos.Y - 1, npos.Z] != (byte)EnumVoxelMaterial.Empty && Voxels[voxelPos.X + opFaceDir.X, voxelPos.Y, voxelPos.Z + opFaceDir.Z] == (byte)EnumVoxelMaterial.Empty) { Voxels[npos.X, npos.Y, npos.Z] = (byte)EnumVoxelMaterial.Metal; Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] = (byte)EnumVoxelMaterial.Empty; return; } if (!moveVoxelDownwards(voxelPos.Clone(), towardsFace, 1)) { moveVoxelDownwards(voxelPos.Clone(), towardsFace, 2); } } return; } npos.Y++; if (npos.X < 0 || npos.X >= 16 || npos.Y < 0 || npos.Y >= 6 || npos.Z < 0 || npos.Z >= 16) { return; } if (voxelPos.X + opFaceDir.X < 0 || voxelPos.X + opFaceDir.X >= 16 || voxelPos.Z + opFaceDir.Z < 0 || voxelPos.Z + opFaceDir.Z >= 16) { return; } if (npos.Y < 6 && Voxels[npos.X, npos.Y, npos.Z] == (byte)EnumVoxelMaterial.Empty && Voxels[npos.X, npos.Y - 1, npos.Z] != (byte)EnumVoxelMaterial.Empty && Voxels[voxelPos.X + opFaceDir.X, voxelPos.Y, voxelPos.Z + opFaceDir.Z] == (byte)EnumVoxelMaterial.Empty) { Voxels[npos.X, npos.Y, npos.Z] = (byte)EnumVoxelMaterial.Metal; Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z] = (byte)EnumVoxelMaterial.Empty; return; } }
internal void UpdateVoxel(IPlayer byPlayer, ItemSlot itemslot, Vec3i voxelPos, BlockFacing facing, bool isBreak) { if (!Api.World.Claims.TryAccess(byPlayer, Pos, EnumBlockAccessFlags.Use)) { MarkDirty(true, byPlayer); return; } EnumChiselMode mode = GetChiselMode(byPlayer); bool wasChanged = false; byte[] lightHsv = this.LightHsv; switch (mode) { case EnumChiselMode.Rename: IClientWorldAccessor clientWorld = (IClientWorldAccessor)Api.World; string prevName = BlockName; GuiDialogBlockEntityTextInput dlg = new GuiDialogBlockEntityTextInput(Lang.Get("Block name"), Pos, BlockName, Api as ICoreClientAPI, 500); dlg.OnTextChanged = (text) => BlockName = text; dlg.OnCloseCancel = () => BlockName = prevName; dlg.TryOpen(); break; case EnumChiselMode.Flip: FlipVoxels(Block.SuggestedHVOrientation(byPlayer, new BlockSelection() { Position = Pos.Copy(), HitPosition = new Vec3d(voxelPos.X / 16.0, voxelPos.Y / 16.0, voxelPos.Z / 16.0) })[0]); wasChanged = true; break; case EnumChiselMode.Rotate: RotateModel(isBreak ? 90 : -90, null); wasChanged = true; break; default: int size = GetChiselSize(byPlayer); Vec3i addAtPos = voxelPos.Clone().Add(size * facing.Normali.X, size * facing.Normali.Y, size * facing.Normali.Z); if (isBreak) { wasChanged = SetVoxel(voxelPos, false, byPlayer, nowmaterialIndex); } else { if (addAtPos.X >= 0 && addAtPos.X < 16 && addAtPos.Y >= 0 && addAtPos.Y < 16 && addAtPos.Z >= 0 && addAtPos.Z < 16) { wasChanged = SetVoxel(addAtPos, true, byPlayer, nowmaterialIndex); } } break; } if (!wasChanged) { return; } if (Api.Side == EnumAppSide.Client) { RegenMesh(); } RegenSelectionBoxes(byPlayer); MarkDirty(true, byPlayer); // Send a custom network packet for server side, because // serverside blockselection index is inaccurate if (Api.Side == EnumAppSide.Client) { SendUseOverPacket(byPlayer, voxelPos, facing, isBreak); } double posx = Pos.X + voxelPos.X / 16f; double posy = Pos.Y + voxelPos.Y / 16f; double posz = Pos.Z + voxelPos.Z / 16f; Api.World.PlaySoundAt(new AssetLocation("sounds/player/knap" + (Api.World.Rand.Next(2) > 0 ? 1 : 2)), posx, posy, posz, byPlayer, true, 12, 1); if (byPlayer.WorldData.CurrentGameMode != EnumGameMode.Creative && Api.World.Rand.Next(3) == 0) { itemslot.Itemstack?.Collectible.DamageItem(Api.World, byPlayer.Entity, itemslot); } if (VoxelCuboids.Count == 0) { Api.World.BlockAccessor.SetBlock(0, Pos); Api.World.BlockAccessor.RemoveBlockLight(LightHsv, Pos); return; } }