private Color GetColorFromChunkBase(ChunkBase cb) { Color c = Color.magenta; switch (cb.Biome) { case ChunkBiome.ocean: c = new Color(0, 0, 1); break; case ChunkBiome.grassland: c = new Color(0, 1, 0); break; case ChunkBiome.dessert: c = new Color(1, 1, 0); break; case ChunkBiome.forrest: c = new Color(34f / 255f, 139f / 255f, 34f / 255f); break; } if (cb.RiverNode != null) { c = new Color(0, 191f / 255f, 1f); } if (cb.Lake != null) { c = new Color(0, 0.2f, 1f); } return(c); }
/// <summary> /// 解析*.3ds文件。 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="_3dsFilename"></param> /// <returns></returns> public MainChunk Parse(string _3dsFilename) { var base_dir = new FileInfo(_3dsFilename).DirectoryName;// +"/"; var file = new FileStream(_3dsFilename, FileMode.Open, FileAccess.Read); var reader = new BinaryReader(file); reader.BaseStream.Seek(0, SeekOrigin.Begin); var context = new ParsingContext() { base_dir = base_dir, file = file, reader = reader, }; ChunkBase chunk = reader.ReadChunk(); if (chunk.GetType() != typeof(MainChunk)) { throw new Exception("Not a proper 3DS file."); } chunk.Process(context); context.Dispose(); return(chunk as MainChunk); }
public Vec2i FindSpace(Kingdom kingdom, int size) { int attempts = 0; while (attempts < 20) { Vec2i v = null; if (kingdom == null) { v = GenerationRandom.RandomFromList(GameGenerator.TerrainGenerator.LandChunks); } else { v = GenerationRandom.RandomFromList(KingdomChunks[kingdom]); } bool canDo = true; //Check point allows settlement within bounds if (v.x - size < 0 || v.x + size > World.WorldSize - 1 || v.z - size < 0 || v.z + size > World.WorldSize - 1) { canDo = false; } else { for (int x = -size; x <= size; x++) { for (int z = -size; z <= size; z++) { int cx = x + v.x; int cz = z + v.z; ChunkBase cb = TerrainGenerator.ChunkBases[cx, cz]; if (cb.Kingdom != kingdom || cb.HasSettlement || !cb.IsLand) { canDo = false; } else if (cb.RiverNode != null || cb.Lake != null) { canDo = false; } /* * else if (TerrainGenerator.ChunkBases[Mathf.Clamp(x + v.x, 0, World.WorldSize - 1), Mathf.Clamp(z + v.z, 0, World.WorldSize - 1)].Kingdom != kingdom) * canDo = false; * else if (TerrainGenerator.ChunkBases[Mathf.Clamp(x + v.x, 0, World.WorldSize - 1), Mathf.Clamp(z + v.z, 0, World.WorldSize - 1)].Settlement != null) * canDo = false; * else if (!TerrainGenerator.ChunkBases[Mathf.Clamp(x + v.x, 0, World.WorldSize - 1), Mathf.Clamp(z + v.z, 0, World.WorldSize - 1)].IsLand) * canDo = false; */ } } } if (canDo) { return(v); } attempts++; } return(null); }
private async Task Incoming(HttpListenerContext context) { try { _tracingHttpServerSource.TraceEvent(TraceEventType.Verbose, TRACEEVENT_RECEIVED); Interlocked.Increment(ref _requestCount); HttpClientImpl client = new HttpClientImpl(context) { StartTicks = _timer.ElapsedTicks }; var currentActive = Interlocked.Increment(ref _activeCount); var maxActive = Interlocked.Read(ref _maxActive); maxActive = Math.Max(currentActive, maxActive); Interlocked.Exchange(ref _maxActive, maxActive); // it is possible to overwrite a higher value on a different thread but it's good enough byte[] buffer = new byte[1024]; int read = 0; ChunkBase root = null; if (Path.GetExtension(context.Request.RawUrl) == "") { client.Context.Response.ContentType = "application/json"; root = new RESTChunk(this); } else if (context.Request.RawUrl.EndsWith(".page")) { client.Context.Response.ContentType = "text/html"; root = new PageChunk(this, null); } else { client.Context.Response.ContentType = "application/octet"; root = new FileChunk(this); } await root.Send(client, null); client.StopTicks = _timer.ElapsedTicks; Interlocked.Add(ref _tickCount, client.TimetoLastByte); } catch (Exception ex) { _tracingHttpServerSource.TraceData(TraceEventType.Error, TRACEEVENT_ERROR, ex); } finally { Interlocked.Increment(ref _requestCompleteCount); Interlocked.Decrement(ref _activeCount); } }
/// <summary> /// Generates a simple texture representing the terrain defined by the /// ChunkBase array. /// This Texture is then stored in GameManager.Game.toDrawTexts[3] /// </summary> /// <param name="cbs">The chunk bases the generated map will be based on</param> private void GenerateTerrainMap(ChunkBase[,] cbs) { Texture2D terMap = new Texture2D(World.WorldSize, World.WorldSize); for (int x = 0; x < World.WorldSize; x++) { for (int z = 0; z < World.WorldSize; z++) { ChunkBase cb = cbs[x, z]; Color c = Color.black; switch (cb.Biome) { case ChunkBiome.ocean: c = new Color(0, 0, 1); break; case ChunkBiome.grassland: c = new Color(0, 1, 0); break; case ChunkBiome.dessert: c = new Color(1, 1, 0); break; case ChunkBiome.forrest: c = new Color(34f / 255f, 139f / 255f, 34f / 255f); break; } if (cb.RiverNode != null) { c = new Color(0, 191f / 255f, 1f); } if (cb.Lake != null) { c = new Color(0, 0.2f, 1f); } if (cb.ChunkStructure != null) { c = Color.magenta; //Debug.Log("chunk struct at " + x + "_" + z); } terMap.SetPixel(x, z, c); } } terMap.Apply(); GameManager.Game.toDrawTexts[3] = terMap; }
public ChunkBase NextChunk(Vault vault) { var header = new ChunkBlockHeader(); header.Read(vault, Reader); ChunkBase chunk = null; switch (header.ID) { case 0x53747245: chunk = new BinStringsChunk(); break; case 0x5374724E: chunk = new VltStartChunk(); break; case 0x456E6443: chunk = new EndChunk(); break; case 0x56657273: chunk = new VltVersionChunk(); break; case 0x4465704E: chunk = new VltDependencyChunk(); break; case 0x4578704E: chunk = new VltExportChunk(); break; case 0x5074724E: chunk = new VltPointersChunk(); break; default: chunk = new GenericChunk(header.ID); break; } chunk.Offset = header.Offset; chunk.Size = header.Size + 8; return(chunk); }
/// <summary> /// Writes a chunk to the data stream. /// </summary> /// <param name="chunk">The chunk to write.</param> public void WriteChunk(ChunkBase chunk) { var beginPos = Writer.BaseStream.Position; Writer.Write(chunk.Id); var sizePos = Writer.BaseStream.Position; Writer.Write(0); chunk.Write(Vault, Writer); var endPos = Writer.BaseStream.Position; Writer.BaseStream.Position = sizePos; Writer.Write((uint)(endPos - beginPos)); Writer.BaseStream.Position = endPos; }
public void SpawnChunkEntities(ChunkBase cb) { if (cb.ChunkStructure != null) { ChunkStructure cStruct = cb.ChunkStructure; Vec2i localPos = cb.Position - cStruct.Position; List <Entity> toSpawn = cStruct.StructureEntities[localPos.x, localPos.z]; if (toSpawn == null) { return; } foreach (Entity e in toSpawn) { e.CombatManager.Reset(); Manager.LoadEntity(e); } } }
public Dictionary <Vec2i, ChunkData> GenerateAllSettlementChunks(SettlementBuilder setBuild, Settlement set) { Vec2i baseChunk = new Vec2i(setBuild.BaseCoord.x / World.ChunkSize, setBuild.BaseCoord.z / World.ChunkSize); Dictionary <Vec2i, ChunkData> setChunks = new Dictionary <Vec2i, ChunkData>(); int setSizeChunks = setBuild.TileSize / World.ChunkSize; for (int x = 0; x < setSizeChunks; x++) { for (int z = 0; z < setSizeChunks; z++) { ChunkBase cb = GameGenerator.TerrainGenerator.ChunkBases[baseChunk.x + x, baseChunk.z + z]; ChunkData cd = null; if (cb.RiverNode != null || cb.Lake != null) { cd = GameGenerator.ChunkGenerator.GenerateChunk(baseChunk.x + x, baseChunk.z + z); } else { int[,] cTiles = new int[World.ChunkSize, World.ChunkSize]; Dictionary <int, WorldObjectData> cObj = new Dictionary <int, WorldObjectData>(); for (int x_ = 0; x_ < World.ChunkSize; x_++) { for (int z_ = 0; z_ < World.ChunkSize; z_++) { Tile st = setBuild.Tiles[x * World.ChunkSize + x_, z *World.ChunkSize + z_]; cTiles[x_, z_] = st == null ? Tile.GRASS.ID : st.ID; cObj[WorldObject.ObjectPositionHash(x_, z_)] = setBuild.SettlementObjects[x * World.ChunkSize + x_, z *World.ChunkSize + z_]; if (setBuild.SettlementObjects[x * World.ChunkSize + x_, z *World.ChunkSize + z_] != null) { setBuild.SettlementObjects[x * World.ChunkSize + x_, z *World.ChunkSize + z_].SetPosition(new Vec2i(baseChunk.x + x + x_, baseChunk.z + z + z_)); } } } cd = new ChunkData(baseChunk.x + x, baseChunk.z + z, cTiles, true, cObj); } cd.SetSettlement(set); setChunks.Add(new Vec2i(cd.X, cd.Z), cd); } } set.AfterApplyToWorld(); return(setChunks); }
/// <summary> /// Generates the chunk based on its biome, as well as things added to it such as forrests and wooded areas /// </summary> /// <param name="x"></param> /// <param name="z"></param> /// <returns></returns> public ChunkData GenerateChunk(int x, int z) { ChunkBase cb = ChunkBases[x, z]; ChunkData cd = null; if (cb.Lake != null) { cd = GenerateLakeChunk(x, z, cb); } else if (cb.RiverNode != null) { cd = GenerateRiverChunk(x, z, cb); } else { cd = GenerateSimpleChunk(x, z, cb); } return(cd); }
private ChunkBase BuildSimpleTree(ChunkBase chunk) { var newChunk = ((ICloneable)chunk).Clone() as ChunkBase; newChunk.Parent = null; newChunk.Children = new List <ChunkBase>(); foreach (var item in chunk.Children) { if (item.GetType() != typeof(UndefinedChunk)) { var newItem = BuildSimpleTree(item); newItem.Parent = newChunk; newChunk.Children.Add(newItem); } } return(newChunk); }
private TreeNode BuildTreeNode(ChunkBase chunk) { TreeNode node = new TreeNode(chunk.ToString()); node.Tag = chunk; node.ToolTipText = chunk.ToString(); if (chunk.Length != chunk.BytesRead) { node.BackColor = Color.Red; } foreach (var item in chunk.Children) { var itemNode = BuildTreeNode(item); node.Nodes.Add(itemNode); } return(node); }
public void LoadChunk(ChunkBase cb, Vec2i v) { //Debug.Log("Loading chunk with entities"); LoadedChunks.Add(v); //Debug.Log("Loading entities from chunk " + v); if (FixedEntities.ContainsKey(v)) { List <int> toLoad = FixedEntities[v]; Debug.Log("Loading " + toLoad.Count + " entities from " + v, Debug.ENTITY); //Debug.Log(toLoad.Count); foreach (int e in toLoad) { LoadEntity(GetEntityFromID(e)); } FixedEntities[v].Clear(); } if (cb != null) { EntitySpawner.SpawnChunkEntities(cb); } }
///Contains function to check if positions are valid #region misc /// <summary> /// Takes a position and size, checks against terrain values to see if /// the position is free to place the desired structure on /// </summary> /// <param name="position"></param> /// <returns></returns> private bool IsPositionValid(Vec2i position, int clear = 5) { for (int x = -clear; x <= clear; x++) { for (int z = -clear; z <= clear; z++) { int cx = position.x + x; int cz = position.z + z; //Debug.Log(cx + "_" + cz); if (cx < 0 || cz < 0 || cx >= World.WorldSize - 1 || cz >= World.WorldSize - 1) { return(false); } ChunkBase cb = GameGenerator.TerrainGenerator.ChunkBases[cx, cz]; if (cb.HasSettlement || cb.RiverNode != null || cb.Lake != null || cb.ChunkStructure != null) { //Debug.Log(cb.HasSettlement + "_" + cb.RiverNode + "_" + cb.Lake + "_" + cb.ChunkStructure); return(false); } } } return(true); }
/// <summary> /// Generates a chunk that has no special land features /// </summary> /// <param name="x"></param> /// <param name="z"></param> /// <param name="cb"></param> /// <returns></returns> private ChunkData GenerateSimpleChunk(int x, int z, ChunkBase cb) { if (!cb.IsLand) { return(new ChunkData(x, z, (int[, ])OCEAN.Clone(), cb.IsLand)); } if (cb.Biome == ChunkBiome.dessert) { return(new ChunkData(x, z, (int[, ])EMPTY_DESERT.Clone(), cb.IsLand)); } int[,] tiles = (int[, ])EMPTY_PLAINS.Clone(); GenerationRandom genRan = new GenerationRandom(Seed + x << 16 + z); //if(genRan.Random() > 0.1f) // return new ChunkData(x, z, tiles, cb.IsLand); Dictionary <int, WorldObjectData> obs = new Dictionary <int, WorldObjectData>(256); for (int i = 0; i < World.ChunkSize; i++) { for (int j = 0; j < World.ChunkSize; j++) { if (genRan.Random() < 0.01f) { obs.Add(WorldObject.ObjectPositionHash(i, j), new Tree(new Vec2i(x * World.ChunkSize + i, z * World.ChunkSize + j))); } else if (genRan.Random() < 0.3f) { //obs.Add(WorldObject.ObjectPositionHash(i, j), new Tree(new Vec2i(x * World.ChunkSize + i, z * World.ChunkSize + j))); } } } ChunkData cd = new ChunkData(x, z, tiles, cb.IsLand, obs); return(cd); }
private void Start() { ///Chunk test ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //original chunk ProjectileObjectSyncChunk message = new ProjectileObjectSyncChunk(); message.chunkType = (int)ChunkType.ProjectileObjectSync; message.connID = 1; message.objID = 12; message.position = new Vector3(1, 1, 1); message.veclocity = new Vector3(2, 2, 2); message.force = new Vector3(3, 3, 3); message.isKinematic = false; message.magicalExtraOne = 233; //protobuf message Chunks.ProjectileObjectSyncChunk projectile = new Chunks.ProjectileObjectSyncChunk(); projectile.Position = GetVector3Message(message.position); projectile.Velocity = GetVector3Message(message.veclocity); projectile.Force = GetVector3Message(message.force); projectile.IsKinematic = message.isKinematic; projectile.MagicalExtraOne = message.magicalExtraOne; //wrapper. (solving the inheritance issue). need a better solution for this. ChunkBase chunkBase = new ChunkBase(); chunkBase.Chunktype = message.chunkType; chunkBase.ConnID = message.connID; chunkBase.ObjID = message.objID; //wrap the content chunkBase.Content = projectile.ToByteString(); //Serialize byte[] bytes = chunkBase.ToByteArray(); //Deserialize Chunks.ChunkBase parsedChunk = Chunks.ChunkBase.Parser.ParseFrom(bytes); if (parsedChunk.Chunktype == (int)ChunkType.ProjectileObjectSync) { //deserialize to child Chunks.ProjectileObjectSyncChunk parsedProjectile = Chunks.ProjectileObjectSyncChunk.Parser.ParseFrom(parsedChunk.Content); Debug.Log(GetVector3(parsedProjectile.Position)); Debug.Log(GetVector3(parsedProjectile.Velocity)); Debug.Log(GetVector3(parsedProjectile.Force)); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///List Test ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //ListTest list = new ListTest(); //for(int i=0; i<10; i++) //{ // list.List.Add(GetVector3Message(new Vector3(i,i,i))); //} //byte[] bytes = list.ToByteArray(); //ListTest newList = ListTest.Parser.ParseFrom(bytes); //foreach(Vector3Message v in newList.List) //{ // Debug.Log(GetVector3(v)); //} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }
public bool IsAreaFree(int x, int z, int width, int height, Tile ignoreTile = null) { if (x < 0 || z < 0) { return(false); } if (GameGenerator != null) { Vec2i baseChunk = BaseChunk + new Vec2i(Mathf.FloorToInt((float)x / World.ChunkSize), Mathf.FloorToInt((float)z / World.ChunkSize)); Vec2i cBase = World.GetChunkPosition(this.BaseCoord + new Vec2i(x, z)) - new Vec2i(2, 2); int chunkWidth = Mathf.FloorToInt((float)width / World.ChunkSize) + 1; int chunkHeight = Mathf.FloorToInt((float)height / World.ChunkSize) + 1; for (int cx = 0; cx < chunkWidth; cx++) { for (int cz = 0; cz < chunkHeight; cz++) { int cbx = baseChunk.x + cx; int cbz = baseChunk.z + cz; if (cbx < 0 || cbx > World.WorldSize - 1 || cbz < 0 || cbz > World.WorldSize - 1) { return(false); } ChunkBase cb = GameGenerator.TerrainGenerator.ChunkBases[cbx, cbz]; if (cb.RiverNode != null) { cb.RiverNode.AddBridge(new RiverBridge()); return(false); } if (cb.RiverNode != null || cb.Lake != null || !cb.IsLand) { return(false); } } } } for (int x_ = x; x_ < x + width; x_++) { for (int z_ = z; z_ < z + height; z_++) { if (z_ >= TileSize - 1 || x_ >= TileSize - 1) { return(false); } if (ignoreTile != null) { if (Tiles[x_, z_] != null && Tiles[x_, z_] != ignoreTile) { return(false); } } else if (Tiles[x_, z_] != null) { return(false); } } } return(true); }
private void CreateWorld2() { World world = new World(); SettlementBase b = new SettlementBase(new Vec2i(8, 8), 8, SettlementType.CAPITAL); SettlementBuilder build = new SettlementBuilder(null, b); build.GenerateSettlement(); /*foreach(SettlementPathNode p in build.nodes) * { * TestNodes.Add(p); * }*/ Tile[,] tiles = build.Tiles; WorldObjectData[,] objs = build.SettlementObjects; int tileSize = build.TileSize; int cSize = tileSize / World.ChunkSize; ChunkData[,] cData = new ChunkData[cSize, cSize]; ChunkBase[,] cBase = new ChunkBase[cSize, cSize]; for (int x = 0; x < cSize; x++) { for (int z = 0; z < cSize; z++) { cBase[x, z] = new ChunkBase(new Vec2i(x, z), true); int[,] cTiles = new int[World.ChunkSize, World.ChunkSize]; WorldObjectData[,] cObj = new WorldObjectData[World.ChunkSize, World.ChunkSize]; Dictionary <int, WorldObjectData> wObjData = new Dictionary <int, WorldObjectData>(); for (int x_ = 0; x_ < World.ChunkSize; x_++) { for (int z_ = 0; z_ < World.ChunkSize; z_++) { if (tiles[x * World.ChunkSize + x_, z *World.ChunkSize + z_] != null) { cTiles[x_, z_] = tiles[x * World.ChunkSize + x_, z *World.ChunkSize + z_].ID; } else { cTiles[x_, z_] = Tile.GRASS.ID; } if (objs[x * World.ChunkSize + x_, z *World.ChunkSize + z_] != null) { wObjData.Add(WorldObject.ObjectPositionHash(x_, z_), objs[x * World.ChunkSize + x_, z * World.ChunkSize + z_]); } // cObj[x_, z_] = objs[x * World.ChunkSize + x_, z * World.ChunkSize + z_]; } } cData[x, z] = new ChunkData(x, z, cTiles, true, wObjData); } } ChunkRegion r = new ChunkRegion(0, 0, cData); WorldManager.LoadedRegions[0, 0] = r; Kingdom k = new Kingdom("test", new Vec2i(0, 0)); k.SetKingdomID(world.AddKingdom(k)); Settlement set = new Settlement(k, "test_set", build); set.SetSettlementID(world.AddSettlement(set)); WorldManager.SetWorld(world); KingdomNPCGenerator npcGen = new KingdomNPCGenerator(new GameGenerator(0), k, EntityManager); Debug.Log("BASE:" + set.BaseCoord); Debug.Log(cSize); npcGen.GenerateSettlementNPC(set); world.SetChunkBases(cBase); for (int x = 0; x < cSize - 1; x++) { for (int z = 0; z < cSize - 1; z++) { //LoadChunk(cData[x, z]); WorldManager.CRManager.LoadChunk(new Vec2i(x, z)); EntityManager.LoadChunk(null, new Vec2i(x, z)); } } /* * DungeonGenerator dugeonGenerator = new DungeonGenerator(); * dungeon = dugeonGenerator.GenerateDungeon(); * ChunkRegion r = new ChunkRegion(0, 0, dungeon.SubworldChunks); * world.LoadedRegions.Add(new Vec2i(0, 0), r); * WorldManager.SetWorld(world);*/ //world.Set }
public bool IsAreaFree(int x, int z, int width, int height, Tile ignoreTile = null) { if (x < 0 || z < 0) { return(false); } if (GameGenerator != null) { Vec2i baseChunk = BaseChunk + new Vec2i(Mathf.FloorToInt((float)x / World.ChunkSize), Mathf.FloorToInt((float)z / World.ChunkSize)); Vec2i cBase = World.GetChunkPosition(this.BaseTile + new Vec2i(x, z)) - new Vec2i(2, 2); int chunkWidth = Mathf.FloorToInt((float)width / World.ChunkSize) + 1; int chunkHeight = Mathf.FloorToInt((float)height / World.ChunkSize) + 1; for (int cx = 0; cx < chunkWidth; cx++) { for (int cz = 0; cz < chunkHeight; cz++) { int cbx = baseChunk.x + cx; int cbz = baseChunk.z + cz; if (cbx < 0 || cbx > World.WorldSize - 1 || cbz < 0 || cbz > World.WorldSize - 1) { return(false); } ChunkBase cb = GameGenerator.TerrainGenerator.ChunkBases[cbx, cbz]; if (cb.RiverNode != null) { cb.RiverNode.AddBridge(new RiverBridge()); return(false); } if (cb.RiverNode != null || cb.Lake != null || !cb.IsLand) { return(false); } } } } Recti rect = new Recti(x, z, width, height); foreach (Recti r in BuildingPlots) { if (rect.Intersects(r)) { return(false); } } for (int x_ = x; x_ < x + width; x_++) { for (int z_ = z; z_ < z + height; z_++) { if (z_ >= TileSize - 1 || x_ >= TileSize - 1) { return(false); } int cx = WorldToChunk(x_); int cz = WorldToChunk(z_); int baseIgnore = Tile.NULL.ID; if (ChunkBases != null && ChunkBases[cx, cz] != null) { baseIgnore = Tile.GetFromBiome(ChunkBases[cx, cz].Biome).ID; } if (ignoreTile != null) { if (GetTile(x_, z_) != 0 && GetTile(x_, z_) != ignoreTile.ID && GetTile(x_, z_) != baseIgnore) { return(false); } } else if (GetTile(x_, z_) != 0 && GetTile(x_, z_) != baseIgnore) { return(false); } } } return(true); }
public void GenerateChunkBases() { ChunkBases = new ChunkBase[World.WorldSize, World.WorldSize]; LandChunks = new List <Vec2i>(); Vec2i mid = new Vec2i(World.WorldSize / 2, World.WorldSize / 2); float r_sqr = (World.WorldSize / 3) * (World.WorldSize / 3); WorldRad = (World.WorldSize / 2.1f) * (World.WorldSize / 2.1f); Texture2D t = new Texture2D(World.WorldSize, World.WorldSize); Texture2D hum = new Texture2D(World.WorldSize, World.WorldSize); Texture2D temp = new Texture2D(World.WorldSize, World.WorldSize); float[,] humdity = new float[World.WorldSize, World.WorldSize]; Vec2i offset = GenRan.RandomVec2i(World.WorldSize / 8, World.WorldSize / 4); Vec2i humMid = mid + offset; float humRadSqr = GenRan.Random(World.WorldSize / 4, World.WorldSize / 2); humRadSqr *= humRadSqr; Vec2i tempMid = mid - offset; float tempRadSqr = GenRan.Random(World.WorldSize / 4, World.WorldSize / 2); tempRadSqr *= tempRadSqr; float[,] temperature = new float[World.WorldSize, World.WorldSize]; for (int x = 0; x < World.WorldSize; x++) { for (int z = 0; z < World.WorldSize; z++) { float c = WorldHeightChunk(x, z); humdity[x, z] = 0.4f + 0.6f * Mathf.PerlinNoise(4000 + x * 0.02f, 4000 + z * 0.02f); humdity[x, z] /= (((x - humMid.x) * (x - humMid.x) + (z - humMid.z) * (z - humMid.z)) / humRadSqr); humdity[x, z] = Mathf.Clamp(humdity[x, z], 0, 1); //temperature[x, z] = Mathf.PerlinNoise(700 + x * 0.02f, 700 + z * 0.02f); temperature[x, z] = 0.4f + 0.6f * Mathf.PerlinNoise(700 + x * 0.02f, 700 + z * 0.02f); temperature[x, z] /= (((x - tempMid.x) * (x - tempMid.x) + (z - tempMid.z) * (z - tempMid.z)) / tempRadSqr); temperature[x, z] = Mathf.Clamp(temperature[x, z], 0, 1); hum.SetPixel(x, z, new Color(humdity[x, z], humdity[x, z], humdity[x, z])); temp.SetPixel(x, z, new Color(temperature[x, z], temperature[x, z], temperature[x, z])); //c /= (((x - mid.x) * (x - mid.x) + (z - mid.z) * (z - mid.z)) / r_sqr); t.SetPixel(x, z, new Color(c / World.ChunkHeight, c / World.ChunkHeight, c / World.ChunkHeight)); Vec2i v = new Vec2i(x, z); //if ((x - mid.x) * (x - mid.x) + (z - mid.z) * (z - mid.z) < r_sqr) if (c > 40 && !(x == 0 || z == 0 || x == World.WorldSize - 1 || z == World.WorldSize - 1)) { //If point within this radius of middle ChunkBases[x, z] = new ChunkBase(v, Mathf.FloorToInt(c), true); LandChunks.Add(v); if (c > 100) { ChunkBases[x, z].SetBiome(ChunkBiome.mountain); } else if (temperature[x, z] > 0.7f && humdity[x, z] < 0.4f) { ChunkBases[x, z].SetBiome(ChunkBiome.dessert); } else if (humdity[x, z] > 0.4f && temperature[x, z] > 0.5f) { ChunkBases[x, z].SetBiome(ChunkBiome.forrest); } else { ChunkBases[x, z].SetBiome(ChunkBiome.grassland); } /* * if(temperature[x, z] > 0.7f && humdity[x,z] < 0.4f) * { * ChunkBases[x, z].SetBiome(ChunkBiome.dessert); * }else if(temperature[x, z] < 0.7f && humdity[x, z] > 0.6f) * if (temperature[x, z] < 0.25f) * { * ChunkBases[x, z].SetBiome(ChunkBiome.forrest); * } * else * { * ChunkBases[x, z].SetBiome(ChunkBiome.grassland); * }*/ } else { ChunkBases[x, z] = new ChunkBase(v, 1, false); } } } t.Apply(); hum.Apply(); temp.Apply(); /* * GameManager.Game.toDrawTexts[0] = t; * GameManager.Game.toDrawTexts[1] = hum; * GameManager.Game.toDrawTexts[2] = temp;*/ }
public void GenerateMesh() { // Default 4096, else use the lase size + 1024 int newSize = vertexBuffer.used == 0 ? 4096 : vertexBuffer.used + 1024; vertexBuffer.Reset(newSize); // Negative X side cXN = chunkPosX > 0 ? m.chunks[chunkPosX - 1, chunkPosY, chunkPosZ] : null; // Positive X side cXP = chunkPosX < Constants.ChunkXAmount - 1 ? m.chunks[chunkPosX + 1, chunkPosY, chunkPosZ] : null; // Negative Y side cYN = chunkPosY > 0 ? m.chunks[chunkPosX, chunkPosY - 1, chunkPosZ] : null; // Positive Y side cYP = chunkPosY < Constants.ChunkYAmount - 1 ? m.chunks[chunkPosX, chunkPosY + 1, chunkPosZ] : null; // Negative Z neighbour cZN = chunkPosZ > 0 ? m.chunks[chunkPosX, chunkPosY, chunkPosZ - 1] : null; // Positive Z side cZP = chunkPosZ < Constants.ChunkZAmount - 1 ? m.chunks[chunkPosX, chunkPosY, chunkPosZ + 1] : null; // Precalculate the map-relative Y position of the chunk in the map int chunkY = chunkPosY * CHUNK_SIZE; // Allocate variables on the stack int access, heightMapAccess, iCS, kCS2, i1, k1, j, topJ; bool minXEdge, maxXEdge, minZEdge, maxZEdge; k1 = 1; for (int k = 0; k < CHUNK_SIZE; k++, k1++) { // Calculate this once, rather than multiple times in the inner loop kCS2 = k * CHUNK_SIZE_SQUARED; i1 = 1; heightMapAccess = k * CHUNK_SIZE; // Is the current run on the Z- or Z+ edge of the chunk minZEdge = k == 0; maxZEdge = k == CHUNK_SIZE_MINUS_ONE; for (int i = 0; i < CHUNK_SIZE; i++; i1++) { // Determine where to start the innermost loop j = MinY[heightMapAccess]; topJ = MaxY[heightMapAccess]; heightMapAccess++; // Calculate this once, rather than multiple times in the inner loop iCS = i * CHUNK_SIZE; // Calculate access here and increment it each time in the innermost loop access = kCS2 + iCS + j; // Is the current run on the X- or X+ edge of the chunk minX = i == 0; maxX = i == CHUNK_SIZE_MINUS_ONE; // X and Z runs search upwards to create runs, so start at the bottom. for (; j < topJ; j++, access++) { ref Block b = ref data[access]; if (b.kind != EMPTY) { CreateRun(ref b, i, j, k << 12, i1, k1 << 12, j + chunkY, access, minX, maxX, j == 0, j == CHUNK_SIZE_MINUS_ONE, minZ, maxZ, iCS, kCS2); } } // Extend the array if it is nearly full if (vertexBuffer.used > vertexBuffer.data.Length - 2048) { vertexBuffer.Extend(2048); } } }
public void GenerateChunkBases() { ChunkBases = new ChunkBase[World.WorldSize, World.WorldSize]; LandChunks = new List <Vec2i>(); GenerationRandom genRan = new GenerationRandom(0); Vec2i mid = new Vec2i(World.WorldSize / 2, World.WorldSize / 2); float r_sqr = (World.WorldSize / 3) * (World.WorldSize / 3); Texture2D t = new Texture2D(World.WorldSize, World.WorldSize); Texture2D hum = new Texture2D(World.WorldSize, World.WorldSize); Texture2D temp = new Texture2D(World.WorldSize, World.WorldSize); float[,] humdity = new float[World.WorldSize, World.WorldSize]; Vec2i offset = genRan.RandomVec2i(World.WorldSize / 8, World.WorldSize / 4); Vec2i humMid = mid + offset; float humRadSqr = genRan.Random(World.WorldSize / 4, World.WorldSize / 2); humRadSqr *= humRadSqr; Vec2i tempMid = mid - offset; float tempRadSqr = genRan.Random(World.WorldSize / 4, World.WorldSize / 2); tempRadSqr *= tempRadSqr; float[,] temperature = new float[World.WorldSize, World.WorldSize]; for (int x = 0; x < World.WorldSize; x++) { for (int z = 0; z < World.WorldSize; z++) { float c = 1 - Mathf.Pow(Mathf.PerlinNoise(x * 0.01f, z * 0.01f), 2); humdity[x, z] = 0.4f + 0.6f * Mathf.PerlinNoise(4000 + x * 0.02f, 4000 + z * 0.02f); humdity[x, z] /= (((x - humMid.x) * (x - humMid.x) + (z - humMid.z) * (z - humMid.z)) / humRadSqr); humdity[x, z] = Mathf.Clamp(humdity[x, z], 0, 1); //temperature[x, z] = Mathf.PerlinNoise(700 + x * 0.02f, 700 + z * 0.02f); temperature[x, z] = 0.4f + 0.6f * Mathf.PerlinNoise(700 + x * 0.02f, 700 + z * 0.02f); temperature[x, z] /= (((x - tempMid.x) * (x - tempMid.x) + (z - tempMid.z) * (z - tempMid.z)) / tempRadSqr); temperature[x, z] = Mathf.Clamp(temperature[x, z], 0, 1); hum.SetPixel(x, z, new Color(humdity[x, z], humdity[x, z], humdity[x, z])); temp.SetPixel(x, z, new Color(temperature[x, z], temperature[x, z], temperature[x, z])); c /= (((x - mid.x) * (x - mid.x) + (z - mid.z) * (z - mid.z)) / r_sqr); t.SetPixel(x, z, new Color(c, c, c)); Vec2i v = new Vec2i(x, z); //if ((x - mid.x) * (x - mid.x) + (z - mid.z) * (z - mid.z) < r_sqr) if (c > 0.5) { //If point within this radius of middle ChunkBases[x, z] = new ChunkBase(v, true); LandChunks.Add(v); //Deserts if its hot and dry if (temperature[x, z] > 0.7f && humdity[x, z] < 0.4f) { ChunkBases[x, z].SetBiome(ChunkBiome.dessert); } else if (humdity[x, z] > 0.4f && temperature[x, z] > 0.5f) { ChunkBases[x, z].SetBiome(ChunkBiome.forrest); } else { ChunkBases[x, z].SetBiome(ChunkBiome.grassland); } /* * if(temperature[x, z] > 0.7f && humdity[x,z] < 0.4f) * { * ChunkBases[x, z].SetBiome(ChunkBiome.dessert); * }else if(temperature[x, z] < 0.7f && humdity[x, z] > 0.6f) * if (temperature[x, z] < 0.25f) * { * ChunkBases[x, z].SetBiome(ChunkBiome.forrest); * } * else * { * ChunkBases[x, z].SetBiome(ChunkBiome.grassland); * }*/ } else { ChunkBases[x, z] = new ChunkBase(v, false); } } } t.Apply(); hum.Apply(); temp.Apply(); GameManager.Game.toDrawTexts[0] = t; GameManager.Game.toDrawTexts[1] = hum; GameManager.Game.toDrawTexts[2] = temp; }
private ChunkData GenerateChunk(int[,] landClone, ChunkBase cb) { int x = cb.Position.x; int z = cb.Position.z; //If there is a river passing through here if (cb.RiverNode != null) { float sqrt2 = Mathf.Sqrt(2); int[,] tiles = new int[World.ChunkSize, World.ChunkSize]; WorldObjectData[,] data = new WorldObjectData[World.ChunkSize, World.ChunkSize]; RiverNode rn = cb.RiverNode; Vec2i exitDelta = rn.RiverExitDelta; Vec2i entrDelta = rn.RiverEntranceDelta; if (exitDelta == null) { exitDelta = new Vec2i(0, 0); } if (entrDelta == null) { entrDelta = new Vec2i(0, 0); } //Calculatee the tile position of the entrance and exit point of the river int entrX = (entrDelta.x == 1) ? 16 : ((entrDelta.x == 0) ? 8 : 0); int entrZ = (entrDelta.z == 1) ? 16 : ((entrDelta.z == 0) ? 8 : 0); int exitX = (exitDelta.x == 1) ? 16 : ((exitDelta.x == 0) ? 8 : 0); int exitZ = (exitDelta.z == 1) ? 16 : ((exitDelta.z == 0) ? 8 : 0); float dx = entrX - exitX; float dz = entrZ - exitZ; //If dx or dz is 0, then float a, b, c; bool angle = (dx != 0 && dz != 0); float divBy = angle ? 2 : 1; if (dx == 0) { a = 0; b = 1; c = -entrX; } else if (dz == 0) { a = 1; b = 0; c = -entrZ; } else { float m = dz / dx; c = -(entrZ - m * entrX); a = 1; b = -m; } float dem_sqr = (a * a + b * b); for (int tx = 0; tx < World.ChunkSize; tx++) { for (int tz = 0; tz < World.ChunkSize; tz++) { float dist_sqr = ((a * tz + b * tx + c) * (a * tz + b * tx + c)) / dem_sqr; if (dist_sqr < (cb.RiverNode.EntranceWidth * cb.RiverNode.EntranceWidth) / divBy) { Vector2 off = new Vector2(x * World.ChunkSize + tx, z * World.ChunkSize + tz); //Debug.Log("here"); tiles[tx, tz] = Tile.WATER.ID; if (!(data[tx, tz] is Water)) { data[tx, tz] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz)); (data[tx, tz] as Water).SetUVOffset(off); } if (tx < World.ChunkSize - 1 && !(data[tx + 1, tz] is Water)) { data[tx + 1, tz] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz)); (data[tx + 1, tz] as Water).SetUVOffset(off + new Vector2(1, 0)); } if (tz < World.ChunkSize - 1 && !(data[tx, tz + 1] is Water)) { data[tx, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz + 1)); (data[tx, tz + 1] as Water).SetUVOffset(off + new Vector2(0, 1)); } if (tx < World.ChunkSize - 1 && tz < World.ChunkSize - 1 && !(data[tx + 1, tz + 1] is Water)) { data[tx + 1, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz + 1)); (data[tx + 1, tz + 1] as Water).SetUVOffset(off + new Vector2(1, 1)); } if (tx > 0 && !(data[tx - 1, tz] is Water)) { data[tx - 1, tz] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz)); (data[tx - 1, tz] as Water).SetUVOffset(off + new Vector2(-1, 0)); } if (tz > 0 && !(data[tx, tz - 1] is Water)) { data[tx, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz - 1)); (data[tx, tz - 1] as Water).SetUVOffset(off + new Vector2(0, -1)); } if (tx > 0 && tz > 0 && !(data[tx - 1, tz - 1] is Water)) { data[tx - 1, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz - 1)); (data[tx - 1, tz - 1] as Water).SetUVOffset(off + new Vector2(-1, -1)); } if (tx > 0 && tz < World.ChunkSize - 1 && !(data[tx - 1, tz + 1] is Water)) { data[tx - 1, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz + 1)); (data[tx - 1, tz + 1] as Water).SetUVOffset(off + new Vector2(-1, +1)); } if (tz > 0 && tx < World.ChunkSize - 1 && !(data[tx + 1, tz - 1] is Water)) { data[tx + 1, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz - 1)); (data[tx + 1, tz - 1] as Water).SetUVOffset(off + new Vector2(1, -1)); } } else if (dist_sqr < (cb.RiverNode.EntranceWidth * cb.RiverNode.EntranceWidth) * 1.4f / divBy) { tiles[tx, tz] = Tile.SAND.ID; } else { tiles[tx, tz] = Tile.GRASS.ID; } } } data[0, 0] = new Tree(new Vec2i(x * World.ChunkSize, z * World.ChunkSize)); Dictionary <int, WorldObjectData> data_ = new Dictionary <int, WorldObjectData>(); for (int i = 0; i < World.ChunkSize; i++) { for (int j = 0; j < World.ChunkSize; j++) { if (data[i, j] != null) { data_.Add(WorldObject.ObjectPositionHash(i, j), data[i, j]); } } } return(new ChunkData(x, z, tiles, cb.IsLand, data_)); //Debug.Log("river"); } else { ChunkData cd = new ChunkData(x, z, landClone, cb.IsLand); return(cd); } }
private ChunkData GenerateLakeChunk(int x, int z, ChunkBase cb) { ChunkData cd = new ChunkData(x, z, (int[, ])OCEAN.Clone(), false); return(cd); }
private void GenerateWorld3() { World world = new World(); //Create chunk bases ChunkBase[,] chunk_b = new ChunkBase[World.RegionSize, World.RegionSize]; ChunkData[,] chunks = new ChunkData[World.RegionSize, World.RegionSize]; River r = new River(); r.SetFirstChunk(new Vec2i(2, 2), 6); r.AddChunk(new Vec2i(3, 2), 6); r.AddChunk(new Vec2i(4, 2), 6); r.AddChunk(new Vec2i(4, 3), 6); r.AddChunk(new Vec2i(5, 3), 6); /* * r.AddChunk(new Vec2i(3,2), 6); * r.AddChunk(new Vec2i(3, 3), 6); * r.AddChunk(new Vec2i(4, 3), 6); * r.AddChunk(new Vec2i(4, 2), 6); * r.AddChunk(new Vec2i(4, 1), 6); * r.AddChunk(new Vec2i(3, 1), 6); * r.AddChunk(new Vec2i(2, 1), 6); * r.AddChunk(new Vec2i(1, 1), 6); */ /* * Vec2i last = new Vec2i(2, 2); * for(int i=0; i<10; i++) * { * int t = (i % 8); * int dx = 0; * int dz = 0; * if (t == 0 || t==1) * dx = 1; * else if (t == 2 || t == 3) * dz = 1; * else if (t == 3 || t == 5) * dx = -1; * else * dz = -1; * //int dx = (i % 2); * //int dz = (i + 1) % 2; * last = last + new Vec2i(dx, dz); * r.AddChunk(last, 6); * }*/ for (int rx = 0; rx < World.RegionSize; rx++) { for (int rz = 0; rz < World.RegionSize; rz++) { chunk_b[rx, rz] = new ChunkBase(new Vec2i(rx, rz), true); } } foreach (KeyValuePair <Vec2i, RiverNode> kvp in r.GenerateRiverNodes()) { chunk_b[kvp.Key.x, kvp.Key.z].AddRiver(kvp.Value); } int[,] emptyLandChunk = new int[World.ChunkSize, World.ChunkSize]; for (int x = 0; x < World.ChunkSize; x++) { for (int z = 0; z < World.ChunkSize; z++) { emptyLandChunk[x, z] = Tile.GRASS.ID; } } for (int rx = 0; rx < World.RegionSize; rx++) { for (int rz = 0; rz < World.RegionSize; rz++) { chunks[rx, rz] = GenerateChunk((int[, ])emptyLandChunk.Clone(), chunk_b[rx, rz]); } } ChunkRegion region = new ChunkRegion(0, 0, chunks); WorldManager.SetWorld(world); WorldManager.LoadedRegions[0, 0] = region; world.SetChunkBases(chunk_b); for (int rx = 0; rx < World.RegionSize - 1; rx++) { for (int rz = 0; rz < World.RegionSize - 1; rz++) { WorldManager.CRManager.LoadChunk(new Vec2i(rx, rz)); } } }
private void GenerateRiverBridge(ChunkBase cb, WorldObjectData[,] chunkObjs, int bridgeWidth = 5) { RiverNode rn = cb.RiverNode; int rDirX = Mathf.Abs(rn.RiverNodeDirection().x); int rDirZ = Mathf.Abs(rn.RiverNodeDirection().z); if (rDirX == 1 && rDirZ == 1) { return; } Vec2i absDir = new Vec2i(rDirX, rDirZ); int riverWidth = (int)rn.EntranceWidth; int halfWidth = bridgeWidth / 2; Vec2i start, end; if (rDirX == 1) { start = new Vec2i(World.ChunkSize / 2 - halfWidth, World.ChunkSize / 2 - riverWidth); end = new Vec2i(World.ChunkSize / 2 + halfWidth, World.ChunkSize / 2 + riverWidth + 1); } else { start = new Vec2i(World.ChunkSize / 2 - riverWidth, World.ChunkSize / 2 - halfWidth); end = new Vec2i(World.ChunkSize / 2 + riverWidth + 1, World.ChunkSize / 2 + halfWidth); } RiverBridgeObject rbObj = new RiverBridgeObject(start, end, absDir); IMultiTileObjectChild[,] childs = rbObj.GetChildren(); for (int x = 0; x < rbObj.Size.x; x++) { for (int z = 0; z < rbObj.Size.z; z++) { chunkObjs[start.x + x, start.z + z] = childs[x, z] as WorldObjectData; } } /* * //If these do not sum to 1, the direction is not simple (i.e, diagonal) and no bridge can be made * if (rnDir.x + rnDir.z != 1) * return; * //If the river is travelling in the z direction * if (rnDir.x == 0) * { * Vec2i start = new Vec2i(World.ChunkSize / 2 - halfWidth, World.ChunkSize / 2 - riverWidth); * Vec2i end = new Vec2i(World.ChunkSize / 2 + halfWidth, World.ChunkSize / 2 + riverWidth); * * RiverBridgeObject rbObj = new RiverBridgeObject(start, end, new Vec2i(1,0)); * IMultiTileObjectChild[,] childs = rbObj.GetChildren(); * for(int x=0; x<rbObj.Size.x; x++) * { * for(int z=0; z<rbObj.Size.z; z++) * { * chunkObjs[start.x + x, start.z + z] = childs[x, z] as WorldObjectData; * } * } * } * else * { * * }*/ }
public static ChunkColumn DecocedChunkColumn(byte[] buffer) { return(null); lock (_chunkRead) { MemoryStream stream = new MemoryStream(buffer); { NbtBinaryReader defStream = new NbtBinaryReader(stream, true); Log.Debug("New chunk column"); int count = defStream.ReadByte(); if (count < 1) { Log.Warn("Nothing to read"); return(null); } Log.Debug($"Reading {count} sections"); ChunkColumn chunkColumn = new ChunkColumn(); for (int s = 0; s < count; s++) { int idx = defStream.ReadByte(); Log.Debug($"New section {s}, index={idx}"); ChunkBase chunk = chunkColumn[s]; int chunkSize = 16 * 16 * 16; //defStream.Read(chunk.blocks, 0, chunkSize); //Log.Debug($"Blocks1:\n{Package.HexDump(chunk.blocks)}"); //if (defStream.Read(chunk.metadata.Data, 0, chunkSize/2) != chunkSize/2) Log.Error($"Out of data: metadata"); //Log.Debug($"metadata:\n{Package.HexDump(chunk.metadata.Data)}"); //if (defStream.Read(chunk.skylight.Data, 0, chunkSize/2) != chunkSize/2) Log.Error($"Out of data: skylight"); //Log.Debug($"skylight:\n{Package.HexDump(chunk.skylight.Data)}"); //if (defStream.Read(chunk.blocklight.Data, 0, chunkSize/2) != chunkSize/2) Log.Error($"Out of data: blocklight"); //Log.Debug($"blocklight:\n{Package.HexDump(chunk.blocklight.Data)}"); //Log.Debug($"skylight.Data:\n{Package.HexDump(chunk.skylight.Data, 64)}"); //Log.Debug($"blocklight.Data:\n{Package.HexDump(chunk.blocklight.Data)}"); //byte[] ints = new byte[256*4]; //var readLen = defStream.Read(ints, 0, ints.Length); //if (readLen != ints.Length) Log.Error($"Out of data biomeColors, read lenght {readLen}"); //Log.Debug($"biomeColor (pre):\n{Package.HexDump(ints)}"); //return null; //int j = 0; //for (int i = 0; i < ints.Length; i = i + 4) //{ // chunk.biomeId[j] = ints[i]; // chunk.biomeColor[j++] = BitConverter.ToInt32(new[] {(byte) 0, ints[i + 1], ints[i + 2], ints[i + 3]}, 0); //} //Log.Debug($"biomeId (post):\n{Package.HexDump(chunk.biomeId)}"); //if (stream.Position >= stream.Length - 1) return chunk; ////return chunk; //return chunk; } //if (stream.Position >= stream.Length - 1) continue; byte[] ba = new byte[512]; if (defStream.Read(ba, 0, 256 * 2) != 256 * 2) { Log.Error($"Out of data height"); } Buffer.BlockCopy(ba, 0, chunkColumn.height, 0, 512); //Log.Debug($"Heights:\n{Package.HexDump(ba)}"); //if (stream.Position >= stream.Length - 1) continue; if (defStream.Read(chunkColumn.biomeId, 0, 256) != 256) { Log.Error($"Out of data biomeId"); } //Log.Debug($"biomeId:\n{Package.HexDump(chunk.biomeId)}"); //if (stream.Position >= stream.Length - 1) continue; int borderBlock = VarInt.ReadInt32(stream); if (borderBlock != 0) { byte[] buf = new byte[borderBlock]; int len = defStream.Read(buf, 0, borderBlock); Log.Warn($"??? Got borderblock {borderBlock}. Read {len} bytes"); Log.Debug($"{Packet.HexDump(buf)}"); for (int i = 0; i < borderBlock; i++) { int x = (buf[i] & 0xf0) >> 4; int z = buf[i] & 0x0f; Log.Debug($"x={x}, z={z}"); } } int extraCount = VarInt.ReadSInt32(stream); if (extraCount != 0) { //Log.Warn($"Got extradata\n{Package.HexDump(defStream.ReadBytes(extraCount*10))}"); for (int i = 0; i < extraCount; i++) { var hash = VarInt.ReadSInt32(stream); var blockData = defStream.ReadInt16(); Log.Warn($"Got extradata: hash=0x{hash:X2}, blockdata=0x{blockData:X2}"); } } if (stream.Position < stream.Length - 1) { //Log.Debug($"Got NBT data\n{Package.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}"); while (stream.Position < stream.Length) { NbtFile file = new NbtFile() { BigEndian = false, UseVarInt = true }; file.LoadFromStream(stream, NbtCompression.None); Log.Debug($"Blockentity: {file.RootTag}"); } } if (stream.Position < stream.Length - 1) { Log.Warn($"Still have data to read\n{Packet.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}"); } return(chunkColumn); } } }
/// <summary> /// Reads the fiche's description and HTML content /// </summary> /// <param name="_reader"></param> /// <remarks>Heavy chunks are NOT read and will only be accessible asynchronously</remarks> public void Read(BinaryReader _reader) { uint signature = _reader.ReadUInt32(); if (signature != SIGNATURE) { throw new Exception("Unexpected signature!"); } uint versionMajor, versionMinor; versionMajor = (uint)_reader.ReadUInt16(); versionMinor = (uint)_reader.ReadUInt16(); uint version = (versionMajor << 16) | versionMinor; // Read hierarchy string strGUID = _reader.ReadString(); if (!Guid.TryParse(strGUID, out m_GUID)) { throw new Exception("Failed to parse fiche GUID!"); } string strCreationTime = _reader.ReadString(); if (!DateTime.TryParse(strCreationTime, out m_creationTime)) { throw new Exception("Failed to parse fiche creation time!"); } // We only read the GUIDs while the actual fiches will be processed later uint parentsCount = _reader.ReadUInt32(); while (m_tags.Count > 0) { RemoveTag(m_tags[0]); } m_tagGUIDs = new Guid[parentsCount]; for (int parentIndex = 0; parentIndex < parentsCount; parentIndex++) { strGUID = _reader.ReadString(); if (!Guid.TryParse(strGUID, out m_tagGUIDs[parentIndex])) { throw new Exception("Failed to parse fiche's parent GUID!"); } } // Read content string strType = _reader.ReadString(); if (!Enum.TryParse(strType, out m_type)) { throw new Exception("Failed to parse fiche's type!"); } m_title = _reader.ReadString(); if (_reader.ReadBoolean()) { string strURL = _reader.ReadString(); m_URL = WebHelpers.CreateCanonicalURL(strURL); } if (_reader.ReadBoolean()) { m_HTMLContent = _reader.ReadString(); } if (_reader.ReadBoolean()) { m_rootElement = new Brain2.DOMElement(_reader); } // Read chunks while (m_chunks.Count > 0) { m_chunks[0].Dispose(); m_chunks.RemoveAt(0); } uint chunksCount = _reader.ReadUInt32(); for (uint chunkIndex = 0; chunkIndex < chunksCount; chunkIndex++) { string chunkType = _reader.ReadString(); uint chunkLength = _reader.ReadUInt32(); ulong chunkStartOffset = (ulong)_reader.BaseStream.Position; ChunkBase chunk = CreateChunkFromType(chunkType, chunkStartOffset, chunkLength); if (chunk != null) { chunk.Read(_reader); // Only shallow data will be available, heavy data will be loaded asynchonously on demand } // Always jump to chunk's end, whether it read something or not... ulong chunkEndOffset = chunkStartOffset + chunkLength; _reader.BaseStream.Seek((long)chunkEndOffset, SeekOrigin.Begin); } // Fiche is now ready! m_status = STATUS.READY; }