Beispiel #1
0
        /// <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>());
            }
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #4
0
 internal bool goSouth()
 {
     if (CurrentChunk.GetSouthNeighbor() != null)
     {
         CurrentChunk = CurrentChunk.GetSouthNeighbor();
         readASlice();
         return(true);
     }
     return(false);
 }
Beispiel #5
0
 public override void Dispose()
 {
     Save();
     EmitEvent(new EntityChangesMap
     {
         FromHere = CurrentChunk
     });
     MovableComponent.Dispose();
     Session = null;
     CurrentMap.UnregisterEntity(this);
     CurrentChunk.UnregisterEntity(this);
     SessionManager.UnregisterCharacterAsync(Character);
 }
Beispiel #6
0
        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();
            }
        }