/// <summary> /// Splits an enumeration into chunks of equal or lesser size /// </summary> /// <typeparam name="T">The enumeration element type</typeparam> /// <param name="source">The source enumeration</param> /// <param name="size">The size of each chunk</param> /// <returns>An enumeration of lists where each chunk is at most <paramref name="size"/> length</returns> /// <remarks>If <paramref name="source"/> yields no results, a single empty chunk is returned</remarks> public static IEnumerable <IReadOnlyList <T> > ChunkOrDefault <T>(this IEnumerable <T> source, int size) { var HasYielded = false; List <T>?CurrentChunk = null; foreach (var Item in source) { if (CurrentChunk == null) { // Creating a new List after each yield prevents unexpected behaviour when saving the results of Chunk() (such as calling .ToArray()) CurrentChunk = new List <T>(size); } CurrentChunk.Add(Item); if (CurrentChunk.Count == size) { HasYielded = true; #if NET40 yield return(new ReadOnlyList <T>(CurrentChunk)); #else yield return(CurrentChunk); #endif CurrentChunk = null; } } // If we haven't returned a single chunk, return an empty one if (!HasYielded) { yield return(Empty.ReadOnlyList <T>()); } }
public void TransferEntity(IChunk chunk) { if (/*CurrentChunk == chunk ||*/ chunk == null) { return; } CurrentChunk?.UnregisterEntity(this); chunk.RegisterEntity(this); ILogicEvent tempEvent; if (CurrentChunk == null || CurrentChunk.Map != chunk.Map) { tempEvent = new EntityChangesMap { FromHere = CurrentChunk, ToHere = chunk }; } else { tempEvent = new EntityTransferBetweenChunks { FromHere = CurrentChunk, ToHere = chunk }; } EmitEventAsync(tempEvent); CurrentChunk = chunk; }
/// <summary> /// Splits an enumeration into chunks of equal or lesser size /// </summary> /// <typeparam name="T">The enumeration element type</typeparam> /// <param name="source">The source enumeration</param> /// <param name="size">The size of each chunk</param> /// <returns>An enumeration of lists where each chunk is at most <paramref name="size"/> length</returns> /// <remarks>If <paramref name="source"/> yields no results, no chunks are returned</remarks> public static async IAsyncEnumerable <IReadOnlyList <T> > Chunk <T>(this IAsyncEnumerable <T> source, int size) { List <T>?CurrentChunk = null; await foreach (var Item in source) { if (CurrentChunk == null) { // Creating a new List after each yield prevents unexpected behaviour when saving the results of Chunk() (such as calling .ToArray()) CurrentChunk = new List <T>(size); } CurrentChunk.Add(Item); if (CurrentChunk.Count == size) { yield return(CurrentChunk); CurrentChunk = null; } } // Return any partial chunk if (CurrentChunk != null) { yield return(CurrentChunk); } }
internal bool goSouth() { if (CurrentChunk.GetSouthNeighbor() != null) { CurrentChunk = CurrentChunk.GetSouthNeighbor(); readASlice(); return(true); } return(false); }
public override void Dispose() { Save(); EmitEvent(new EntityChangesMap { FromHere = CurrentChunk }); MovableComponent.Dispose(); Session = null; CurrentMap.UnregisterEntity(this); CurrentChunk.UnregisterEntity(this); SessionManager.UnregisterCharacterAsync(Character); }
static internal void Go(string srcfile) { VP($"Assembling: {srcfile}"); var src = new Source(srcfile); var ofile = $"{qstr.StripExt(srcfile)}.WBIN"; var bo = QuickStream.WriteFile(ofile); bo.WriteString($"Wendicka Binary {(char)26}", true); var Chunks = new SortedDictionary <string, Chunk>(); Chunk CurrentChunk = null; try { var lastspace = 0; foreach (Source.Line L in src.Lines) { for (int p = 0; p < lastspace; p++) { WASM_Main.VT(" "); } WASM_Main.VT("\r"); var s = $"{L.From_File}:{L.Line_Number}"; lastspace = s.Length; WASM_Main.VT($"{s}\r"); Debug.WriteLine(s); var instr = Instruction.Get(L.Instruction); if (L.Instruction == "CHUNK") { if (!ValidID(L.ParamString)) { throw new Exception($"Illegal chunk name: {L.ParamString}"); } var CName = L.ParamString.ToUpper(); if (Chunks.ContainsKey(CName)) { WASM_Main.VP(""); WASM_Main.WARN($"Duplicate chunk name {CName}! Code will be appended to existing chunk! Is that what you wanted?"); CurrentChunk = Chunks[CName]; Debug.WriteLine($"Appending to Chunk: {CName}"); } else { Debug.WriteLine($"Creating Chunk: {CName}"); CurrentChunk = new Chunk(); Chunks[CName] = CurrentChunk; } } else if (L.Instruction.Length > 0 && (L.Instruction[0] == ':' || L.Instruction[L.Instruction.Length - 1] == ':')) { var Lab = L.Instruction.Replace(":", "").ToUpper(); if (CurrentChunk == null) { throw new Exception("Label requires chunk"); } CurrentChunk.Labels[Lab] = CurrentChunk.Length; } else if (instr == null) { throw new Exception($"Unknown instruction! \"{L.Instruction}\"!"); } else if (!instr.Check(L)) { throw new Exception($"Instruction {L.Instruction} does not provide the parameters wanted, or has otherwise bad input!"); } else if (CurrentChunk == null) { throw new Exception("No chunk!"); } else { // If all is good, let's do it! Debug.WriteLine($"Writing instruction {L.Instruction}/{Instruction.Get(L.Instruction).insnum}"); CurrentChunk.Add((byte)2); CurrentChunk.Add((byte)Instruction.Get(L.Instruction).insnum); foreach (Source.Parameter p in L.Parameters) { switch (p.Kind) { case Source.DataKind.StartChunk: case Source.DataKind.Einde: case Source.DataKind.Instruction: throw new Exception($"Internal error! Illegal instruction parameter! {p.Kind}"); case Source.DataKind.Index: CurrentChunk.Add((byte)Source.DataKind.Index); break; case Source.DataKind.Chunk: case Source.DataKind.String: case Source.DataKind.LocalVar: case Source.DataKind.GlobalVar: case Source.DataKind.API: CurrentChunk.Add((byte)p.Kind); CurrentChunk.Add(p.StrValue); break; case Source.DataKind.Label: CurrentChunk.Add((byte)Source.DataKind.Label); CurrentChunk.RequestedLabels[CurrentChunk.Length] = p.StrValue.ToString(); Debug.WriteLine($"Label {p.StrValue} requested at offset {CurrentChunk.Length}"); CurrentChunk.Add((int)0); break; case Source.DataKind.Reference: throw new Exception("No support for referrence (yet)"); case Source.DataKind.IntValue: CurrentChunk.Add((byte)Source.DataKind.IntValue); CurrentChunk.Add(p.intvalue); break; case Source.DataKind.FloatValue: throw new Exception("No support for float yet"); case Source.DataKind.Boolean: { var c = p.StrValue.ToString().ToUpper() == "TRUE" || p.StrValue.ToString().ToUpper() == "YES"; CurrentChunk.Add((byte)Source.DataKind.Boolean); CurrentChunk.Add((byte)p.intvalue); break; } case Source.DataKind.Null: CurrentChunk.Add((byte)12); break; default: throw new Exception($"Unknown datakind {p.Kind}! Source version conflict? Internal error?"); } } CurrentChunk.Add((byte)0); Debug.WriteLine($"Instruction {L.Instruction} ended"); } } for (int p = 0; p < lastspace; p++) { WASM_Main.VT(" "); } WASM_Main.VT("\r"); VP($" Saving: {ofile}"); foreach (string k in Chunks.Keys) { var Chnk = Chunks[k]; Debug.WriteLine($"Chunk: {k}"); Debug.WriteLine("= Configuring Labels"); foreach (int ofs in Chnk.RequestedLabels.Keys) { var Lab = Chnk.RequestedLabels[ofs]; var o = BitConverter.GetBytes(Chnk.Labels[Lab]); Debug.WriteLine($" = {ofs} => {Lab}"); if (!BitConverter.IsLittleEndian) { Array.Reverse(o); } for (byte i = 0; i < 4; ++i) { Chnk.buffer[ofs + i] = o[i]; } } Debug.WriteLine("= Writing Chunk Buffer"); bo.WriteByte((byte)Source.DataKind.StartChunk); bo.WriteByte(1); bo.WriteString(k); bo.WriteByte(2); bo.WriteInt(Chnk.buffer.Length); bo.WriteByte(0); bo.WriteBytes(Chnk.buffer); bo.WriteByte(0); } bo.WriteString("WBIN", true); bo.WriteInt((int)bo.Size + 4); bo.WriteString("WBIN", true); } catch (Exception e) { WASM_Main.VP("\n"); WASM_Main.Error(e); } finally { bo.Close(); } }