private void DamageNearbyBlocks(IPlayer player, BlockSelection blockSel, float damage, int leftDurability) { Block block = player.Entity.World.BlockAccessor.GetBlock(blockSel.Position); if (!CanMultiBreak(block)) { return; } Vec3d hitPos = blockSel.Position.ToVec3d().Add(blockSel.HitPosition); OrderedDictionary <BlockPos, float> dict = GetNearblyMultibreakables(player.Entity.World, blockSel.Position, hitPos); var orderedPositions = dict.OrderBy(x => x.Value).Select(x => x.Key); int q = Math.Min(MultiBreakQuantity, leftDurability); foreach (var pos in orderedPositions) { if (q == 0) { break; } BlockFacing facing = BlockFacing.FromNormal(player.Entity.ServerPos.GetViewVector()).GetOpposite(); if (!player.Entity.World.Claims.TryAccess(player, blockSel.Position, EnumBlockAccessFlags.BuildOrBreak)) { continue; } player.Entity.World.BlockAccessor.DamageBlock(pos, facing, damage); q--; } }
private bool RequiresStand(BlockPos pos, Vec3i vector) { BlockMPBase block = Api.World.BlockAccessor.GetBlock(pos.X + vector.X, pos.Y + vector.Y, pos.Z + vector.Z) as BlockMPBase; if (block == null) { return(true); } BlockPos sidePos = new BlockPos(pos.X + vector.X, pos.Y + vector.Y, pos.Z + vector.Z); BEBehaviorMPBase bemp = Api.World.BlockAccessor.GetBlockEntity(sidePos)?.GetBehavior <BEBehaviorMPBase>(); if (bemp == null) { return(true); } BEBehaviorMPAxle bempaxle = bemp as BEBehaviorMPAxle; if (bempaxle == null) { if (bemp is BEBehaviorMPBrake || bemp is BEBehaviorMPCreativeRotor) { BlockFacing side = BlockFacing.FromNormal(vector); if (side != null && block.HasMechPowerConnectorAt(Api.World, sidePos, side.Opposite)) { return(false); } } return(true); } if (IsAttachedToBlock(Api.World.BlockAccessor, block, sidePos)) { return(false); } return(bempaxle.RequiresStand(sidePos, vector)); }
private void initSoundsAndTicking() { fuelBlock = Api.World.BlockAccessor.GetBlock(FuelPos); l1 = Blockentity.RegisterGameTickListener(OnTick, 25); if (Api.Side == EnumAppSide.Server) { l2 = Blockentity.RegisterGameTickListener(OnSlowServerTick, 1000); } wsys = Api.ModLoader.GetModSystem <WeatherSystemBase>(); if (ambientSound == null && Api.Side == EnumAppSide.Client) { ambientSound = ((IClientWorldAccessor)Api.World).LoadSound(new SoundParams() { Location = new AssetLocation("sounds/environment/fire.ogg"), ShouldLoop = true, Position = FirePos.ToVec3f().Add(0.5f, 0.25f, 0.5f), DisposeOnFinish = false, Volume = 1f }); if (ambientSound != null) { ambientSound.PlaybackPosition = ambientSound.SoundLengthSeconds * (float)Api.World.Rand.NextDouble(); ambientSound.Start(); } } particleFacing = BlockFacing.FromNormal(new Vec3i(FirePos.X - FuelPos.X, FirePos.Y - FuelPos.Y, FirePos.Z - FuelPos.Z)); }
public void OnNeighbourBlockChange(BlockPos neibpos) { var bh = GetBehavior <FruitTreeGrowingBranchBH>(); if (bh != null) { bh.OnNeighbourBlockChange(BlockFacing.FromNormal((neibpos - Pos).ToVec3i())); } }
public override bool TryPlaceBlock(IWorldAccessor world, IPlayer byPlayer, ItemStack itemstack, BlockSelection blockSel, ref string failureCode) { if (!CanPlaceBlock(world, byPlayer, blockSel, ref failureCode)) { return(false); } foreach (BlockFacing face in BlockFacing.ALLFACES) { BlockPos pos = blockSel.Position.AddCopy(face); IMechanicalPowerBlock block = world.BlockAccessor.GetBlock(pos) as IMechanicalPowerBlock; if (block != null) { if (block.HasMechPowerConnectorAt(world, pos, face.Opposite)) { //Prevent rotor back-to-back placement if (block is IMPPowered) { return(false); } Block toPlaceBlock = world.GetBlock(CodeWithParts(face.Opposite.Code)); world.BlockAccessor.SetBlock(toPlaceBlock.BlockId, blockSel.Position); block.DidConnectAt(world, pos, face.Opposite); WasPlaced(world, blockSel.Position, face); powerOutFacing = face; return(true); } } } if (byPlayer != null && byPlayer.Entity != null) { Vec3f vec = new Vec3d().Ahead(1f, byPlayer.Entity.Pos.Pitch, byPlayer.Entity.Pos.Yaw).ToVec3f(); BlockFacing face = BlockFacing.FromNormal(vec); Block toPlaceBlock = world.GetBlock(CodeWithParts(face.Opposite.Code)); world.BlockAccessor.SetBlock(toPlaceBlock.BlockId, blockSel.Position); WasPlaced(world, blockSel.Position, null); powerOutFacing = face; return(true); } bool ok = base.TryPlaceBlock(world, byPlayer, itemstack, blockSel, ref failureCode); if (ok) { WasPlaced(world, blockSel.Position, null); } return(ok); }
public override bool TryPlaceBlock(IWorldAccessor world, IPlayer byPlayer, ItemStack itemstack, BlockSelection blockSel, ref EnumHandling handling, ref string failureCode) { handling = EnumHandling.PreventDefault; Vec3f vec = new Vec3d().Ahead(1f, byPlayer.Entity.Pos.Pitch, byPlayer.Entity.Pos.Yaw).ToVec3f(); BlockFacing face = BlockFacing.FromNormal(vec).Opposite; AssetLocation blockCode = block.CodeWithVariant("side", face.Code); Block orientedBlock = world.BlockAccessor.GetBlock(blockCode); if (orientedBlock.CanPlaceBlock(world, byPlayer, blockSel, ref failureCode)) { orientedBlock.DoPlaceBlock(world, byPlayer, blockSel, itemstack); return(true); } return(false); }
private bool RequiresStand(BlockPos pos, Vec3i vector) { try { BlockMPBase block = Api.World.BlockAccessor.GetBlock(pos.X + vector.X, pos.Y + vector.Y, pos.Z + vector.Z) as BlockMPBase; if (block == null) { return(true); } BlockPos sidePos = new BlockPos(pos.X + vector.X, pos.Y + vector.Y, pos.Z + vector.Z); BEBehaviorMPBase bemp = Api.World.BlockAccessor.GetBlockEntity(sidePos)?.GetBehavior <BEBehaviorMPBase>(); if (bemp == null) { return(true); } BEBehaviorMPAxle bempaxle = bemp as BEBehaviorMPAxle; if (bempaxle == null) { if (bemp is BEBehaviorMPBrake || bemp is BEBehaviorMPCreativeRotor) { BlockFacing side = BlockFacing.FromNormal(vector); if (side != null && block.HasMechPowerConnectorAt(Api.World, sidePos, side.Opposite)) { return(false); } } return(true); } if (IsAttachedToBlock(Api.World.BlockAccessor, block, sidePos)) { return(false); } return(bempaxle.RequiresStand(sidePos, vector)); } catch (Exception e) { #if DEBUG throw (e); #else Api.Logger.Error("Exception thrown in RequiresStand, will log exception but silently ignore it"); Api.Logger.Error("{0}", e); return(false); #endif } }
/// <summary> /// Loads the meta information for each block in the schematic. /// </summary> /// <param name="blockAccessor"></param> /// <param name="worldForResolve"></param> /// <param name="fileNameForLogging"></param> public void LoadMetaInformationAndValidate(IBlockAccessor blockAccessor, IWorldAccessor worldForResolve, string fileNameForLogging) { List <BlockPos> undergroundPositions = new List <BlockPos>(); Queue <BlockPos> pathwayPositions = new Queue <BlockPos>(); HashSet <AssetLocation> missingBlocks = new HashSet <AssetLocation>(); 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 = blockAccessor.GetBlock(blockCode); if (newBlock == null) { missingBlocks.Add(blockCode); } if (newBlock != pathwayBlock && newBlock != undergroundBlock) { continue; } BlockPos pos = new BlockPos(dx, dy, dz); if (newBlock == pathwayBlock) { pathwayPositions.Enqueue(pos); } else { undergroundPositions.Add(pos); } } if (missingBlocks.Count > 0) { worldForResolve.Logger.Warning("Block schematic file {0} uses blocks that could no longer be found. These will turn into air blocks! (affected: {1})", fileNameForLogging, string.Join(",", missingBlocks)); } HashSet <AssetLocation> missingItems = new HashSet <AssetLocation>(); foreach (var val in ItemCodes) { if (worldForResolve.GetItem(val.Value) == null) { missingItems.Add(val.Value); } } if (missingItems.Count > 0) { worldForResolve.Logger.Warning("Block schematic file {0} uses items that could no longer be found. These will turn into unknown items! (affected: {1})", fileNameForLogging, string.Join(",", missingItems)); } UndergroundCheckPositions = undergroundPositions.ToArray(); List <List <BlockPos> > pathwayslist = new List <List <BlockPos> >(); if (pathwayPositions.Count == 0) { this.PathwayStarts = new BlockPos[0]; this.PathwayOffsets = new BlockPos[0][]; this.PathwaySides = new BlockFacing[0]; return; } while (pathwayPositions.Count > 0) { List <BlockPos> pathway = new List <BlockPos>() { pathwayPositions.Dequeue() }; pathwayslist.Add(pathway); int i = pathwayPositions.Count; while (i-- > 0) { BlockPos pos = pathwayPositions.Dequeue(); bool found = false; for (int j = 0; j < pathway.Count; j++) { BlockPos ppos = pathway[j]; int distance = Math.Abs(pos.X - ppos.X) + Math.Abs(pos.Y - ppos.Y) + Math.Abs(pos.Z - ppos.Z); if (distance == 1) { found = true; pathway.Add(pos); break; } } if (!found) { pathwayPositions.Enqueue(pos); } else { i = pathwayPositions.Count; } } } PathwayStarts = new BlockPos[pathwayslist.Count]; PathwayOffsets = new BlockPos[pathwayslist.Count][]; PathwaySides = new BlockFacing[pathwayslist.Count]; for (int i = 0; i < PathwayStarts.Length; i++) { // Concept to determine on which side the door is: // 1. Iterate over every pathway block // 2. Calculate the vector between the schematic center point an the pathway block // 3. Get the average vector by summing up + divide by count // => this is now basically the centerpoint of the door! // 4. This final vector can now be used to determine the block facing Vec3f dirToMiddle = new Vec3f(); List <BlockPos> pathway = pathwayslist[i]; for (int j = 0; j < pathway.Count; j++) { BlockPos pos = pathway[j]; dirToMiddle.X += pos.X - SizeX / 2f; dirToMiddle.Y += pos.Y - SizeY / 2f; dirToMiddle.Z += pos.Z - SizeZ / 2f; } dirToMiddle.Normalize(); PathwaySides[i] = BlockFacing.FromNormal(dirToMiddle); BlockPos start = PathwayStarts[i] = pathwayslist[i][0].Copy(); PathwayOffsets[i] = new BlockPos[pathwayslist[i].Count]; for (int j = 0; j < pathwayslist[i].Count; j++) { PathwayOffsets[i][j] = pathwayslist[i][j].Sub(start); } } }