private void RunCall(IDataContainer obj, string func, object[] parameters, bool isSelf, FallbackAction fallback) { // This executes in the job thread. // Checks if this is still alive. if (IsDisposed) { return; } // Checks if the function still exists. LuaDataContainer dc = obj as LuaDataContainer; if (dc == null) { return; } IDataProvider lf = dc.GetProvider(func, isSelf); if (lf == null) { return; } // Calls the function. try { lf.Execute(parameters); } catch (InvalidOperationException ex) { // Last chance fallback action, if any. if (fallback != null) { fallback(ex); } else if (DefaultFallbackAction != null) { DefaultFallbackAction(ex); } else { // No fallback action: let's rethrow this. throw; } } catch (Exception) { // Other exceptions than InvalidOperationException are // immediately rethrown because they are, indeed, unexpected. throw; } }
private void SetField(LuaDataContainer obj, object key, object value, IDataProvider rawset) { if (rawset != null) { rawset.Execute(obj, key, value); } else { obj[key] = value; } }
private void AddMethodToTable(LuaDataContainer container, string fieldName, string funcName = null) { // Gets the type of the delegate to create. Type dType = this.GetType().GetNestedType(fieldName + "Delegate", BindingFlags.NonPublic); // Gets the delegate for the method to create. Delegate d = Delegate.CreateDelegate(dType, this, funcName ?? fieldName); // Creates the function and sets it to the table. container.BindWithFunction(fieldName, d); }
internal GWS( Cartridge cart, Character player, IPlatformHelper platformHelper, LuaDataFactory dataFactory) { this._dataFactory = dataFactory; this._cartridgeEntity = cart; this._cartridge = (LuaDataContainer)cart.DataContainer; this._player = (LuaDataContainer)player.DataContainer; this._platformHelper = platformHelper; ZonePoint pos = player.ObjectLocation; this._latitude = pos.Latitude; this._longitude = pos.Longitude; this._altitude = pos.Latitude; }
internal WIGInternalImpl(Engine engine, LuaDataFactory dataFactory) { this._engine = engine; this._dataFactory = dataFactory; this._mathHelper = new GeoMathHelper(dataFactory); LuaDataContainer wiginternal = dataFactory.CreateContainerAt("WIGInternal"); // WIGInternal Lua hooks: UI-related events AddMethodToTable(wiginternal, "LogMessage"); AddMethodToTable(wiginternal, "MessageBox"); AddMethodToTable(wiginternal, "GetInput"); AddMethodToTable(wiginternal, "NotifyOS"); AddMethodToTable(wiginternal, "ShowScreen"); AddMethodToTable(wiginternal, "ShowStatusText"); // WIGInternal Lua hooks: gameplay-related events AddMethodToTable(wiginternal, "AttributeChangedEvent"); AddMethodToTable(wiginternal, "CartridgeEvent"); AddMethodToTable(wiginternal, "CommandChangedEvent"); AddMethodToTable(wiginternal, "InventoryEvent"); AddMethodToTable(wiginternal, "MediaEvent"); AddMethodToTable(wiginternal, "TimerEvent"); AddMethodToTable(wiginternal, "ZoneStateChangedEvent"); // WIGInternal Lua hooks: internal functions AddMethodToTable(wiginternal, "IsPointInZone", "IsPointInZoneLua"); AddMethodToTable(wiginternal, "VectorToZone", "VectorToZoneLua"); AddMethodToTable(wiginternal, "VectorToSegment", "VectorToSegmentLua"); AddMethodToTable(wiginternal, "VectorToPoint", "VectorToPointLua"); AddMethodToTable(wiginternal, "TranslatePoint", "TranslatePointLua"); // Marks package WIGInternal as loaded dataFactory.SetContainerAt("package.loaded.WIGInternal", wiginternal); dataFactory.SetContainerAt("package.preload.WIGInternal", wiginternal); // Loads the Wherigo LUA engine. dataFactory.LoadAndRunEngine(); }
/// <summary> /// Write the table obj to the binary writer output. /// </summary> /// <param name="output">BinaryWriter to write the table to.</param> /// <param name="obj">Table to write to binary writer.</param> private void writeTable(BinaryWriter output, LuaDataContainer obj) { output.Write((byte)5); var entry = obj.GetEnumerator(); while (entry.MoveNext()) { // Save key if (entry.Key is bool) { output.Write((byte)1); output.Write((bool)entry.Key ? (byte)1 : (byte)0); } if (entry.Key is double) { output.Write((byte)2); output.Write((double)entry.Key); } if (entry.Key is string) { output.Write((byte)3); writeString(output, (string)entry.Key); } // Save value if (entry.Value == null) { // Write false for null output.Write((byte)1); output.Write((byte)0); } if (entry.Value is bool) { output.Write((byte)1); output.Write((bool)entry.Value ? (byte)1 : (byte)0); } if (entry.Value is double || entry.Value is int) { output.Write((byte)2); output.Write((double)entry.Value); } if (entry.Value is string) { output.Write((byte)3); writeByteArray(output, obj.GetByteArray(entry.Key)); } if (entry.Value is LuaDataProvider) { output.Write((byte)4); byte[] array = toArray(_dataFactory.GetProviderAt("string.dump").FirstOrDefault <string>(entry.Value)); output.Write(array.Length); output.Write(array); } if (entry.Value is LuaDataContainer) { LuaDataContainer dc = (LuaDataContainer)entry.Value; string className = dc.GetString("ClassName"); if (className != null && (className.Equals("Distance") || className.Equals("ZonePoint") || className.Equals("ZCommand") || className.Equals("ZReciprocalCommand"))) { output.Write((byte)8); writeString(output, className); LuaDataContainer data = dc.CallSelf("serialize"); writeTable(output, data); } else if (className != null && (className.Equals("ZCartridge") || className.Equals("ZCharacter") || className.Equals("ZInput") || className.Equals("ZItem") || className.Equals("ZMedia") || className.Equals("Zone") || className.Equals("ZTask") || className.Equals("ZTimer"))) { output.Write((byte)7); output.Write(Convert.ToInt16(dc.GetInt("ObjIndex").Value)); } else { // New: It is a normal LuaTable or an unknown new ZObject type LuaDataContainer data = dc; if (className != null) { // New: If we are here, than this is a new ZObject class, so call serialize before. // New: That means, that it is a normal LuaTable, so save it LuaDataProvider lf = dc.GetProvider("serialize", true); if (lf != null) { data = lf.FirstContainerOrDefault(); } } writeTable(output, data); } } } output.Write((byte)6); }
/// <summary> /// Saves the current cartridge to a GWS file. /// </summary> /// <param name="stream">Stream to write the data to.</param> /// <param name="saveName">Description for the save file, which is put into the file.</param> public void Save(Stream stream, string saveName = "UI initiated sync") { using (BinaryWriter output = new BinaryWriter(stream)) { // Write signature and version output.Write(Signature); output.Write(new byte[] { 0x00, 0x00, 0x00, 0x00 }); int lengthOfHeader = 0; lengthOfHeader += writeCString(output, _cartridgeEntity.Name); output.Write(BitConverter.GetBytes((long)((_cartridgeEntity.CreateDate.Ticks - new DateTime(2004, 02, 10, 01, 00, 00).Ticks) / TimeSpan.TicksPerSecond))); lengthOfHeader += 8; lengthOfHeader += writeCString(output, _cartridgeEntity.Player); // MUST be "Windows PPC" for Emulator lengthOfHeader += writeCString(output, _platformHelper.Device); // MUST be "Desktop" for Emulator lengthOfHeader += writeCString(output, _platformHelper.DeviceId); output.Write(BitConverter.GetBytes((long)((DateTime.Now.Ticks - new DateTime(2004, 02, 10, 01, 00, 00).Ticks) / TimeSpan.TicksPerSecond))); lengthOfHeader += 8; lengthOfHeader += writeCString(output, saveName); output.Write(BitConverter.GetBytes(_latitude)); lengthOfHeader += 8; output.Write(BitConverter.GetBytes(_longitude)); lengthOfHeader += 8; output.Write(BitConverter.GetBytes(_altitude)); lengthOfHeader += 8; var pos = output.BaseStream.Position; output.BaseStream.Position = 7; output.Write(BitConverter.GetBytes(lengthOfHeader)); output.BaseStream.Position = pos; _allZObjects = _cartridge.GetContainer("AllZObjects"); int numAllZObjects = _allZObjects.Count; output.Write(numAllZObjects); for (int i = 1; i < numAllZObjects; i++) { writeString(output, _allZObjects.GetContainer(i).GetString("ClassName")); } LuaDataContainer obj = _player; writeString(output, obj.GetString("ClassName")); LuaDataContainer data = obj.CallSelf("serialize"); writeTable(output, data); for (int i = 0; i < numAllZObjects; i++) { obj = (LuaDataContainer)_allZObjects.GetContainer(i); writeString(output, obj.GetString("ClassName")); data = obj.CallSelf("serialize"); writeTable(output, data); } output.Flush(); output.Close(); } }
private void readTable(BinaryReader input, LuaDataContainer obj) { string className = "unknown"; IDataProvider rawset = null; LuaDataContainer tab; object key = 1; if (obj != null) { className = obj.GetString("ClassName"); if (className != null) { rawset = obj.GetProvider("rawset", false); } } byte b = input.ReadByte(); while (b != 6) { // Key switch (b) { case 1: key = input.ReadByte() == 0 ? false : true; break; case 2: key = input.ReadDouble(); break; case 3: key = readString(input); break; default: throw new Exception(String.Format("Unsupported table key: {0} at byte {1}", b, input.BaseStream.Position)); } b = input.ReadByte(); // Value switch (b) { case 1: SetField(obj, key, input.ReadBoolean(), rawset); break; case 2: SetField(obj, key, input.ReadDouble(), rawset); break; case 3: SetField(obj, key, readByteArray(input), rawset); break; case 4: byte[] chunk = input.ReadBytes(input.ReadInt32()); SetField(obj, key, _dataFactory.LoadProvider(chunk, key.ToString()), rawset); break; case 5: tab = _dataFactory.CreateContainer(); SetField(obj, key, tab, rawset); readTable(input, tab); break; case 6: // End of table return; case 7: var objIndex = input.ReadInt16(); if (objIndex == -21555) { SetField(obj, key, _player, rawset); } else { SetField(obj, key, _allZObjects.GetContainer(objIndex), rawset); } break; case 8: tab = (LuaDataContainer)_dataFactory.CreateWherigoObject(readString(input)).DataContainer; SetField(obj, key, tab, rawset); // After an object, there is always a table with the content input.ReadByte(); readTable(input, tab); break; } b = input.ReadByte(); } }
/// <summary> /// Loads a save game for the current cartridge from a stream. /// </summary> /// <param name="stream">Stream to load the game from.</param> /// <returns>The metadata of the file.</returns> public Metadata Load(Stream stream) { int numAllZObjects; Metadata metadata; using (BinaryReader input = new BinaryReader(stream)) { // Loads the GWS metadata. metadata = LoadMetadata(input); // Belongs this GWS file to the cartridge if (!metadata.CartridgeCreateDate.Equals(_cartridgeEntity.CreateDate)) { throw new Exception("Trying to load a GWS file with different creation date of cartridge."); } // TODO // Check, if all fields are the same as the fields from the GWC cartridge. // If not, than ask, if we should go on, even it could get problems. int numOfObjects = input.ReadInt32(); _allZObjects = _cartridge.GetContainer("AllZObjects"); numAllZObjects = _allZObjects.Count; string objectType = null; for (int i = 1; i < numOfObjects; i++) { objectType = readString(input); if (i > numAllZObjects - 1) { // Object creation can be done using: WherigoObject wo = _dataFactory.CreateWherigoObject(objectType, _cartridge); } else { // TODO: Check, if objectType and real type of object are the same } } // Now update allZObjects, because it could be, that new ones are created _allZObjects = _cartridge.GetContainer("AllZObjects"); numAllZObjects = _allZObjects.Count; //LuaTable obj = _player; LuaDataContainer obj = _player; objectType = readString(input); // Read begin table (5) for player byte b = input.ReadByte(); // Read data for player readTable(input, obj); for (int i = 0; i < numAllZObjects; i++) { objectType = readString(input); b = input.ReadByte(); if (b != 5) { // error throw new InvalidOperationException(); } else { obj = (LuaDataContainer)_allZObjects.GetContainer(i); readTable(input, obj); } } input.Close(); } // Now deserialize all ZObjects for (int i = 0; i < numAllZObjects; i++) { ((LuaDataContainer)_allZObjects.GetContainer(i)).CallSelf("deserialize"); } // TODO: Update all lists return(metadata); }
/// <summary> /// Write the table obj to the binary writer output. /// </summary> /// <param name="output">BinaryWriter to write the table to.</param> /// <param name="obj">Table to write to binary writer.</param> private void writeTable(BinaryWriter output, LuaDataContainer obj) { output.Write((byte)5); var entry = obj.GetEnumerator(); while (entry.MoveNext()) { // Save key if (entry.Key is bool) { output.Write((byte)1); output.Write((bool)entry.Key ? (byte)1 : (byte)0); } if (entry.Key is double) { output.Write((byte)2); output.Write((double)entry.Key); } if (entry.Key is string) { output.Write((byte)3); writeString(output, (string)entry.Key); } // Save value if (entry.Value == null) { // Write false for null output.Write((byte)1); output.Write((byte)0); } if (entry.Value is bool) { output.Write((byte)1); output.Write((bool)entry.Value ? (byte)1 : (byte)0); } if (entry.Value is double || entry.Value is int) { output.Write((byte)2); output.Write((double)entry.Value); } if (entry.Value is string) { output.Write((byte)3); writeByteArray(output, obj.GetByteArray(entry.Key)); } if (entry.Value is LuaDataProvider) { output.Write((byte)4); byte[] array = toArray(_dataFactory.GetProviderAt("string.dump").FirstOrDefault<string>(entry.Value)); output.Write(array.Length); output.Write(array); } if (entry.Value is LuaDataContainer) { LuaDataContainer dc = (LuaDataContainer)entry.Value; string className = dc.GetString("ClassName"); if (className != null && (className.Equals("Distance") || className.Equals("ZonePoint") || className.Equals("ZCommand") || className.Equals("ZReciprocalCommand"))) { output.Write((byte)8); writeString(output, className); LuaDataContainer data = dc.CallSelf("serialize"); writeTable(output, data); } else if (className != null && (className.Equals("ZCartridge") || className.Equals("ZCharacter") || className.Equals("ZInput") || className.Equals("ZItem") || className.Equals("ZMedia") || className.Equals("Zone") || className.Equals("ZTask") || className.Equals("ZTimer"))) { output.Write((byte)7); output.Write(Convert.ToInt16(dc.GetInt("ObjIndex").Value)); } else { // New: It is a normal LuaTable or an unknown new ZObject type LuaDataContainer data = dc; if (className != null) { // New: If we are here, than this is a new ZObject class, so call serialize before. // New: That means, that it is a normal LuaTable, so save it LuaDataProvider lf = dc.GetProvider("serialize", true); if (lf != null) data = lf.FirstContainerOrDefault(); } writeTable(output, data); } } } output.Write((byte)6); }
private void SetField(LuaDataContainer obj, object key, object value, IDataProvider rawset) { if (rawset != null) rawset.Execute(obj, key, value); else obj[key] = value; }
private void readTable(BinaryReader input, LuaDataContainer obj) { string className = "unknown"; IDataProvider rawset = null; LuaDataContainer tab; object key = 1; if (obj != null) { className = obj.GetString("ClassName"); if (className != null) rawset = obj.GetProvider("rawset", false); } byte b = input.ReadByte(); while (b != 6) { // Key switch (b) { case 1: key = input.ReadByte() == 0 ? false : true; break; case 2: key = input.ReadDouble(); break; case 3: key = readString(input); break; default: throw new Exception(String.Format("Unsupported table key: {0} at byte {1}", b, input.BaseStream.Position)); } b = input.ReadByte(); // Value switch (b) { case 1: SetField(obj, key, input.ReadBoolean(), rawset); break; case 2: SetField(obj, key, input.ReadDouble(), rawset); break; case 3: SetField(obj, key, readByteArray(input), rawset); break; case 4: byte[] chunk = input.ReadBytes(input.ReadInt32()); SetField(obj, key, _dataFactory.LoadProvider(chunk, key.ToString()), rawset); break; case 5: tab = _dataFactory.CreateContainer(); SetField(obj, key, tab, rawset); readTable(input, tab); break; case 6: // End of table return; case 7: var objIndex = input.ReadInt16 (); if (objIndex == -21555) SetField (obj, key, _player, rawset); else SetField(obj, key, _allZObjects.GetContainer(objIndex), rawset); break; case 8: tab = (LuaDataContainer)_dataFactory.CreateWherigoObject(readString(input)).DataContainer; SetField(obj, key, tab, rawset); // After an object, there is always a table with the content input.ReadByte(); readTable(input, tab); break; } b = input.ReadByte(); } }
/// <summary> /// Loads a save game for the current cartridge from a stream. /// </summary> /// <param name="stream">Stream to load the game from.</param> /// <returns>The metadata of the file.</returns> public Metadata Load(Stream stream) { int numAllZObjects; Metadata metadata; using (BinaryReader input = new BinaryReader(stream)) { // Loads the GWS metadata. metadata = LoadMetadata(input); // Belongs this GWS file to the cartridge if (!metadata.CartridgeCreateDate.Equals(_cartridgeEntity.CreateDate)) throw new Exception("Trying to load a GWS file with different creation date of cartridge."); // TODO // Check, if all fields are the same as the fields from the GWC cartridge. // If not, than ask, if we should go on, even it could get problems. int numOfObjects = input.ReadInt32(); _allZObjects = _cartridge.GetContainer("AllZObjects"); numAllZObjects = _allZObjects.Count; string objectType = null; for (int i = 1; i < numOfObjects; i++) { objectType = readString(input); if (i > numAllZObjects - 1) { // Object creation can be done using: WherigoObject wo = _dataFactory.CreateWherigoObject(objectType, _cartridge); } else { // TODO: Check, if objectType and real type of object are the same } } // Now update allZObjects, because it could be, that new ones are created _allZObjects = _cartridge.GetContainer("AllZObjects"); numAllZObjects = _allZObjects.Count; //LuaTable obj = _player; LuaDataContainer obj = _player; objectType = readString(input); // Read begin table (5) for player byte b = input.ReadByte(); // Read data for player readTable(input, obj); for (int i = 0; i < numAllZObjects; i++) { objectType = readString(input); b = input.ReadByte(); if (b != 5) { // error throw new InvalidOperationException(); } else { obj = (LuaDataContainer)_allZObjects.GetContainer(i); readTable(input, obj); } } input.Close(); } // Now deserialize all ZObjects for (int i = 0; i < numAllZObjects; i++) { ((LuaDataContainer)_allZObjects.GetContainer(i)).CallSelf("deserialize"); } // TODO: Update all lists return metadata; }