private string GetSuggestedKnobOrientation(IBlockAccessor ba, BlockPos pos, BlockFacing facing) { string leftOrRight = "left"; Block nBlock1 = ba.GetBlock(pos.AddCopy(facing.GetCCW())); Block nBlock2 = ba.GetBlock(pos.AddCopy(facing.GetCW())); bool isDoor1 = IsSameDoor(nBlock1); bool isDoor2 = IsSameDoor(nBlock2); if (isDoor1 && isDoor2) { leftOrRight = "left"; } else { if (isDoor1) { leftOrRight = GetKnobOrientation(nBlock1) == "right" ? "left" : "right"; } else if (isDoor2) { leftOrRight = GetKnobOrientation(nBlock2) == "right" ? "left" : "right"; } } return(leftOrRight); }
protected override BlockPos TryGetConnectedDoorPos(BlockPos pos) { string knob = GetKnobOrientation(); BlockFacing dir = GetDirection(); return(knob == "left" ? pos.AddCopy(dir.GetCW()) : pos.AddCopy(dir.GetCCW())); }
//Take a block code (that ends in a cardinal direction) and a BlockFacing, //and rotate it, returning the appropriate blockfacing public static BlockFacing OrientFace(string checkBlockCode, BlockFacing toChange) { if (!toChange.IsHorizontal) { return(toChange); } if (checkBlockCode.EndsWith("east")) { toChange = toChange.GetCW(); } else if (checkBlockCode.EndsWith("south")) { toChange = toChange.GetCW().GetCW(); } else if (checkBlockCode.EndsWith("west")) { toChange = toChange.GetCCW(); } return(toChange); }
private string GetSuggestedKnobOrientation(IBlockAccessor ba, BlockPos pos, BlockFacing facing, out bool neighbourOpen) { string leftOrRight = "left"; Block nBlock1 = ba.GetBlock(pos.AddCopy(facing.GetCW())); Block nBlock2 = ba.GetBlock(pos.AddCopy(facing.GetCCW())); bool invert = facing == BlockFacing.EAST || facing == BlockFacing.SOUTH; //doors and gates assets are setup for n or w orientations bool isDoor1 = IsSameDoor(nBlock1); bool isDoor2 = IsSameDoor(nBlock2); if (isDoor1 && isDoor2) { leftOrRight = "left"; neighbourOpen = (nBlock1 as BlockBaseDoor).IsOpened(); } else { if (isDoor1) { if (GetKnobOrientation(nBlock1) == "right") //facing gate: the gate to the right, has its hinge away from us { leftOrRight = invert ? "left" : "right"; neighbourOpen = false; } else { leftOrRight = invert ? "right" : "left"; neighbourOpen = (nBlock1 as BlockBaseDoor).IsOpened(); } } else if (isDoor2) { if (GetKnobOrientation(nBlock2) == "right") //facing gate: the gate to the left, has its hinge towards us ("knob" is hinge apparently) { leftOrRight = invert ? "right" : "left"; neighbourOpen = false; } else { leftOrRight = invert ? "left" : "right"; neighbourOpen = (nBlock2 as BlockBaseDoor).IsOpened(); } } else { //no neighbouring gate, but some AI for trying to guess which side the player wants the hinge (including potentially the first gate to be placed of a double gate) neighbourOpen = false; if (nBlock1.Attributes?.IsTrue("isFence") == true ^ nBlock2.Attributes?.IsTrue("isFence") == true) { leftOrRight = (invert ^ nBlock2.Attributes?.IsTrue("isFence") == true) ? "left" : "right"; } else if (nBlock2.Replaceable >= 6000 && nBlock1.Replaceable < 6000) //empty space on left, place hinge on right { leftOrRight = invert ? "left" : "right"; } else if (nBlock1.Replaceable >= 6000 && nBlock2.Replaceable < 6000) //empty space on right, place hinge on left { leftOrRight = invert ? "right" : "left"; } } } return(leftOrRight); }
protected override BlockPos TryGetConnectedDoorPos(BlockPos pos) { BlockFacing dir = GetDirection(); return(pos.AddCopy(dir.GetCW())); }
protected virtual BlockFacing[] OrientForPlacement(IBlockAccessor worldmap, IPlayer player, BlockSelection bs) { BlockFacing[] facings = SuggestedHVOrientation(player, bs); BlockPos pos = bs.Position; BlockFacing horizontal = null; BlockFacing face = bs.Face.Opposite; BlockFacing vert = null; //If player is placing against a block horizontally, check that one and all other horizontals for connectors if (face.IsHorizontal) { if (HasConnector(worldmap, pos.AddCopy(face), bs.Face, out vert)) { horizontal = face; } else { face = face.GetCW(); if (HasConnector(worldmap, pos.AddCopy(face), face.Opposite, out vert)) { horizontal = face; } else if (HasConnector(worldmap, pos.AddCopy(face.Opposite), face, out vert)) { horizontal = face.Opposite; } else if (HasConnector(worldmap, pos.AddCopy(bs.Face), bs.Face.Opposite, out vert)) { horizontal = bs.Face; } } //Special case: the 3way has two connectors but the directional attribute covers only one of them if (Type == "3way" && horizontal != null) { face = horizontal.GetCW(); BlockFacing unused = null; if (HasConnector(worldmap, pos.AddCopy(face), face.Opposite, out unused) && !HasConnector(worldmap, pos.AddCopy(face.Opposite), face, out unused)) { horizontal = face; } } } else { //Player is placing against a block vertically, use that as the vertical connection and check all horizontals for connectors vert = face; bool moreThanOne = false; horizontal = HasConnector(worldmap, pos.EastCopy(), BlockFacing.WEST, out vert) ? BlockFacing.EAST : null; if (HasConnector(worldmap, pos.WestCopy(), BlockFacing.EAST, out vert)) { moreThanOne = horizontal != null; horizontal = BlockFacing.WEST; } if (HasConnector(worldmap, pos.NorthCopy(), BlockFacing.SOUTH, out vert)) { moreThanOne = horizontal != null; horizontal = BlockFacing.NORTH; } if (HasConnector(worldmap, pos.SouthCopy(), BlockFacing.NORTH, out vert)) { moreThanOne = horizontal != null; horizontal = BlockFacing.SOUTH; } if (moreThanOne) { horizontal = null; } } if (vert == null) { //If vertical orientation not already chosen, see whether there is an existing open connector up or down BlockFacing unused = null; bool up = HasConnector(worldmap, pos.UpCopy(), BlockFacing.DOWN, out unused); bool down = HasConnector(worldmap, pos.DownCopy(), BlockFacing.UP, out unused); if (up && !down) { vert = BlockFacing.UP; } else if (down && !up) { vert = BlockFacing.DOWN; } } if (vert != null) { facings[1] = vert; } facings[0] = horizontal ?? facings[0].Opposite; return(facings); }
/// <summary> /// Attempts to transform each block as they are placed in directions different from the schematic. /// </summary> /// <param name="worldForResolve"></param> /// <param name="aroundOrigin"></param> /// <param name="angle"></param> /// <param name="flipAxis"></param> public virtual void TransformWhilePacked(IWorldAccessor worldForResolve, EnumOrigin aroundOrigin, int angle, EnumAxis?flipAxis = null) { BlockPos curPos = new BlockPos(); BlockPos startPos = new BlockPos(1024, 1024, 1024); BlocksUnpacked.Clear(); BlockEntitiesUnpacked.Clear(); DecorsUnpacked.Clear(); EntitiesUnpacked.Clear(); angle = GameMath.Mod(angle, 360); for (int i = 0; i < Indices.Count; i++) { uint index = Indices[i]; int storedBlockid = BlockIds[i]; int dx = (int)(index & 0x1ff); int dy = (int)((index >> 20) & 0x1ff); int dz = (int)((index >> 10) & 0x1ff); AssetLocation blockCode = BlockCodes[storedBlockid]; Block newBlock = worldForResolve.GetBlock(blockCode); if (newBlock == null) { BlockEntities.Remove(index); continue; } if (flipAxis != null) { if (flipAxis == EnumAxis.Y) { dy = SizeY - dy; AssetLocation newCode = newBlock.GetVerticallyFlippedBlockCode(); newBlock = worldForResolve.GetBlock(newCode); } if (flipAxis == EnumAxis.X) { dx = SizeX - dx; AssetLocation newCode = newBlock.GetHorizontallyFlippedBlockCode((EnumAxis)flipAxis); newBlock = worldForResolve.GetBlock(newCode); } if (flipAxis == EnumAxis.Z) { dz = SizeZ - dz; AssetLocation newCode = newBlock.GetHorizontallyFlippedBlockCode((EnumAxis)flipAxis); newBlock = worldForResolve.GetBlock(newCode); } } if (angle != 0) { AssetLocation newCode = newBlock.GetRotatedBlockCode(angle); newBlock = worldForResolve.GetBlock(newCode); } if (aroundOrigin != EnumOrigin.StartPos) { dx -= SizeX / 2; dz -= SizeZ / 2; } BlockPos pos = new BlockPos(dx, dy, dz); // 90 deg: // xNew = -yOld // yNew = xOld // 180 deg: // xNew = -xOld // yNew = -yOld // 270 deg: // xNew = yOld // yNew = -xOld switch (angle) { case 90: pos.Set(-dz, dy, dx); break; case 180: pos.Set(-dx, dy, -dz); break; case 270: pos.Set(dz, dy, -dx); break; } if (aroundOrigin != EnumOrigin.StartPos) { pos.X += SizeX / 2; pos.Z += SizeZ / 2; } BlocksUnpacked[pos] = newBlock.BlockId; } for (int i = 0; i < DecorIndices.Count; i++) { uint index = DecorIndices[i]; int storedBlockid = DecorIds[i]; byte faceIndex = (byte)(storedBlockid >> 24); if (faceIndex > 5) { continue; } BlockFacing face = BlockFacing.ALLFACES[faceIndex]; int dx = (int)(index & 0x1ff); int dy = (int)((index >> 20) & 0x1ff); int dz = (int)((index >> 10) & 0x1ff); AssetLocation blockCode = BlockCodes[storedBlockid & 0xFFFFFF]; Block newBlock = worldForResolve.GetBlock(blockCode); if (newBlock == null) { continue; } if (flipAxis != null) { if (flipAxis == EnumAxis.Y) { dy = SizeY - dy; AssetLocation newCode = newBlock.GetVerticallyFlippedBlockCode(); newBlock = worldForResolve.GetBlock(newCode); if (face.IsVertical) { face = face.Opposite; } } if (flipAxis == EnumAxis.X) { dx = SizeX - dx; AssetLocation newCode = newBlock.GetHorizontallyFlippedBlockCode((EnumAxis)flipAxis); newBlock = worldForResolve.GetBlock(newCode); if (face.Axis == EnumAxis.X) { face = face.Opposite; } } if (flipAxis == EnumAxis.Z) { dz = SizeZ - dz; AssetLocation newCode = newBlock.GetHorizontallyFlippedBlockCode((EnumAxis)flipAxis); newBlock = worldForResolve.GetBlock(newCode); if (face.Axis == EnumAxis.Z) { face = face.Opposite; } } } if (angle != 0) { AssetLocation newCode = newBlock.GetRotatedBlockCode(angle); newBlock = worldForResolve.GetBlock(newCode); } if (aroundOrigin != EnumOrigin.StartPos) { dx -= SizeX / 2; dz -= SizeZ / 2; } BlockPos pos = new BlockPos(dx, dy, dz); // 90 deg: // xNew = -yOld // yNew = xOld // 180 deg: // xNew = -xOld // yNew = -yOld // 270 deg: // xNew = yOld // yNew = -xOld switch (angle) { case 90: pos.Set(-dz, dy, dx); if (face.IsHorizontal) { face = face.GetCW(); } break; case 180: pos.Set(-dx, dy, -dz); if (face.IsHorizontal) { face = face.Opposite; } break; case 270: pos.Set(dz, dy, -dx); if (face.IsHorizontal) { face = face.GetCCW(); } break; } if (aroundOrigin != EnumOrigin.StartPos) { pos.X += SizeX / 2; pos.Z += SizeZ / 2; } DecorsUnpacked.TryGetValue(pos, out Block[] decorsTmp); if (decorsTmp == null) { decorsTmp = new Block[6]; DecorsUnpacked[pos] = decorsTmp; } decorsTmp[face.Index] = newBlock; } foreach (var val in BlockEntities) { uint index = val.Key; int dx = (int)(index & 0x1ff); int dy = (int)((index >> 20) & 0x1ff); int dz = (int)((index >> 10) & 0x1ff); dx -= SizeX / 2; dz -= SizeZ / 2; BlockPos pos = new BlockPos(dx, dy, dz); // 90 deg: // xNew = -yOld // yNew = xOld // 180 deg: // xNew = -xOld // yNew = -yOld // 270 deg: // xNew = yOld // yNew = -xOld switch (angle) { case 90: pos.Set(-dz, dy, dx); break; case 180: pos.Set(-dx, dy, -dz); break; case 270: pos.Set(dz, dy, -dx); break; } pos.X += SizeX / 2; pos.Z += SizeZ / 2; curPos.Set(pos.X + startPos.X, pos.Y + startPos.Y, pos.Z + startPos.Z); string beData = val.Value; string entityclass = worldForResolve.GetBlock(BlocksUnpacked[pos]).EntityClass; if (entityclass != null) { BlockEntity be = worldForResolve.ClassRegistry.CreateBlockEntity(entityclass); if (be is IBlockEntityRotatable) { ITreeAttribute tree = DecodeBlockEntityData(beData); (be as IBlockEntityRotatable).OnTransformed(tree, angle, flipAxis); beData = StringEncodeTreeAttribute(tree); } BlockEntitiesUnpacked[pos] = beData; } } foreach (string entityData in Entities) { using (MemoryStream ms = new MemoryStream(Ascii85.Decode(entityData))) { BinaryReader reader = new BinaryReader(ms); string className = reader.ReadString(); Entity entity = worldForResolve.ClassRegistry.CreateEntity(className); entity.FromBytes(reader, false); entity.DidImportOrExport(startPos); double dx = entity.ServerPos.X - startPos.X; double dy = entity.ServerPos.Y - startPos.Y; double dz = entity.ServerPos.Z - startPos.Z; dx -= SizeX / 2; dz -= SizeZ / 2; Vec3d pos = new Vec3d(); // 90 deg: // xNew = -yOld // yNew = xOld // 180 deg: // xNew = -xOld // yNew = -yOld // 270 deg: // xNew = yOld // yNew = -xOld switch (angle) { case 90: pos.Set(-dz, dy, dx); break; case 180: pos.Set(-dx, dy, -dz); break; case 270: pos.Set(dz, dy, -dx); break; } pos.X += SizeX / 2; pos.Z += SizeZ / 2; entity.ServerPos.SetPos(startPos.X + pos.X, entity.ServerPos.Y, startPos.Z + pos.Z); entity.Pos.SetPos(startPos.X + pos.X, entity.Pos.Y, startPos.Z + pos.Z); entity.PositionBeforeFalling.Set(startPos.X + pos.X, entity.PositionBeforeFalling.Y, startPos.Z + pos.Z); EntitiesUnpacked.Add(entity); } } Pack(worldForResolve, startPos); }
private void CheckWater(float dt) { willSpeed = 0; BlockPos block1pos = Position.AddCopy(face.GetCCW()).AddCopy(face.GetCCW()); Block block1 = Api.World.BlockAccessor.GetBlock(block1pos); Block block2 = Api.World.BlockAccessor.GetBlock(block1pos.AddCopy(BlockFacing.DOWN)); Block block3 = Api.World.BlockAccessor.GetBlock(block1pos.AddCopy(BlockFacing.UP)); if (block1.Code.BeginsWith("game", "water-d")) { willSpeed++; } if (block2.Code.BeginsWith("game", "water-d")) { willSpeed++; } if (block3.Code.BeginsWith("game", "water-d")) { willSpeed++; } BlockPos block2pos = Position.AddCopy(face.GetCW()).AddCopy(face.GetCW()); Block block21 = Api.World.BlockAccessor.GetBlock(block2pos); Block block22 = Api.World.BlockAccessor.GetBlock(block2pos.AddCopy(BlockFacing.DOWN)); Block block23 = Api.World.BlockAccessor.GetBlock(block2pos.AddCopy(BlockFacing.UP)); if (block21.Code.BeginsWith("game", "water-d")) { willSpeed--; } if (block22.Code.BeginsWith("game", "water-d")) { willSpeed--; } if (block23.Code.BeginsWith("game", "water-d")) { willSpeed--; } BlockPos block4pos = Position.AddCopy(BlockFacing.DOWN).AddCopy(BlockFacing.DOWN); Block block4 = Api.World.BlockAccessor.GetBlock(block4pos); Block block5 = Api.World.BlockAccessor.GetBlock(block4pos.AddCopy(face.GetCCW())); Block block6 = Api.World.BlockAccessor.GetBlock(block4pos.AddCopy(face.GetCW())); string waterpath = "water-" + face.GetCW().Code[0]; string waterpath2 = "water-" + face.GetCCW().Code[0]; if (block4.Code.BeginsWith("game", waterpath)) { willSpeed++; } else if (block4.Code.BeginsWith("game", waterpath2)) { willSpeed--; } if (block5.Code.BeginsWith("game", waterpath)) { willSpeed++; } else if (block5.Code.BeginsWith("game", waterpath2)) { willSpeed--; } if (block6.Code.BeginsWith("game", waterpath)) { willSpeed++; } else if (block6.Code.BeginsWith("game", waterpath2)) { willSpeed--; } if (willSpeed < 0) { willSpeed = Math.Abs(willSpeed); //SetPropagationDirection(new MechPowerPath(face.Opposite, 1 /*GearedRatio*/, null, true)); propagationDir = OutFacingForNetworkDiscovery.Opposite; } else { //SetPropagationDirection(new MechPowerPath(face.Opposite, 1 /*GearedRatio*/, null, false)); propagationDir = OutFacingForNetworkDiscovery; } }