public void SetBlockMaterial(Location pos, Material mat, byte dat = 0, byte paint = 0, byte locdat = (byte)BlockFlags.EDITED, BlockDamage damage = BlockDamage.NONE, bool broadcast = true, bool regen = true, bool override_protection = false) { Chunk ch = LoadChunk(ChunkLocFor(pos)); lock (ch.EditSessionLock) { int x = (int)Math.Floor(pos.X) - (int)ch.WorldPosition.X * Chunk.CHUNK_SIZE; int y = (int)Math.Floor(pos.Y) - (int)ch.WorldPosition.Y * Chunk.CHUNK_SIZE; int z = (int)Math.Floor(pos.Z) - (int)ch.WorldPosition.Z * Chunk.CHUNK_SIZE; if (!override_protection && ((BlockFlags)ch.GetBlockAt(x, y, z).BlockLocalData).HasFlag(BlockFlags.PROTECTED)) { return; } BlockInternal bi = new BlockInternal((ushort)mat, dat, paint, locdat) { Damage = damage }; ch.SetBlockAt(x, y, z, bi); ch.LastEdited = GlobalTickTime; ch.Flags |= ChunkFlags.NEEDS_DETECT; ch.ChunkDetect(); // TODO: See if this makes any new chunks visible! if (broadcast) { // TODO: Send per-person based on chunk awareness details ChunkSendToAll(new BlockEditPacketOut(new Location[] { pos }, new ushort[] { bi._BlockMaterialInternal }, new byte[] { dat }, new byte[] { paint }), ch.WorldPosition); } } }
public override Entity Create(Region tregion, BsonDocument doc) { BlockItemEntity ent = new BlockItemEntity(tregion, BlockInternal.FromItemDatum(doc["bie_bi"].AsInt32), Location.Zero); ent.ApplyPhysicsData(doc); return(ent); }
public static bool IsFilled(this BlockInternal bi) { return(((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.FILLED) || ((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.FILLED2) || ((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.FILLED3) || ((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.FILLED4)); }
public override void Execute(PlayerCommandEntry entry) { if (entry.InputArguments.Count < 2) { entry.Player.SendMessage(TextChannel.COMMAND_RESPONSE, "/blockflood <material> <max radius>"); return; } Material chosenMat = MaterialHelpers.FromNameOrNumber(entry.InputArguments[0]); double maxRad = Utilities.StringToFloat(entry.InputArguments[1]); if (maxRad > 50) // TODO: Config! { entry.Player.SendMessage(TextChannel.COMMAND_RESPONSE, "Maximum radius is 50!"); return; } Location start = entry.Player.GetPosition().GetBlockLocation() + new Location(0, 0, 1); HashSet <Location> locs = new HashSet <Location>(); FloodFrom(entry.Player.TheRegion, start, start, maxRad, locs); Location[] tlocs = locs.ToArray(); BlockInternal[] bis = new BlockInternal[tlocs.Length]; for (int i = 0; i < bis.Length; i++) { bis[i] = new BlockInternal((ushort)chosenMat, 0, 0, (byte)BlockFlags.EDITED); } entry.Player.TheRegion.MassBlockEdit(tlocs, bis, false); }
public override void Click(Entity entity, ItemStack item) { if (!(entity is PlayerEntity)) { // TODO: non-player support return; } PlayerEntity player = (PlayerEntity)entity; Location eye = player.GetEyePosition(); Location forw = player.ForwardVector(); RayCastResult rcr; bool h = player.TheRegion.SpecialCaseRayTrace(eye, forw, 5, MaterialSolidity.ANY, player.IgnoreThis, out rcr); if (h) { if (rcr.HitObject != null && rcr.HitObject is EntityCollidable && ((EntityCollidable)rcr.HitObject).Entity != null) { // TODO: ??? } else if (player.Mode.GetDetails().CanPlace) { Location block = (new Location(rcr.HitData.Location) - new Location(rcr.HitData.Normal).Normalize() * 0.01).GetBlockLocation(); block = block.GetBlockLocation(); BlockInternal blockdat = player.TheRegion.GetBlockInternal(block); Material mat = (Material)blockdat.BlockMaterial; if (mat != Material.AIR) { int shape = item.Datum; player.TheRegion.SetBlockMaterial(block, mat, (byte)shape, blockdat.BlockPaint, (byte)(blockdat.BlockLocalData | (byte)BlockFlags.EDITED), blockdat.Damage); } } } }
void Events_ContactCreated(EntityCollidable sender, Collidable other, CollidablePairHandler pair, ContactData contact) { if (TheRegion.GlobalTickTimeLocal - lastSoundTime < soundmaxrate) { return; } lastSoundTime = TheRegion.GlobalTickTimeLocal; if (other is FullChunkObject) { ((ConvexFCOPairHandler)pair).ContactInfo(/*contact.Id*/ 0, out ContactInformation info); float vellen = (float)(Math.Abs(info.RelativeVelocity.X) + Math.Abs(info.RelativeVelocity.Y) + Math.Abs(info.RelativeVelocity.Z)); float mod = vellen / 5; if (mod > 2) { mod = 2; } Location block = new Location(contact.Position - contact.Normal * 0.01f); BlockInternal bi = TheRegion.GetBlockInternal(block); MaterialSound sound = ((Material)bi.BlockMaterial).Sound(); if (sound != MaterialSound.NONE) { new DefaultSoundPacketIn() { TheClient = TheClient }.PlayDefaultBlockSound(block, sound, mod, 0.5f * mod); } MaterialSound sound2 = Mat.Sound(); if (sound2 != MaterialSound.NONE) { new DefaultSoundPacketIn() { TheClient = TheClient }.PlayDefaultBlockSound(block, sound2, mod, 0.5f * mod); } } else if (other is EntityCollidable) { BEPUphysics.Entities.Entity e = ((EntityCollidable)other).Entity; BEPUutilities.Vector3 velocity = BEPUutilities.Vector3.Zero; if (e != null) { velocity = e.LinearVelocity; } BEPUutilities.Vector3 relvel = Body.LinearVelocity - velocity; float vellen = (float)(Math.Abs(relvel.X) + Math.Abs(relvel.Y) + Math.Abs(relvel.Z)); float mod = vellen / 5; if (mod > 2) { mod = 2; } MaterialSound sound = Mat.Sound(); if (sound != MaterialSound.NONE) { new DefaultSoundPacketIn() { TheClient = TheClient }.PlayDefaultBlockSound(new Location(contact.Position), sound, mod, 0.5f * mod); } } }
/// <summary> /// Converts an item to its entity equivalent. /// TODO: Registry / helpers / something / anything! /// </summary> /// <param name="item">The item to convert.</param> /// <returns>An entity.</returns> public PhysicsEntity ItemToEntity(ItemStack item) { if (item.Info is BlockItem) { return(new BlockItemEntity(this, BlockInternal.FromItemDatum(item.Datum), Location.Zero)); } if (item.Info is GlowstickItem) { return(new GlowstickEntity(item.DrawColor, this)); } if (item.Info is SmokegrenadeItem) { return(new SmokeGrenadeEntity(item.DrawColor, this, item.GetAttributeI("big_smoke", 0) == 0 ? ParticleEffectNetType.SMOKE : ParticleEffectNetType.BIG_SMOKE) { SmokeLeft = item.GetAttributeI("max_smoke", 300) }); } if (item.Info is ExplosivegrenadeItem) { return(new ExplosiveGrenadeEntity(this)); } if (item.Info is PaintbombItem) { int paint = item.Datum; return(new PaintBombEntity((byte)paint, this)); } return(new ItemEntity(item, this)); }
public void BreakNaturally(Location pos, bool regentrans = true) { pos = pos.GetBlockLocation(); Chunk ch = LoadChunk(ChunkLocFor(pos)); lock (ch.EditSessionLock) { int x = (int)Math.Floor(pos.X) - (int)ch.WorldPosition.X * Chunk.CHUNK_SIZE; int y = (int)Math.Floor(pos.Y) - (int)ch.WorldPosition.Y * Chunk.CHUNK_SIZE; int z = (int)Math.Floor(pos.Z) - (int)ch.WorldPosition.Z * Chunk.CHUNK_SIZE; BlockInternal bi = ch.GetBlockAt(x, y, z); if (((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.PROTECTED)) { return; } Material mat = (Material)bi.BlockMaterial; ch.BlocksInternal[ch.BlockIndex(x, y, z)].BlockLocalData |= (byte)BlockFlags.PROTECTED; if (mat != (ushort)Material.AIR) { ch.SetBlockAt(x, y, z, new BlockInternal((ushort)Material.AIR, 0, 0, (byte)BlockFlags.EDITED)); ch.LastEdited = GlobalTickTime; SurroundRunPhysics(pos); if (regentrans) { ChunkSendToAll(new BlockEditPacketOut(new Location[] { pos }, new ushort[] { 0 }, new byte[] { 0 }, new byte[] { 0 }), ch.WorldPosition); } bi.Material = mat.GetBreaksInto(); BlockItemEntity bie = new BlockItemEntity(this, new BlockInternal((ushort)bi._BlockMaterialInternal, bi.BlockData, bi._BlockPaintInternal, 0), pos); SpawnEntity(bie); } } }
void SpecialSetBlockAt(Chunk chunk, int X, int Y, int Z, BlockInternal bi) { if (X < 0 || Y < 0 || Z < 0 || X >= Chunk.CHUNK_SIZE || Y >= Chunk.CHUNK_SIZE || Z >= Chunk.CHUNK_SIZE) { Vector3i chloc = chunk.OwningRegion.ChunkLocFor(new Location(X, Y, Z)); Chunk ch = chunk.OwningRegion.LoadChunkNoPopulate(chunk.WorldPosition + chloc); int x = (int)(X - chloc.X * Chunk.CHUNK_SIZE); int y = (int)(Y - chloc.Y * Chunk.CHUNK_SIZE); int z = (int)(Z - chloc.Z * Chunk.CHUNK_SIZE); BlockInternal orig = ch.GetBlockAt(x, y, z); BlockFlags flags = ((BlockFlags)orig.BlockLocalData); if (!flags.HasFlag(BlockFlags.EDITED) && !flags.HasFlag(BlockFlags.PROTECTED)) { // TODO: lock? ch.BlocksInternal[chunk.BlockIndex(x, y, z)] = bi; } } else { BlockInternal orig = chunk.GetBlockAt(X, Y, Z); BlockFlags flags = ((BlockFlags)orig.BlockLocalData); if (!flags.HasFlag(BlockFlags.EDITED) && !flags.HasFlag(BlockFlags.PROTECTED)) { chunk.BlocksInternal[chunk.BlockIndex(X, Y, Z)] = bi; } } }
public ConvexShape ShapeAt(int x, int y, int z, out Vector3 offs) { BlockInternal bi = Blocks[BlockIndex(x, y, z)]; ConvexShape shape = (ConvexShape)BlockShapeRegistry.BSD[bi.BlockData].GetShape(bi.Damage, out Location loffs, false); offs = loffs.ToBVector(); return(shape); }
public void SetBlockAt(int x, int y, int z, BlockInternal mat) { if (SucceededBy != null) { SucceededBy.SetBlockAt(x, y, z, mat); } BlocksInternal[BlockIndex(x, y, z)] = mat; }
public BlockItemEntity(Region tregion, BlockInternal orig, Location pos) : base(tregion) { SetMass(20); CGroup = CollisionUtil.Item; Original = orig; Shape = BlockShapeRegistry.BSD[orig.BlockData].GetShape(orig.Damage, out Location offset, true); SetPosition(pos.GetBlockLocation() + offset); }
public FullChunkObject(Vector3 pos, BlockInternal[] blocks) { ChunkShape = new FullChunkShape(blocks); base.Shape = ChunkShape; Position = pos; boundingBox = new BoundingBox(Position, Position + new Vector3(30, 30, 30)); Events = new ContactEventManager<FullChunkObject>(this); Material.Bounciness = 0.75f; }
public Structure(Region tregion, Location startOfTrace, int maxrad) { // TODO: Optimize tracing! startOfTrace = startOfTrace.GetBlockLocation(); Queue <Location> locs = new Queue <Location>(); HashSet <Location> found = new HashSet <Location>(); List <Location> resultLocs = new List <Location>(); locs.Enqueue(startOfTrace); int maxradsq = maxrad * maxrad; AABB box = new AABB() { Max = startOfTrace, Min = startOfTrace }; while (locs.Count > 0) { Location loc = locs.Dequeue(); if (found.Contains(loc)) { continue; } if (loc.DistanceSquared(startOfTrace) > maxradsq) { throw new Exception("Escaped radius!"); } BlockInternal bi = tregion.GetBlockInternal(loc); if ((Material)bi.BlockMaterial == Material.AIR) { continue; } if (!((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.EDITED)) { throw new Exception("Found natural block!"); } if (((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.PROTECTED)) { throw new Exception("Found protected block!"); } found.Add(loc); resultLocs.Add(loc); box.Include(loc); foreach (Location dir in FloodDirs) { locs.Enqueue(loc + dir); } } Location ext = box.Max - box.Min; Size = new Vector3i((int)ext.X + 1, (int)ext.Y + 1, (int)ext.Z + 1); Origin = new Vector3i((int)Math.Floor(startOfTrace.X - box.Min.X), (int)Math.Floor(startOfTrace.Y - box.Min.Y), (int)Math.Floor(startOfTrace.Z - box.Min.Z)); Blocks = new BlockInternal[Size.X * Size.Y * Size.Z]; foreach (Location loc in resultLocs) { Blocks[BlockIndex((int)(loc.X - box.Min.X), (int)(loc.Y - box.Min.Y), (int)(loc.Z - box.Min.Z))] = tregion.GetBlockInternal(loc); } }
public override Entity Create(Region tregion, byte[] data) { int itsbyte = Utilities.BytesToInt(Utilities.BytesPartial(data, PhysicsEntity.PhysicsNetworkDataLength, 4)); BlockInternal bi = BlockInternal.FromItemDatum(itsbyte); StaticBlockEntity sbe = new StaticBlockEntity(tregion, bi.Material, bi.BlockPaint); sbe.ApplyPhysicsNetworkData(data); return(sbe); }
public void TryPushOne(Location pos, Material mat) { pos = pos.GetBlockLocation(); Vector3i wpos = ChunkLocFor(pos); Vector2i two = new Vector2i(wpos.X, wpos.Y); int rx = (int)(pos.X - wpos.X * Constants.CHUNK_WIDTH); int ry = (int)(pos.Y - wpos.Y * Constants.CHUNK_WIDTH); if (UpperAreas.TryGetValue(two, out BlockUpperArea bua)) { if (mat.IsOpaque()) { bua.TryPush(rx, ry, (int)pos.Z, mat); } else { if (mat.RendersAtAll()) { bua.TryPushTrans(rx, ry, (int)pos.Z, mat); } int min = ChunkManager.GetMins(two.X, two.Y); for (int i = wpos.Z; i >= min; i--) { Chunk chk = LoadChunkNoPopulate(new Vector3i(wpos.X, wpos.Y, i)); if (chk == null || chk.Flags.HasFlag(ChunkFlags.ISCUSTOM)) { continue; } bool pass = false; while (!pass) { lock (chk.GetLocker()) { pass = chk.LoadSchedule == null; } if (!pass) { Thread.Sleep(1); // TODO: Handle loading a still-populating chunk more cleanly. } } for (int z = Constants.CHUNK_WIDTH - 1; z >= 0; z--) { BlockInternal bi = chk.GetBlockAt(rx, ry, z); if (bi.IsOpaque()) { int ind = bua.BlockIndex(rx, ry); bua.Blocks[ind].BasicMat = bi.Material; bua.Blocks[ind].Height = Constants.CHUNK_WIDTH * chk.WorldPosition.Z + z; } } } } } }
public void RunBlockPhysics(Location block) { block = block.GetBlockLocation(); BlockInternal c = GetBlockInternal(block); if (((BlockFlags)c.BlockLocalData).HasFlag(BlockFlags.NEEDS_RECALC)) { c.BlockLocalData = (byte)(c.BlockLocalData & ~((byte)BlockFlags.NEEDS_RECALC)); SetBlockMaterial(block, c, false, false, true); } LiquidPhysics(block, c); }
public void LiquidPhysics(Location block, BlockInternal c) { Material cmat = c.Material; if (!cmat.ShouldSpread()) { return; } Material spreadAs = cmat.GetBigSpreadsAs(); if (spreadAs == Material.AIR) { spreadAs = cmat; } byte cpaint = c.BlockPaint; if (c.BlockData > 5 || c.Damage != BlockDamage.NONE) { PhysicsSetBlock(block, cmat, 0, cpaint, BlockDamage.NONE); return; } Location block_below = block + new Location(0, 0, -1); BlockInternal below = GetBlockInternal(block_below); Material below_mat = below.Material; if (below_mat == Material.AIR) { PhysicsSetBlock(block_below, spreadAs, 0, cpaint, BlockDamage.NONE); return; } byte below_paint = below.BlockPaint; if ((below_mat == spreadAs || below_mat == cmat) && below_paint == cpaint) { if (below.BlockData != 0) { PhysicsSetBlock(block_below, below_mat, 0, cpaint, BlockDamage.NONE); } return; } // TODO: What happens when one liquid is on top of another of a different type?! // For liquid on top of gas, we can swap their places to make the gas rise... // But for the rest? if (c.BlockData == 5) { return; } TryLiquidSpreadSide(block, c, cmat, cpaint, spreadAs, block + new Location(1, 0, 0)); TryLiquidSpreadSide(block, c, cmat, cpaint, spreadAs, block + new Location(-1, 0, 0)); TryLiquidSpreadSide(block, c, cmat, cpaint, spreadAs, block + new Location(0, 1, 0)); TryLiquidSpreadSide(block, c, cmat, cpaint, spreadAs, block + new Location(0, -1, 0)); }
public ConvexShape ShapeAt(int x, int y, int z, out Vector3 offs) { if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= CHUNK_SIZE || z >= CHUNK_SIZE) { offs = new Vector3(double.NaN, double.NaN, double.NaN); return(null); } BlockInternal bi = Blocks[BlockIndex(x, y, z)]; ConvexShape shape = (ConvexShape)BlockShapeRegistry.BSD[bi.BlockData].GetShape(bi.Damage, out Location loffs, false); offs = loffs.ToBVector(); return(shape); }
public Structure(byte[] dat) { Size.X = Utilities.BytesToInt(Utilities.BytesPartial(dat, 0, 4)); Size.Y = Utilities.BytesToInt(Utilities.BytesPartial(dat, 4, 4)); Size.Z = Utilities.BytesToInt(Utilities.BytesPartial(dat, 8, 4)); Origin.X = Utilities.BytesToInt(Utilities.BytesPartial(dat, 12, 4)); Origin.Y = Utilities.BytesToInt(Utilities.BytesPartial(dat, 12 + 4, 4)); Origin.Z = Utilities.BytesToInt(Utilities.BytesPartial(dat, 12 + 8, 4)); Blocks = new BlockInternal[Size.X * Size.Y * Size.Z]; for (int i = 0; i < Blocks.Length; i++) { Blocks[i] = new BlockInternal(Utilities.BytesToUShort(Utilities.BytesPartial(dat, 12 + 12 + i * 2, 2)), dat[12 + 12 + Blocks.Length * 2 + i], dat[12 + 12 + Blocks.Length * 4 + i], dat[12 + 12 + Blocks.Length * 3 + i]); } }
public override void AltClick(Entity entity, ItemStack item) { if (!(entity is PlayerEntity)) { // TODO: non-player support return; } PlayerEntity player = (PlayerEntity)entity; Location eye = player.ItemSource(); Location forw = player.ItemDir; RayCastResult rcr; bool h = player.TheRegion.SpecialCaseRayTrace(eye, forw, 5, MaterialSolidity.ANY, player.IgnoreThis, out rcr); if (h) { if (rcr.HitObject != null && rcr.HitObject is EntityCollidable && ((EntityCollidable)rcr.HitObject).Entity != null) { // TODO: ??? } else if (player.Mode.GetDetails().CanPlace&& player.TheRegion.GlobalTickTime - player.LastBlockPlace >= 0.2) { Location block = new Location(rcr.HitData.Location) + new Location(rcr.HitData.Normal).Normalize() * 0.9f; block = block.GetBlockLocation(); Material mat = player.TheRegion.GetBlockMaterial(block); if (player.TheRegion.IsAllowedToPlaceIn(player, block, mat)) { CollisionResult hit = player.TheRegion.Collision.CuboidLineTrace(new Location(0.45, 0.45, 0.45), block + new Location(0.5), block + new Location(0.5, 0.5, 0.501), player.TheRegion.Collision.ShouldCollide); if (!hit.Hit) { BlockInternal bi = BlockInternal.FromItemDatum(item.Datum); MusicBlockEntity mbe = new MusicBlockEntity(player.TheRegion, item, block); // TODO: Vary based on material! player.TheRegion.SpawnEntity(mbe); player.Network.SendPacket(new DefaultSoundPacketOut(block, DefaultSound.PLACE, (byte)((Material)bi.BlockMaterial).Sound())); item.Count = item.Count - 1; if (item.Count <= 0) { player.Items.RemoveItem(player.Items.cItem); } else { player.Items.SetSlot(player.Items.cItem - 1, item); } player.LastBlockPlace = player.TheRegion.GlobalTickTime; } } } } }
public override void SetTextureName(string name) { if (name == null || name.Length == 0) { Tex = null; } else { if (name.Contains(":") && name.Before(":").ToLowerFast() == "render_block") { string[] blockDataToRender = name.After(":").SplitFast(','); if (blockDataToRender[0] == "self") { BlockInternal bi = BlockInternal.FromItemDatum(Datum); RenderedBlock = new BlockItemEntity(TheClient.TheRegion, bi.Material, bi.BlockData, bi.BlockPaint, bi.Damage); RenderedBlock.GenVBO(); } else { Material mat = MaterialHelpers.FromNameOrNumber(blockDataToRender[0]); byte data = (byte)(blockDataToRender.Length < 2 ? 0 : Utilities.StringToInt(blockDataToRender[1])); byte paint = (byte)(blockDataToRender.Length < 3 ? 0 : Colors.ForName(blockDataToRender[2])); BlockDamage damage = blockDataToRender.Length < 4 ? BlockDamage.NONE : (BlockDamage)Enum.Parse(typeof(BlockDamage), blockDataToRender[3], true); RenderedBlock = new BlockItemEntity(TheClient.TheRegion, mat, data, paint, damage); RenderedBlock.GenVBO(); } Tex = null; } if (name.Contains(":") && name.Before(":").ToLowerFast() == "render_model") { string model = name.After(":"); if (model.ToLowerFast() == "self") { model = GetModelName(); } RenderedModel = new ModelEntity(model, TheClient.TheRegion) { Visible = true }; RenderedModel.PreHandleSpawn(); Tex = null; } else { Tex = TheClient.Textures.GetTexture(name); } } }
// TODO: EFficiency needed so much! public override void Execute(PlayerCommandEntry entry) { if (entry.InputArguments.Count < 1) { entry.Player.SendMessage(TextChannel.COMMAND_RESPONSE, "/blockship <convex/perfect> [scale]"); return; } BGETraceMode tm = BGETraceMode.CONVEX; if (entry.InputArguments[0].ToLowerFast() == "perfect") { tm = BGETraceMode.PERFECT; } double maxRad = 20; // TODO: Config! Location start = (entry.Player.GetPosition() + new Location(0, 0, -0.1)).GetBlockLocation(); List <KeyValuePair <Location, BlockInternal> > blocks = new List <KeyValuePair <Location, BlockInternal> >(); AABB extent = new AABB() { Min = start, Max = start }; if (!FloodFrom(entry.Player.TheRegion, start, blocks, maxRad, extent) || blocks.Count == 0) { entry.Player.SendMessage(TextChannel.COMMAND_RESPONSE, "Invalid flood-search!"); return; } Location size = extent.Max - extent.Min; int xwidth = (int)size.X + 1; int ywidth = (int)size.Y + 1; int zwidth = (int)size.Z + 1; int xsub = (int)extent.Min.X; int ysub = (int)extent.Min.Y; int zsub = (int)extent.Min.Z; BlockInternal[] blocksin = new BlockInternal[xwidth * ywidth * zwidth]; foreach (KeyValuePair <Location, BlockInternal> block in blocks) { entry.Player.TheRegion.SetBlockMaterial(block.Key, Material.AIR, 0, 0, 1, 0, true, true); blocksin[(int)(block.Key.Z - zsub) * ywidth * xwidth + (int)(block.Key.Y - ysub) * xwidth + (int)(block.Key.X - xsub)] = block.Value; } BlockGroupEntity bge = new BlockGroupEntity(extent.Min, tm, entry.Player.TheRegion, blocksin, xwidth, ywidth, zwidth) { scale = entry.InputArguments.Count < 2 ? Location.One : Location.FromString(entry.InputArguments[1]) }; entry.Player.TheRegion.SpawnEntity(bge); }
void RenderChunkInternalAngle(WorldSystem.Region tregion, Vector3i chunkCoords, Chunk chunk) { MaterialImage bmp = new MaterialImage() { Colors = new Color[BmpSize2, BmpSize2] }; for (int z = 0; z < Chunk.CHUNK_SIZE; z++) { for (int x = 0; x < Chunk.CHUNK_SIZE; x++) { for (int y = 0; y < Chunk.CHUNK_SIZE; y++) { // TODO: async chunk read locker? BlockInternal bi = chunk.GetBlockAt(x, y, z); if (bi.Material.RendersAtAll()) { RenderBlockIntoAngle(bi, x, y, z, bmp); } } } } Bitmap tbmp = new Bitmap(BmpSize2, BmpSize2); BitmapData bdat = tbmp.LockBits(new Rectangle(0, 0, tbmp.Width, tbmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int stride = bdat.Stride; // Surely there's a better way to do this! unsafe { byte *ptr = (byte *)bdat.Scan0; for (int x = 0; x < BmpSize2; x++) { for (int y = 0; y < BmpSize2; y++) { Color tcol = bmp.Colors[x, y]; ptr[(x * 4) + y * stride + 0] = tcol.B; ptr[(x * 4) + y * stride + 1] = tcol.G; ptr[(x * 4) + y * stride + 2] = tcol.R; ptr[(x * 4) + y * stride + 3] = tcol.A; } } } DataStream ds = new DataStream(); tbmp.Save(ds, ImageFormat.Png); tregion.ChunkManager.WriteImageAngle((int)chunkCoords.X, (int)chunkCoords.Y, (int)chunkCoords.Z, ds.ToArray()); }
public BlockItemEntity(Region tregion, BlockInternal orig, Location pos) : base(tregion) { SetMass(20); CGroup = CollisionUtil.Item; Original = orig; Shape = BlockShapeRegistry.BSD[orig.BlockData].GetShape(orig.Damage, out Location offset, true); SetPosition(pos.GetBlockLocation() + offset); DamageableEntityProperty dep = Damageable(); dep.SetMaxHealth(5); dep.SetHealth(5); dep.EffectiveDeathEvent.AddEvent((e) => { RemoveMe(); }, this, 0); }
public MobileChunkShape(Vector3i csize, BlockInternal[] blocks, out Vector3 center) { Matrix3x3 boxMat = new BoxShape(csize.X, csize.Y, csize.Z).VolumeDistribution; ChunkSize = csize; Blocks = blocks; double weightInv = 1f / blocks.Length; center = new Vector3(csize.X / 2f, csize.Y / 2f, csize.Z / 2f); // TODO: More accurately get center of weight based on which blocks are solid or not!? Matrix3x3 volumeDistribution = new Matrix3x3(); RigidTransform transform = new RigidTransform(center); Matrix3x3 contribution; CompoundShape.TransformContribution(ref transform, ref center, ref boxMat, blocks.Length, out contribution); Matrix3x3.Add(ref volumeDistribution, ref contribution, out volumeDistribution); Matrix3x3.Multiply(ref volumeDistribution, weightInv, out volumeDistribution); UpdateEntityShapeVolume(new EntityShapeVolumeDescription() { Volume = csize.X * csize.Y * csize.Z, VolumeDistribution = volumeDistribution }); Center = center; }
/// <summary> /// Explodes a paint bomb at a given location, repainting all in-radius blocks. /// TODO: Move elsewhere? /// </summary> /// <param name="pos">The position to detonate at.</param> /// <param name="bcol">The color byte.</param> /// <param name="rad">The radius.</param> public void PaintBomb(Location pos, byte bcol, double rad = 5f) { foreach (Location loc in GetBlocksInRadius(pos, 5)) { // TODO: Ray-trace the block? BlockInternal bi = GetBlockInternal(loc); SetBlockMaterial(loc, (Material)bi.BlockMaterial, bi.BlockData, bcol, (byte)(bi.BlockLocalData | (byte)BlockFlags.EDITED), bi.Damage); } System.Drawing.Color ccol = Colors.ForByte(bcol); ParticleEffectPacketOut pepo = new ParticleEffectPacketOut(ParticleEffectNetType.PAINT_BOMB, rad + 15, pos, new Location(ccol.R / 255f, ccol.G / 255f, ccol.B / 255f)); foreach (PlayerEntity pe in GetPlayersInRadius(pos, rad + 30)) // TODO: Better particle view dist { pe.Network.SendPacket(pepo); } // TODO: Sound effect? }
/// <summary> /// Attempts to spread a liquid sideways. /// </summary> /// <param name="block">The block.</param> /// <param name="cDat">The shape of the block.</param> /// <param name="cmat">The material of the block.</param> /// <param name="cpaint">The paint of the block.</param> /// <param name="spreadAs">What material to spread as.</param> /// <param name="two">The location to spread into.</param> /// <returns>How much spreading happened.</returns> public byte TryLiquidSpreadSide(Location block, byte cDat, Material cmat, byte cpaint, Material spreadAs, Location two) { BlockInternal tc = GetBlockInternal(two); Material tmat = tc.Material; if (tmat == Material.AIR) { PhysicsSetBlock(two, spreadAs, (byte)5, cpaint, BlockDamage.NONE); return((byte)1); } byte tpaint = tc.BlockPaint; if ((tmat == cmat || tmat == spreadAs) && tpaint == cpaint && tc.BlockData > cDat + 1) { PhysicsSetBlock(two, tmat, (byte)(tc.BlockData - 1), cpaint, BlockDamage.NONE); return((byte)1); } return(0); }
// TODO: Async? public EntityShape CalculateHullShape(out Location offs) { List <Vector3> Vertices = new List <Vector3>(XWidth * YWidth * ZWidth); for (int x = 0; x < XWidth; x++) { for (int y = 0; y < YWidth; y++) { for (int z = 0; z < ZWidth; z++) { BlockInternal c = GetBlockAt(x, y, z); // TODO: Figure out how to handle solidity here //if (((Material)c.BlockMaterial).GetSolidity() == MaterialSolidity.FULLSOLID) //{ BlockInternal def = new BlockInternal(0, 0, 0, 0); BlockInternal zp = z + 1 < ZWidth?GetBlockAt(x, y, z + 1) : def; BlockInternal zm = z > 0 ? GetBlockAt(x, y, z - 1) : def; BlockInternal yp = y + 1 < YWidth?GetBlockAt(x, y + 1, z) : def; BlockInternal ym = y > 0 ? GetBlockAt(x, y - 1, z) : def; BlockInternal xp = x + 1 < XWidth?GetBlockAt(x + 1, y, z) : def; BlockInternal xm = x > 0 ? GetBlockAt(x - 1, y, z) : def; bool zps = ((Material)zp.BlockMaterial).GetSolidity() == MaterialSolidity.FULLSOLID && BlockShapeRegistry.BSD[zp.BlockData].OccupiesBOTTOM(); bool zms = ((Material)zm.BlockMaterial).GetSolidity() == MaterialSolidity.FULLSOLID && BlockShapeRegistry.BSD[zm.BlockData].OccupiesTOP(); bool xps = ((Material)xp.BlockMaterial).GetSolidity() == MaterialSolidity.FULLSOLID && BlockShapeRegistry.BSD[xp.BlockData].OccupiesXM(); bool xms = ((Material)xm.BlockMaterial).GetSolidity() == MaterialSolidity.FULLSOLID && BlockShapeRegistry.BSD[xm.BlockData].OccupiesXP(); bool yps = ((Material)yp.BlockMaterial).GetSolidity() == MaterialSolidity.FULLSOLID && BlockShapeRegistry.BSD[yp.BlockData].OccupiesYM(); bool yms = ((Material)ym.BlockMaterial).GetSolidity() == MaterialSolidity.FULLSOLID && BlockShapeRegistry.BSD[ym.BlockData].OccupiesYP(); Vector3 pos = new Vector3(x, y, z); List <Vector3> vecsi = BlockShapeRegistry.BSD[c.BlockData].GetVertices(pos, xps, xms, yps, yms, zps, zms); Vertices.AddRange(vecsi); //} } } } Vector3 center; ConvexHullShape chs = new ConvexHullShape(Vertices, out center); offs = new Location(center); return(chs); }
public void CreateVBO() { List <KeyValuePair <Vector3i, Material> > tLits = new List <KeyValuePair <Vector3i, Material> >(); if (CSize == CHUNK_SIZE) { List <Entity> cents = new List <Entity>(); for (int x = 0; x < CHUNK_SIZE; x++) { for (int y = 0; y < CHUNK_SIZE; y++) { for (int z = 0; z < CHUNK_SIZE; z++) { BlockInternal bi = GetBlockAt(x, y, z); if (bi.Material.GetLightEmitRange() > 0) { tLits.Add(new KeyValuePair <Vector3i, Material>(new Vector3i(x, y, z), bi.Material)); } MaterialSpawnType mst = bi.Material.GetSpawnType(); if (mst == MaterialSpawnType.FIRE) { cents.Add(new FireEntity(WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(x, y, z - 1), null, OwningRegion)); } } } } OwningRegion.TheClient.Schedule.ScheduleSyncTask(() => { foreach (Entity e in CreatedEnts) { OwningRegion.Despawn(e); } CreatedEnts = cents; foreach (Entity e in cents) { OwningRegion.SpawnEntity(e); } }); } Lits = tLits; OwningRegion.NeedToRender(this); }
public void CalcSkyLight(Chunk above) { if (CSize != CHUNK_SIZE) { for (int x = 0; x < CSize; x++) { for (int y = 0; y < CSize; y++) { for (int z = 0; z < CSize; z++) { BlocksInternal[BlockIndex(x, y, z)].BlockLocalData = 255; } } } return; } for (int x = 0; x < CHUNK_SIZE; x++) { for (int y = 0; y < CHUNK_SIZE; y++) { byte light = (above != null && above.CSize == CHUNK_SIZE) ? above.GetBlockAt(x, y, 0).BlockLocalData : (byte)255; for (int z = CHUNK_SIZE - 1; z >= 0; z--) { if (light > 0) { BlockInternal bi = GetBlockAt(x, y, z); double transc = Colors.AlphaForByte(bi.BlockPaint); if (bi.Material.IsOpaque()) { light = (byte)(light * (1.0 - (BlockShapeRegistry.BSD[bi.BlockData].LightDamage * transc))); } else { light = (byte)(light * (1.0 - (bi.Material.GetLightDamage() * transc))); } } BlocksInternal[BlockIndex(x, y, z)].BlockLocalData = light; } } } }
public override Entity Create(Region tregion, byte[] data) { int xwidth = (int)Utilities.BytesToInt(Utilities.BytesPartial(data, PhysicsEntity.PhysicsNetworkDataLength, 4)); int ywidth = (int)Utilities.BytesToInt(Utilities.BytesPartial(data, PhysicsEntity.PhysicsNetworkDataLength + 4, 4)); int zwidth = (int)Utilities.BytesToInt(Utilities.BytesPartial(data, PhysicsEntity.PhysicsNetworkDataLength + 4 + 4, 4)); BlockInternal[] bi = new BlockInternal[xwidth * ywidth * zwidth]; for (int i = 0; i < bi.Length; i++) { bi[i]._BlockMaterialInternal = Utilities.BytesToUshort(Utilities.BytesPartial(data, PhysicsEntity.PhysicsNetworkDataLength + (4 + 4 + 4) + i * 2, 2)); bi[i].BlockData = data[PhysicsEntity.PhysicsNetworkDataLength + (4 + 4 + 4) + bi.Length * 2 + i]; bi[i].BlockPaint = data[PhysicsEntity.PhysicsNetworkDataLength + (4 + 4 + 4) + bi.Length * 3 + i]; } BGETraceMode tm = (BGETraceMode)data[PhysicsEntity.PhysicsNetworkDataLength + (4 + 4 + 4) + bi.Length * 4]; BlockGroupEntity bge = new BlockGroupEntity(tregion, tm, bi, xwidth, ywidth, zwidth, Location.FromDoubleBytes(data, PhysicsEntity.PhysicsNetworkDataLength + (4 + 4 + 4) + bi.Length * 4 + 1 + 4)); bge.Color = System.Drawing.Color.FromArgb(Utilities.BytesToInt(Utilities.BytesPartial(data, PhysicsEntity.PhysicsNetworkDataLength + (4 + 4 + 4) + bi.Length * 4 + 1, 4))); bge.scale = Location.FromDoubleBytes(data, PhysicsEntity.PhysicsNetworkDataLength + (4 + 4 + 4) + bi.Length * 4 + 1 + 4 + 24); bge.ApplyPhysicsNetworkData(data); return(bge); }
public override KeyValuePair<List<Vector4>, List<Vector4>> GetStretchData(Vector3 blockpos, List<Vector3> vertices, BlockInternal XP, BlockInternal XM, BlockInternal YP, BlockInternal YM, BlockInternal ZP, BlockInternal ZM, bool bxp, bool bxm, bool byp, bool bym, bool bzp, bool bzm) { List<Vector4> sdat = new List<Vector4>(); List<Vector4> swei = new List<Vector4>(); if (!bzp) { double txp = XP.Material.TextureID(MaterialSide.TOP); double txm = XM.Material.TextureID(MaterialSide.TOP); double typ = YP.Material.TextureID(MaterialSide.TOP); double tym = YM.Material.TextureID(MaterialSide.TOP); double zer = 0; double vxp = XP.IsOpaque() ? 1 : 0; double vxm = XM.IsOpaque() ? 1 : 0; double vyp = YP.IsOpaque() ? 1 : 0; double vym = XM.IsOpaque() ? 1 : 0; for (int i = 0; i < 6; i++) { sdat.Add(new Vector4(txp, txm, typ, tym)); } swei.Add(new Vector4(zer, vxm, vyp, zer)); swei.Add(new Vector4(vxp, zer, vyp, zer)); swei.Add(new Vector4(zer, vxm, zer, vym)); swei.Add(new Vector4(vxp, zer, vyp, zer)); swei.Add(new Vector4(vxp, zer, zer, vym)); swei.Add(new Vector4(zer, vxm, zer, vym)); } if (!bzm) { sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); } if (!bxp) { sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); } if (!bxm) { sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); } if (!byp) { sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); } if (!bym) { sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); sdat.Add(new Vector4(5, 5, 5, 5)); swei.Add(new Vector4(1, 1, 1, 1)); } return new KeyValuePair<List<Vector4>, List<Vector4>>(sdat, swei); }
public FullChunkShape(BlockInternal[] blocks) { Blocks = blocks; }