示例#1
0
 public void RemoveCloudsFrom(Chunk chunk)
 {
     for (int i = Clouds.Count - 1; i >= 0; i--)
     {
         if (chunk.Contains(Clouds[i].Position))
         {
             DeleteCloud(Clouds[i]);
         }
     }
 }
示例#2
0
 public void AddCloudsToNewChunk(Chunk chunk)
 {
     if (chunk.WorldPosition.Z >= 3 && chunk.WorldPosition.Z <= 7 && Utilities.UtilRandom.Next(100) > 90)
     {
         double d1 = Utilities.UtilRandom.NextDouble() * Chunk.CHUNK_SIZE;
         double d2 = Utilities.UtilRandom.NextDouble() * Chunk.CHUNK_SIZE;
         double d3 = Utilities.UtilRandom.NextDouble() * Chunk.CHUNK_SIZE;
         Cloud cloud = new Cloud(this, chunk.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(d1, d2, d3));
         int rand = Utilities.UtilRandom.Next(7) > 2 ? Utilities.UtilRandom.Next(50) + 50: Utilities.UtilRandom.Next(100);
         for (int i = 0; i < rand; i++)
         {
             AddToCloud(cloud, 10f);
         }
         SpawnCloud(cloud);
     }
 }
示例#3
0
 void RenderChunkInternal(WorldSystem.Region tregion, Vector3i chunkCoords, Chunk chunk)
 {
     Stopwatch sw = new Stopwatch();
     sw.Start();
     MaterialImage bmp = new MaterialImage() { Colors = new Color[BmpSize, BmpSize] };
     for (int x = 0; x < Chunk.CHUNK_SIZE; x++)
     {
         for (int y = 0; y < Chunk.CHUNK_SIZE; y++)
         {
             // TODO: async chunk read locker?
             BlockInternal topOpaque = BlockInternal.AIR;
             int topZ = 0;
             for (int z = 0; z < Chunk.CHUNK_SIZE; z++)
             {
                 BlockInternal bi = chunk.GetBlockAt(x, y, z);
                 if (bi.IsOpaque())
                 {
                     topOpaque = bi;
                     topZ = z;
                 }
             }
             if (!topOpaque.Material.RendersAtAll())
             {
                 DrawImage(bmp, MaterialImages[0], x * TexWidth, y * TexWidth, Color.Transparent);
             }
             for (int z = topZ; z < Chunk.CHUNK_SIZE; z++)
             {
                 BlockInternal bi = chunk.GetBlockAt(x, y, z);
                 if (bi.Material.RendersAtAll())
                 {
                     MaterialImage zmatbmp = MaterialImages[bi.Material.TextureID(MaterialSide.TOP)];
                     if (zmatbmp == null)
                     {
                         continue;
                     }
                     Color zcolor = Colors.ForByte(bi.BlockPaint);
                     if (zcolor.A == 0)
                     {
                         zcolor = Color.White;
                     }
                     DrawImage(bmp, zmatbmp, x * TexWidth, y * TexWidth, zcolor);
                 }
             }
         }
     }
     sw.Stop();
     Timings_A += sw.ElapsedTicks / (double)Stopwatch.Frequency;
     sw.Reset();
     sw.Start();
     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 < BmpSize; x++)
         {
             for (int y = 0; y < BmpSize; 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;
             }
         }
     }
     tbmp.UnlockBits(bdat);
     sw.Stop();
     Timings_B += sw.ElapsedTicks / (double)Stopwatch.Frequency;
     sw.Reset();
     sw.Start();
     DataStream ds = new DataStream();
     tbmp.Save(ds, ImageFormat.Png);
     tbmp.Dispose();
     sw.Stop();
     Timings_C += sw.ElapsedTicks / (double)Stopwatch.Frequency;
     sw.Reset();
     sw.Start();
     lock (OneAtATimePlease) // NOTE: We can probably make this grab off an array of locks to reduce load a little.
     {
         KeyValuePair<int, int> maxes = tregion.ChunkManager.GetMaxes((int)chunkCoords.X, (int)chunkCoords.Y);
         tregion.ChunkManager.SetMaxes((int)chunkCoords.X, (int)chunkCoords.Y, Math.Min(maxes.Key, (int)chunkCoords.Z), Math.Max(maxes.Value, (int)chunkCoords.Z));
     }
     tregion.ChunkManager.WriteImage((int)chunkCoords.X, (int)chunkCoords.Y, (int)chunkCoords.Z, ds.ToArray());
     sw.Stop();
     Timings_D += sw.ElapsedTicks / (double)Stopwatch.Frequency;
 }
示例#4
0
 public void RenderChunk(WorldSystem.Region tregion, Vector3i chunkCoords, Chunk chunk)
 {
     #if TIMINGS
     Stopwatch sw = new Stopwatch();
     sw.Start();
     #endif
     if (tregion.TheServer.CVars.g_renderblocks.ValueB)
     {
         RenderChunkInternal(tregion, chunkCoords, chunk);
     }
     if (tregion.TheServer.CVars.n_rendersides.ValueB)
     {
         RenderChunkInternalAngle(tregion, chunkCoords, chunk);
     }
     #if TIMINGS
     sw.Stop();
     Timings_General += sw.ElapsedTicks / (double)Stopwatch.Frequency;
     #endif
 }
示例#5
0
 // TODO: Efficiency?
 public bool TryChunk(Vector3i cworldPos, int posMult, Chunk chi = null)
 {
     if (pkick)
     {
         return false;
     }
     if (!ChunksAwareOf.ContainsKey(cworldPos) || ChunksAwareOf[cworldPos].LOD > posMult) // TODO: Efficiency - TryGetValue?
     {
         double dist = (cworldPos.ToLocation() * Chunk.CHUNK_SIZE - LoadRelPos).LengthSquared();
         bool async = chi == null && dist > (Chunk.CHUNK_SIZE * Chunk.CHUNK_SIZE * 2 * 2);
         if (async)
         {
             TheRegion.LoadChunk_Background(cworldPos, (chn) =>
             {
                 if (!pkick && chn != null)
                 {
                     ChunkNetwork.SendPacket(new ChunkInfoPacketOut(chn, posMult));
                 }
             });
         }
         else
         {
             Chunk chk = chi != null ? chi : TheRegion.LoadChunk(cworldPos);
             ChunkNetwork.SendPacket(new ChunkInfoPacketOut(chk, posMult));
         }
         ChunksAwareOf.Remove(cworldPos);
         ChunksAwareOf.Add(cworldPos, new ChunkAwarenessInfo() { ChunkPos = cworldPos, LOD = posMult });
         return true;
     }
     return false;
 }
示例#6
0
 public bool ForgetChunk(Chunk ch, Vector3i cpos)
 {
     if (ChunksAwareOf.Remove(cpos))
     {
         foreach (Entity ent in TheRegion.Entities)
         {
             if (ch.Contains(ent.GetPosition()))
             {
                 Network.SendPacket(new DespawnEntityPacketOut(ent.EID));
             }
         }
         ChunkNetwork.SendPacket(new ChunkForgetPacketOut(cpos));
         return true;
     }
     return false;
 }
示例#7
0
 /// <summary>
 /// Immediately populates a chunk.
 /// </summary>
 /// <param name="chunk">The chunk to populate.</param>
 /// <param name="allowFile">Whether loading from file is allowed.</param>
 /// <param name="fileOnly">Whether we can ONLY load from file.</param>
 /// <returns>Whether it successfully populated the chunk.</returns>
 public bool PopulateChunk(Chunk chunk, bool allowFile, bool fileOnly = false)
 {
     try
     {
         if (allowFile)
         {
             ChunkDetails dat = null;
             lock (chunk.GetLocker())
             {
                 try
                 {
                     dat = ChunkManager.GetChunkDetails((int)chunk.WorldPosition.X, (int)chunk.WorldPosition.Y, (int)chunk.WorldPosition.Z);
                 }
                 catch (Exception ex)
                 {
                     SysConsole.Output("Reading chunk " + chunk.WorldPosition, ex);
                 }
             }
             ChunkDetails ents = null;
             lock (chunk.GetLocker())
             {
                 try
                 {
                     ents = ChunkManager.GetChunkEntities((int)chunk.WorldPosition.X, (int)chunk.WorldPosition.Y, (int)chunk.WorldPosition.Z);
                 }
                 catch (Exception ex)
                 {
                     SysConsole.Output("Reading chunk " + chunk.WorldPosition, ex);
                 }
             }
             if (dat != null)
             {
                 if (ents == null)
                 {
                     ents = new ChunkDetails()
                     {
                         X = dat.X, Y = dat.Y, Z = dat.Z, Version = dat.Version, Flags = dat.Flags, Reachables = null, Blocks = new byte[0]
                     };
                 }
                 chunk.LoadFromSaveData(dat, ents);
                 if (!chunk.Flags.HasFlag(ChunkFlags.ISCUSTOM))
                 {
                     chunk.Flags &= ~ChunkFlags.POPULATING;
                 }
                 if (!chunk.Flags.HasFlag(ChunkFlags.POPULATING))
                 {
                     return(true);
                 }
             }
         }
     }
     catch (Exception ex)
     {
         Utilities.CheckException(ex);
         SysConsole.Output(OutputType.ERROR, "Loading chunk: " + chunk.WorldPosition.ToString() + ": " + ex.ToString());
         return(false);
     }
     if (fileOnly)
     {
         return(false);
     }
     try
     {
         Generator.Populate(TheWorld.Seed, TheWorld.Seed2, TheWorld.Seed3, TheWorld.Seed4, TheWorld.Seed5, chunk);
         chunk.LastEdited = GlobalTickTime;
         chunk.Flags     &= ~(ChunkFlags.POPULATING | ChunkFlags.ISCUSTOM);
         chunk.Flags     |= ChunkFlags.NEEDS_DETECT;
         chunk.IsNew      = true;
     }
     catch (Exception ex)
     {
         Utilities.CheckException(ex);
         SysConsole.Output(OutputType.ERROR, "Loading chunk" + chunk.WorldPosition.ToString() + ": " + ex.ToString());
         return(false);
     }
     return(true);
 }
示例#8
0
 public Chunk LoadChunkNoPopulate(Vector3i cpos)
 {
     Chunk chunk;
     if (LoadedChunks.TryGetValue(cpos, out chunk))
     {
         // Be warned, it may still be loading here!
         return chunk;
     }
     chunk = new Chunk();
     chunk.Flags = ChunkFlags.ISCUSTOM | ChunkFlags.POPULATING;
     chunk.OwningRegion = this;
     chunk.WorldPosition = cpos;
     if (PopulateChunk(chunk, true, true))
     {
         LoadedChunks.Add(cpos, chunk);
         chunk.Flags &= ~ChunkFlags.ISCUSTOM;
         chunk.AddToWorld();
     }
     chunk.LastEdited = GlobalTickTime;
     return chunk;
 }
示例#9
0
        /// <summary>
        /// Ticks the entire region.
        /// </summary>
        public void Tick()
        {
            if (Delta <= 0)
            {
                return;
            }
            PostPhysics();
            opsat += Delta;
            while (opsat > 1.0)
            {
                opsat -= 1.0;
                OncePerSecondActions();
            }
            Stopwatch sw = new Stopwatch();

            sw.Start();
            if (Delta > TheWorld.TargetDelta * 2)
            {
                PhysicsWorld.TimeStepSettings.TimeStepDuration = Delta * 0.5;
            }
            else
            {
                PhysicsWorld.TimeStepSettings.TimeStepDuration = TheWorld.TargetDelta;
            }
            PhysicsWorld.Update(Delta);
            sw.Stop();
            TheServer.PhysicsTimeC += sw.Elapsed.TotalMilliseconds;
            TheServer.PhysicsTimes++;
            sw.Reset();
            // TODO: Async tick
            sw.Start();
            for (int i = 0; i < Tickers.Count; i++)
            {
                if (!Tickers[i].Removed && Tickers[i] is PhysicsEntity)
                {
                    (Tickers[i] as PhysicsEntity).PreTick();
                }
            }
            for (int i = 0; i < Tickers.Count; i++)
            {
                if (!Tickers[i].Removed)
                {
                    Tickers[i].Tick();
                }
            }
            for (int i = 0; i < Tickers.Count; i++)
            {
                if (!Tickers[i].Removed && Tickers[i] is PhysicsEntity)
                {
                    (Tickers[i] as PhysicsEntity).EndTick();
                }
            }
            for (int i = 0; i < DespawnQuick.Count; i++)
            {
                DespawnEntity(DespawnQuick[i]);
            }
            DespawnQuick.Clear();
            for (int i = 0; i < Joints.Count; i++) // TODO: Optimize!
            {
                if (Joints[i].Enabled && Joints[i] is BaseFJoint)
                {
                    ((BaseFJoint)Joints[i]).Solve();
                }
            }
            sw.Stop();
            TheServer.EntityTimeC += sw.Elapsed.TotalMilliseconds;
            TheServer.EntityTimes++;
            while (ChunkFixQueue.TryDequeue(out Vector3i res))
            {
                Chunk chkres = GetChunk(res);
                chkres?.LateSpawn();
            }
        }
示例#10
0
 public abstract void Populate(int seed, int seed2, int seed3, int seed4, int seed5, Chunk chunk);
示例#11
0
 void HandleChunkBGOne(Chunk chunk, Action<Chunk> callback)
 {
     if (chunk.Flags.HasFlag(ChunkFlags.ISCUSTOM))
     {
         chunk.Flags &= ~ChunkFlags.ISCUSTOM;
         chunk.LoadSchedule = TheWorld.Schedule.StartASyncTask(() =>
         {
             chunk.UnloadTimer = 0;
             PopulateChunk(chunk, false, false, true);
             chunk.UnloadTimer = 0;
             chunk.LoadSchedule = null;
             TheWorld.Schedule.ScheduleSyncTask(() =>
             {
                 chunk.UnloadTimer = 0;
                 chunk.AddToWorld();
                 callback.Invoke(chunk);
             });
         });
         return;
     }
     if (chunk.Flags.HasFlag(ChunkFlags.POPULATING))
     {
         LoadedChunks.Remove(chunk.WorldPosition);
         ChunkManager.ClearChunkDetails(chunk.WorldPosition);
         SysConsole.Output(OutputType.ERROR, "non-custom chunk was still loading when grabbed: " + chunk.WorldPosition);
     }
     chunk.LoadSchedule = TheWorld.Schedule.StartASyncTask(() =>
     {
         chunk.UnloadTimer = 0;
         PopulateChunk(chunk, true, false, true);
         chunk.UnloadTimer = 0;
         chunk.LoadSchedule = null;
         TheWorld.Schedule.ScheduleSyncTask(() =>
         {
             chunk.UnloadTimer = 0;
             chunk.AddToWorld();
             callback.Invoke(chunk);
         });
     });
 }
示例#12
0
 public bool PopulateChunk(Chunk chunk, bool allowFile, bool fileOnly = false, bool async = false)
 {
     try
     {
         if (allowFile)
         {
             ChunkDetails dat;
             lock (chunk.GetLocker())
             {
                 dat = ChunkManager.GetChunkDetails((int)chunk.WorldPosition.X, (int)chunk.WorldPosition.Y, (int)chunk.WorldPosition.Z);
             }
             ChunkDetails ents;
             lock (chunk.GetLocker())
             {
                 ents = ChunkManager.GetChunkEntities((int)chunk.WorldPosition.X, (int)chunk.WorldPosition.Y, (int)chunk.WorldPosition.Z);
             }
             if (dat != null)
             {
                 if (ents == null)
                 {
                     ents = new ChunkDetails() { X = dat.X, Y = dat.Y, Z = dat.Z, Version = dat.Version, Flags = dat.Flags, Reachables = null, Blocks = new byte[0] };
                 }
                 chunk.LoadFromSaveData(dat, ents);
                 if (!chunk.Flags.HasFlag(ChunkFlags.ISCUSTOM))
                 {
                     chunk.Flags &= ~ChunkFlags.POPULATING;
                 }
                 return true;
             }
         }
     }
     catch (Exception ex)
     {
         Utilities.CheckException(ex);
         SysConsole.Output(OutputType.ERROR, "Loading chunk: " + chunk.WorldPosition.ToString() + ": " + ex.ToString());
         return false;
     }
     if (fileOnly)
     {
         return false;
     }
     try
     {
         Generator.Populate(TheWorld.Seed, TheWorld.Seed2, TheWorld.Seed3, TheWorld.Seed4, TheWorld.Seed5, chunk);
         chunk.LastEdited = GlobalTickTime;
         chunk.Flags &= ~(ChunkFlags.POPULATING | ChunkFlags.ISCUSTOM);
         chunk.Flags |= ChunkFlags.NEEDS_DETECT;
     }
     catch (Exception ex)
     {
         Utilities.CheckException(ex);
         SysConsole.Output(OutputType.ERROR, "Loading chunk" + chunk.WorldPosition.ToString() + ": " + ex.ToString());
         return false;
     }
     return true;
 }
示例#13
0
 public void LoadChunk_Background(Vector3i cpos, Action<Chunk> callback = null)
 {
     Chunk chunk;
     if (LoadedChunks.TryGetValue(cpos, out chunk))
     {
         if (chunk.LoadSchedule != null)
         {
             TheWorld.Schedule.StartASyncTask(() =>
             {
                 while (chunk.LoadSchedule != null)
                 {
                     Thread.Sleep(1); // TODO: Handle loading a loading chunk more cleanly.
                 }
                 TheWorld.Schedule.ScheduleSyncTask(() =>
                 {
                     HandleChunkBGOne(chunk, callback);
                 });
             });
             return;
         }
         HandleChunkBGOne(chunk, callback);
         return;
     }
     chunk = new Chunk();
     chunk.Flags = ChunkFlags.POPULATING;
     chunk.OwningRegion = this;
     chunk.WorldPosition = cpos;
     LoadedChunks.Add(cpos, chunk);
     chunk.UnloadTimer = 0;
     chunk.LoadSchedule = TheWorld.Schedule.StartASyncTask(() =>
     {
         chunk.UnloadTimer = 0;
         PopulateChunk(chunk, true, false, true);
         chunk.LoadSchedule = null;
         TheWorld.Schedule.ScheduleSyncTask(() =>
         {
             chunk.UnloadTimer = 0;
             chunk.AddToWorld();
             callback.Invoke(chunk);
         });
     });
 }
示例#14
0
 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());
 }
示例#15
0
 public ChunkInfoPacketOut(Chunk chunk, int lod)
 {
     UsageType = NetUsageType.CHUNKS;
     if (chunk.Flags.HasFlag(ChunkFlags.POPULATING) && (lod != 5 || chunk.LOD == null))
     {
         throw new Exception("Trying to transmit chunk while it's still loading! For chunk at " + chunk.WorldPosition);
     }
     ID = ServerToClientPacket.CHUNK_INFO;
     byte[] data_orig;
     if (lod == 1)
     {
         bool isAir = true;
         data_orig = new byte[chunk.BlocksInternal.Length * 4];
         for (int x = 0; x < chunk.BlocksInternal.Length; x++)
         {
             ushort mat = chunk.BlocksInternal[x].BlockMaterial;
             if (mat != 0)
             {
                 isAir = false;
             }
             data_orig[x * 2] = (byte)(mat & 0xFF);
             data_orig[x * 2 + 1] = (byte)((mat >> 8) & 0xFF);
         }
         if (isAir)
         {
             data_orig = null;
         }
         else
         {
             for (int i = 0; i < chunk.BlocksInternal.Length; i++)
             {
                 data_orig[chunk.BlocksInternal.Length * 2 + i] = chunk.BlocksInternal[i].BlockData;
                 data_orig[chunk.BlocksInternal.Length * 3 + i] = chunk.BlocksInternal[i]._BlockPaintInternal;
             }
         }
     }
     else
     {
         data_orig = chunk.LODBytes(lod, true);
     }
     if (data_orig == null)
     {
         Data = new byte[12];
         // TODO: This is a bit hackish
         ID = ServerToClientPacket.CHUNK_FORGET;
         Utilities.IntToBytes((int)chunk.WorldPosition.X).CopyTo(Data, 0);
         Utilities.IntToBytes((int)chunk.WorldPosition.Y).CopyTo(Data, 4);
         Utilities.IntToBytes((int)chunk.WorldPosition.Z).CopyTo(Data, 8);
         return;
     }
     byte[] gdata = FileHandler.Compress(data_orig);
     DataStream ds = new DataStream(gdata.Length + 16);
     DataWriter dw = new DataWriter(ds);
     dw.WriteInt((int)chunk.WorldPosition.X);
     dw.WriteInt((int)chunk.WorldPosition.Y);
     dw.WriteInt((int)chunk.WorldPosition.Z);
     dw.WriteInt(lod);
     byte[] reach = new byte[chunk.Reachability.Length];
     for (int i = 0; i < reach.Length; i++)
     {
         reach[i] = (byte)(chunk.Reachability[i] ? 1 : 0);
     }
     dw.WriteBytes(reach);
     dw.WriteBytes(gdata);
     Data = ds.ToArray();
 }
示例#16
0
 public void SpawnTree(string tree, Location opos, Chunk chunk)
 {
     // TODO: Efficiency!
     ModelEntity me = new ModelEntity("plants/trees/" + tree, this);
     Location pos = opos + new Location(0, 0, 1);
     /*RayCastResult rcr;
     bool h = SpecialCaseRayTrace(pos, -Location.UnitZ, 50, MaterialSolidity.FULLSOLID, IgnoreEntities, out rcr);
     me.SetPosition(h ? new Location(rcr.HitData.Location) : pos);*/
     Vector3 treealign = new Vector3(0, 0, 1);
     Vector3 norm = /*h ? rcr.HitData.Normal : */new Vector3(0, 0, 1);
     Quaternion orient;
     Quaternion.GetQuaternionBetweenNormalizedVectors(ref treealign, ref norm, out orient);
     orient *= Quaternion.CreateFromAxisAngle(Vector3.UnitZ, (double)(Utilities.UtilRandom.NextDouble() * Math.PI * 2));
     me.SetOrientation(orient);
     me.SetPosition(pos);
     me.CanLOD = true;
     me.GenBlockShadow = true;
     Action res = () =>
     {
         SpawnEntity(me);
         me.SetPosition(pos - new Location(norm) - new Location(Quaternion.Transform(me.offset.ToBVector(), orient)));
         me.ForceNetwork();
     };
     if (chunk == null)
     {
         res.Invoke();
     }
     else
     {
         chunk.fixesToRun.Add(TheWorld.Schedule.GetSyncTask(res));
     }
 }
示例#17
0
 public Chunk LoadChunk(Vector3i cpos)
 {
     Chunk chunk;
     if (LoadedChunks.TryGetValue(cpos, out chunk))
     {
         while (chunk.LoadSchedule != null)
         {
             Thread.Sleep(1); // TODO: Handle loading a loading chunk more cleanly.
         }
         if (chunk.Flags.HasFlag(ChunkFlags.ISCUSTOM))
         {
             chunk.Flags &= ~ChunkFlags.ISCUSTOM;
             PopulateChunk(chunk, false);
             chunk.AddToWorld();
         }
         if (chunk.Flags.HasFlag(ChunkFlags.POPULATING))
         {
             LoadedChunks.Remove(cpos);
             ChunkManager.ClearChunkDetails(cpos);
             SysConsole.Output(OutputType.ERROR, "non-custom chunk was still loading when grabbed: " + chunk.WorldPosition);
         }
         else
         {
             chunk.UnloadTimer = 0;
             return chunk;
         }
     }
     chunk = new Chunk();
     chunk.Flags = ChunkFlags.POPULATING;
     chunk.OwningRegion = this;
     chunk.WorldPosition = cpos;
     LoadedChunks.Add(cpos, chunk);
     PopulateChunk(chunk, true);
     chunk.AddToWorld();
     return chunk;
 }