diff options
author | John Hurliman | 2009-10-18 02:00:42 -0700 |
---|---|---|
committer | John Hurliman | 2009-10-18 02:00:42 -0700 |
commit | b4526a5a6d170e04655990c8edb8e355156a2061 (patch) | |
tree | 457cc8535e9213f6003545a0363f325b9ef9e90b /OpenSim/Data | |
parent | * Committing Nini.dll with the patch from #3773 applied (diff) | |
download | opensim-SC_OLD-b4526a5a6d170e04655990c8edb8e355156a2061.zip opensim-SC_OLD-b4526a5a6d170e04655990c8edb8e355156a2061.tar.gz opensim-SC_OLD-b4526a5a6d170e04655990c8edb8e355156a2061.tar.bz2 opensim-SC_OLD-b4526a5a6d170e04655990c8edb8e355156a2061.tar.xz |
* Big performance increase in loading prims from the region database with MySQL
* Handle the AgentFOV packet
* Bypass queuing and throttles for ping checks to make ping times more closely match network latency
* Only track reliable bytes in LLUDPCLient.BytesSinceLastACK
Diffstat (limited to 'OpenSim/Data')
-rw-r--r-- | OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | 271 |
1 files changed, 138 insertions, 133 deletions
diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs index 6bc8bec..801d6b9 100644 --- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | |||
@@ -403,26 +403,23 @@ namespace OpenSim.Data.MySQL | |||
403 | } | 403 | } |
404 | } | 404 | } |
405 | 405 | ||
406 | public List<SceneObjectGroup> LoadObjects(UUID regionUUID) | 406 | public List<SceneObjectGroup> LoadObjects(UUID regionID) |
407 | { | 407 | { |
408 | UUID lastGroupID = UUID.Zero; | 408 | const int ROWS_PER_QUERY = 5000; |
409 | |||
410 | Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(ROWS_PER_QUERY); | ||
409 | Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>(); | 411 | Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>(); |
410 | Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(); | ||
411 | SceneObjectGroup grp = null; | ||
412 | int count = 0; | 412 | int count = 0; |
413 | 413 | ||
414 | #region Prim Loading | ||
415 | |||
414 | lock (m_Connection) | 416 | lock (m_Connection) |
415 | { | 417 | { |
416 | using (MySqlCommand cmd = m_Connection.CreateCommand()) | 418 | using (MySqlCommand cmd = m_Connection.CreateCommand()) |
417 | { | 419 | { |
418 | cmd.CommandText = "select *, " + | 420 | cmd.CommandText = |
419 | "case when prims.UUID = SceneGroupID " + | 421 | "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID"; |
420 | "then 0 else 1 end as sort from prims " + | 422 | cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString()); |
421 | "left join primshapes on prims.UUID = primshapes.UUID " + | ||
422 | "where RegionUUID = ?RegionUUID " + | ||
423 | "order by SceneGroupID asc, sort asc, LinkNumber asc"; | ||
424 | |||
425 | cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString()); | ||
426 | 423 | ||
427 | using (IDataReader reader = ExecuteReader(cmd)) | 424 | using (IDataReader reader = ExecuteReader(cmd)) |
428 | { | 425 | { |
@@ -434,56 +431,61 @@ namespace OpenSim.Data.MySQL | |||
434 | else | 431 | else |
435 | prim.Shape = BuildShape(reader); | 432 | prim.Shape = BuildShape(reader); |
436 | 433 | ||
437 | prims[prim.UUID] = prim; | 434 | UUID parentID = new UUID(reader["SceneGroupID"].ToString()); |
438 | 435 | if (parentID != prim.UUID) | |
439 | UUID groupID = new UUID(reader["SceneGroupID"].ToString()); | 436 | prim.ParentUUID = parentID; |
440 | 437 | ||
441 | if (groupID != lastGroupID) // New SOG | 438 | prims[prim.UUID] = prim; |
442 | { | ||
443 | if (grp != null) | ||
444 | objects[grp.UUID] = grp; | ||
445 | 439 | ||
446 | lastGroupID = groupID; | 440 | ++count; |
441 | if (count % ROWS_PER_QUERY == 0) | ||
442 | m_log.Debug("[REGION DB]: Loaded " + count + " prims..."); | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | 447 | ||
448 | // There sometimes exist OpenSim bugs that 'orphan groups' so that none of the prims are | 448 | #endregion Prim Loading |
449 | // recorded as the root prim (for which the UUID must equal the persisted group UUID). In | ||
450 | // this case, force the UUID to be the same as the group UUID so that at least these can be | ||
451 | // deleted (we need to change the UUID so that any other prims in the linkset can also be | ||
452 | // deleted). | ||
453 | if (prim.UUID != groupID && groupID != UUID.Zero) | ||
454 | { | ||
455 | m_log.WarnFormat( | ||
456 | "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID", | ||
457 | prim.Name, prim.UUID, prim.GroupPosition, groupID); | ||
458 | 449 | ||
459 | prim.UUID = groupID; | 450 | #region SceneObjectGroup Creation |
460 | } | ||
461 | 451 | ||
462 | grp = new SceneObjectGroup(prim); | 452 | // Create all of the SOGs from the root prims first |
463 | } | 453 | foreach (SceneObjectPart prim in prims.Values) |
464 | else | 454 | { |
465 | { | 455 | if (prim.ParentUUID == UUID.Zero) |
466 | // Black magic to preserve link numbers | 456 | objects[prim.UUID] = new SceneObjectGroup(prim); |
467 | // | 457 | } |
468 | int link = prim.LinkNum; | ||
469 | 458 | ||
470 | grp.AddPart(prim); | 459 | // Add all of the children objects to the SOGs |
460 | foreach (SceneObjectPart prim in prims.Values) | ||
461 | { | ||
462 | SceneObjectGroup sog; | ||
463 | if (prim.UUID != prim.ParentUUID) | ||
464 | { | ||
465 | if (objects.TryGetValue(prim.ParentUUID, out sog)) | ||
466 | { | ||
467 | int originalLinkNum = prim.LinkNum; | ||
471 | 468 | ||
472 | if (link != 0) | 469 | sog.AddPart(prim); |
473 | prim.LinkNum = link; | ||
474 | } | ||
475 | 470 | ||
476 | ++count; | 471 | // SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum. |
477 | if (count % 5000 == 0) | 472 | // We override that here |
478 | m_log.Debug("[REGION DB]: Loaded " + count + " prims..."); | 473 | if (originalLinkNum != 0) |
479 | } | 474 | prim.LinkNum = originalLinkNum; |
475 | } | ||
476 | else | ||
477 | { | ||
478 | m_log.Warn("[REGION DB]: Database contains an orphan child prim " + prim.UUID + " pointing to missing parent " + prim.ParentUUID); | ||
480 | } | 479 | } |
481 | |||
482 | if (grp != null) | ||
483 | objects[grp.UUID] = grp; | ||
484 | } | 480 | } |
485 | } | 481 | } |
486 | 482 | ||
483 | #endregion SceneObjectGroup Creation | ||
484 | |||
485 | m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count); | ||
486 | |||
487 | #region Prim Inventory Loading | ||
488 | |||
487 | // Instead of attempting to LoadItems on every prim, | 489 | // Instead of attempting to LoadItems on every prim, |
488 | // most of which probably have no items... get a | 490 | // most of which probably have no items... get a |
489 | // list from DB of all prims which have items and | 491 | // list from DB of all prims which have items and |
@@ -493,7 +495,7 @@ namespace OpenSim.Data.MySQL | |||
493 | { | 495 | { |
494 | using (MySqlCommand itemCmd = m_Connection.CreateCommand()) | 496 | using (MySqlCommand itemCmd = m_Connection.CreateCommand()) |
495 | { | 497 | { |
496 | itemCmd.CommandText = "select distinct primID from primitems"; | 498 | itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems"; |
497 | using (IDataReader itemReader = ExecuteReader(itemCmd)) | 499 | using (IDataReader itemReader = ExecuteReader(itemCmd)) |
498 | { | 500 | { |
499 | while (itemReader.Read()) | 501 | while (itemReader.Read()) |
@@ -502,9 +504,7 @@ namespace OpenSim.Data.MySQL | |||
502 | { | 504 | { |
503 | UUID primID = new UUID(itemReader["primID"].ToString()); | 505 | UUID primID = new UUID(itemReader["primID"].ToString()); |
504 | if (prims.ContainsKey(primID)) | 506 | if (prims.ContainsKey(primID)) |
505 | { | ||
506 | primsWithInventory.Add(prims[primID]); | 507 | primsWithInventory.Add(prims[primID]); |
507 | } | ||
508 | } | 508 | } |
509 | } | 509 | } |
510 | } | 510 | } |
@@ -512,9 +512,14 @@ namespace OpenSim.Data.MySQL | |||
512 | } | 512 | } |
513 | 513 | ||
514 | foreach (SceneObjectPart prim in primsWithInventory) | 514 | foreach (SceneObjectPart prim in primsWithInventory) |
515 | { | ||
515 | LoadItems(prim); | 516 | LoadItems(prim); |
517 | } | ||
518 | |||
519 | #endregion Prim Inventory Loading | ||
520 | |||
521 | m_log.DebugFormat("[REGION DB]: Loaded inventory from {0} objects", primsWithInventory.Count); | ||
516 | 522 | ||
517 | m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count); | ||
518 | return new List<SceneObjectGroup>(objects.Values); | 523 | return new List<SceneObjectGroup>(objects.Values); |
519 | } | 524 | } |
520 | 525 | ||
@@ -811,137 +816,137 @@ namespace OpenSim.Data.MySQL | |||
811 | private SceneObjectPart BuildPrim(IDataReader row) | 816 | private SceneObjectPart BuildPrim(IDataReader row) |
812 | { | 817 | { |
813 | SceneObjectPart prim = new SceneObjectPart(); | 818 | SceneObjectPart prim = new SceneObjectPart(); |
814 | prim.UUID = new UUID((String) row["UUID"]); | 819 | prim.UUID = new UUID((string)row["UUID"]); |
815 | // explicit conversion of integers is required, which sort | 820 | // explicit conversion of integers is required, which sort |
816 | // of sucks. No idea if there is a shortcut here or not. | 821 | // of sucks. No idea if there is a shortcut here or not. |
817 | prim.CreationDate = Convert.ToInt32(row["CreationDate"]); | 822 | prim.CreationDate = (int)row["CreationDate"]; |
818 | if (row["Name"] != DBNull.Value) | 823 | if (row["Name"] != DBNull.Value) |
819 | prim.Name = (String)row["Name"]; | 824 | prim.Name = (string)row["Name"]; |
820 | else | 825 | else |
821 | prim.Name = string.Empty; | 826 | prim.Name = String.Empty; |
822 | // various text fields | 827 | // Various text fields |
823 | prim.Text = (String) row["Text"]; | 828 | prim.Text = (string)row["Text"]; |
824 | prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), | 829 | prim.Color = Color.FromArgb((int)row["ColorA"], |
825 | Convert.ToInt32(row["ColorR"]), | 830 | (int)row["ColorR"], |
826 | Convert.ToInt32(row["ColorG"]), | 831 | (int)row["ColorG"], |
827 | Convert.ToInt32(row["ColorB"])); | 832 | (int)row["ColorB"]); |
828 | prim.Description = (String) row["Description"]; | 833 | prim.Description = (string)row["Description"]; |
829 | prim.SitName = (String) row["SitName"]; | 834 | prim.SitName = (string)row["SitName"]; |
830 | prim.TouchName = (String) row["TouchName"]; | 835 | prim.TouchName = (string)row["TouchName"]; |
831 | // permissions | 836 | // Permissions |
832 | prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); | 837 | prim.ObjectFlags = (uint)(int)row["ObjectFlags"]; |
833 | prim.CreatorID = new UUID((String) row["CreatorID"]); | 838 | prim.CreatorID = new UUID((string)row["CreatorID"]); |
834 | prim.OwnerID = new UUID((String) row["OwnerID"]); | 839 | prim.OwnerID = new UUID((string)row["OwnerID"]); |
835 | prim.GroupID = new UUID((String) row["GroupID"]); | 840 | prim.GroupID = new UUID((string)row["GroupID"]); |
836 | prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); | 841 | prim.LastOwnerID = new UUID((string)row["LastOwnerID"]); |
837 | prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); | 842 | prim.OwnerMask = (uint)(int)row["OwnerMask"]; |
838 | prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); | 843 | prim.NextOwnerMask = (uint)(int)row["NextOwnerMask"]; |
839 | prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); | 844 | prim.GroupMask = (uint)(int)row["GroupMask"]; |
840 | prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); | 845 | prim.EveryoneMask = (uint)(int)row["EveryoneMask"]; |
841 | prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); | 846 | prim.BaseMask = (uint)(int)row["BaseMask"]; |
842 | // vectors | 847 | // Vectors |
843 | prim.OffsetPosition = new Vector3( | 848 | prim.OffsetPosition = new Vector3( |
844 | Convert.ToSingle(row["PositionX"]), | 849 | (float)(double)row["PositionX"], |
845 | Convert.ToSingle(row["PositionY"]), | 850 | (float)(double)row["PositionY"], |
846 | Convert.ToSingle(row["PositionZ"]) | 851 | (float)(double)row["PositionZ"] |
847 | ); | 852 | ); |
848 | prim.GroupPosition = new Vector3( | 853 | prim.GroupPosition = new Vector3( |
849 | Convert.ToSingle(row["GroupPositionX"]), | 854 | (float)(double)row["GroupPositionX"], |
850 | Convert.ToSingle(row["GroupPositionY"]), | 855 | (float)(double)row["GroupPositionY"], |
851 | Convert.ToSingle(row["GroupPositionZ"]) | 856 | (float)(double)row["GroupPositionZ"] |
852 | ); | 857 | ); |
853 | prim.Velocity = new Vector3( | 858 | prim.Velocity = new Vector3( |
854 | Convert.ToSingle(row["VelocityX"]), | 859 | (float)(double)row["VelocityX"], |
855 | Convert.ToSingle(row["VelocityY"]), | 860 | (float)(double)row["VelocityY"], |
856 | Convert.ToSingle(row["VelocityZ"]) | 861 | (float)(double)row["VelocityZ"] |
857 | ); | 862 | ); |
858 | prim.AngularVelocity = new Vector3( | 863 | prim.AngularVelocity = new Vector3( |
859 | Convert.ToSingle(row["AngularVelocityX"]), | 864 | (float)(double)row["AngularVelocityX"], |
860 | Convert.ToSingle(row["AngularVelocityY"]), | 865 | (float)(double)row["AngularVelocityY"], |
861 | Convert.ToSingle(row["AngularVelocityZ"]) | 866 | (float)(double)row["AngularVelocityZ"] |
862 | ); | 867 | ); |
863 | prim.Acceleration = new Vector3( | 868 | prim.Acceleration = new Vector3( |
864 | Convert.ToSingle(row["AccelerationX"]), | 869 | (float)(double)row["AccelerationX"], |
865 | Convert.ToSingle(row["AccelerationY"]), | 870 | (float)(double)row["AccelerationY"], |
866 | Convert.ToSingle(row["AccelerationZ"]) | 871 | (float)(double)row["AccelerationZ"] |
867 | ); | 872 | ); |
868 | // quaternions | 873 | // quaternions |
869 | prim.RotationOffset = new Quaternion( | 874 | prim.RotationOffset = new Quaternion( |
870 | Convert.ToSingle(row["RotationX"]), | 875 | (float)(double)row["RotationX"], |
871 | Convert.ToSingle(row["RotationY"]), | 876 | (float)(double)row["RotationY"], |
872 | Convert.ToSingle(row["RotationZ"]), | 877 | (float)(double)row["RotationZ"], |
873 | Convert.ToSingle(row["RotationW"]) | 878 | (float)(double)row["RotationW"] |
874 | ); | 879 | ); |
875 | prim.SitTargetPositionLL = new Vector3( | 880 | prim.SitTargetPositionLL = new Vector3( |
876 | Convert.ToSingle(row["SitTargetOffsetX"]), | 881 | (float)(double)row["SitTargetOffsetX"], |
877 | Convert.ToSingle(row["SitTargetOffsetY"]), | 882 | (float)(double)row["SitTargetOffsetY"], |
878 | Convert.ToSingle(row["SitTargetOffsetZ"]) | 883 | (float)(double)row["SitTargetOffsetZ"] |
879 | ); | 884 | ); |
880 | prim.SitTargetOrientationLL = new Quaternion( | 885 | prim.SitTargetOrientationLL = new Quaternion( |
881 | Convert.ToSingle(row["SitTargetOrientX"]), | 886 | (float)(double)row["SitTargetOrientX"], |
882 | Convert.ToSingle(row["SitTargetOrientY"]), | 887 | (float)(double)row["SitTargetOrientY"], |
883 | Convert.ToSingle(row["SitTargetOrientZ"]), | 888 | (float)(double)row["SitTargetOrientZ"], |
884 | Convert.ToSingle(row["SitTargetOrientW"]) | 889 | (float)(double)row["SitTargetOrientW"] |
885 | ); | 890 | ); |
886 | 891 | ||
887 | prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); | 892 | prim.PayPrice[0] = (int)row["PayPrice"]; |
888 | prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); | 893 | prim.PayPrice[1] = (int)row["PayButton1"]; |
889 | prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); | 894 | prim.PayPrice[2] = (int)row["PayButton2"]; |
890 | prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); | 895 | prim.PayPrice[3] = (int)row["PayButton3"]; |
891 | prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); | 896 | prim.PayPrice[4] = (int)row["PayButton4"]; |
892 | 897 | ||
893 | prim.Sound = new UUID(row["LoopedSound"].ToString()); | 898 | prim.Sound = new UUID(row["LoopedSound"].ToString()); |
894 | prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); | 899 | prim.SoundGain = (float)(double)row["LoopedSoundGain"]; |
895 | prim.SoundFlags = 1; // If it's persisted at all, it's looped | 900 | prim.SoundFlags = 1; // If it's persisted at all, it's looped |
896 | 901 | ||
897 | if (!(row["TextureAnimation"] is DBNull)) | 902 | if (!(row["TextureAnimation"] is DBNull)) |
898 | prim.TextureAnimation = (Byte[])row["TextureAnimation"]; | 903 | prim.TextureAnimation = (byte[])row["TextureAnimation"]; |
899 | if (!(row["ParticleSystem"] is DBNull)) | 904 | if (!(row["ParticleSystem"] is DBNull)) |
900 | prim.ParticleSystem = (Byte[])row["ParticleSystem"]; | 905 | prim.ParticleSystem = (byte[])row["ParticleSystem"]; |
901 | 906 | ||
902 | prim.RotationalVelocity = new Vector3( | 907 | prim.RotationalVelocity = new Vector3( |
903 | Convert.ToSingle(row["OmegaX"]), | 908 | (float)(double)row["OmegaX"], |
904 | Convert.ToSingle(row["OmegaY"]), | 909 | (float)(double)row["OmegaY"], |
905 | Convert.ToSingle(row["OmegaZ"]) | 910 | (float)(double)row["OmegaZ"] |
906 | ); | 911 | ); |
907 | 912 | ||
908 | prim.SetCameraEyeOffset(new Vector3( | 913 | prim.SetCameraEyeOffset(new Vector3( |
909 | Convert.ToSingle(row["CameraEyeOffsetX"]), | 914 | (float)(double)row["CameraEyeOffsetX"], |
910 | Convert.ToSingle(row["CameraEyeOffsetY"]), | 915 | (float)(double)row["CameraEyeOffsetY"], |
911 | Convert.ToSingle(row["CameraEyeOffsetZ"]) | 916 | (float)(double)row["CameraEyeOffsetZ"] |
912 | )); | 917 | )); |
913 | 918 | ||
914 | prim.SetCameraAtOffset(new Vector3( | 919 | prim.SetCameraAtOffset(new Vector3( |
915 | Convert.ToSingle(row["CameraAtOffsetX"]), | 920 | (float)(double)row["CameraAtOffsetX"], |
916 | Convert.ToSingle(row["CameraAtOffsetY"]), | 921 | (float)(double)row["CameraAtOffsetY"], |
917 | Convert.ToSingle(row["CameraAtOffsetZ"]) | 922 | (float)(double)row["CameraAtOffsetZ"] |
918 | )); | 923 | )); |
919 | 924 | ||
920 | if (Convert.ToInt16(row["ForceMouselook"]) != 0) | 925 | if ((sbyte)row["ForceMouselook"] != 0) |
921 | prim.SetForceMouselook(true); | 926 | prim.SetForceMouselook(true); |
922 | 927 | ||
923 | prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); | 928 | prim.ScriptAccessPin = (int)row["ScriptAccessPin"]; |
924 | 929 | ||
925 | if (Convert.ToInt16(row["AllowedDrop"]) != 0) | 930 | if ((sbyte)row["AllowedDrop"] != 0) |
926 | prim.AllowedDrop = true; | 931 | prim.AllowedDrop = true; |
927 | 932 | ||
928 | if (Convert.ToInt16(row["DieAtEdge"]) != 0) | 933 | if ((sbyte)row["DieAtEdge"] != 0) |
929 | prim.DIE_AT_EDGE = true; | 934 | prim.DIE_AT_EDGE = true; |
930 | 935 | ||
931 | prim.SalePrice = Convert.ToInt32(row["SalePrice"]); | 936 | prim.SalePrice = (int)row["SalePrice"]; |
932 | prim.ObjectSaleType = unchecked((byte)Convert.ToSByte(row["SaleType"])); | 937 | prim.ObjectSaleType = unchecked((byte)(sbyte)row["SaleType"]); |
933 | 938 | ||
934 | prim.Material = unchecked((byte)Convert.ToSByte(row["Material"])); | 939 | prim.Material = unchecked((byte)(sbyte)row["Material"]); |
935 | 940 | ||
936 | if (!(row["ClickAction"] is DBNull)) | 941 | if (!(row["ClickAction"] is DBNull)) |
937 | prim.ClickAction = unchecked((byte)Convert.ToSByte(row["ClickAction"])); | 942 | prim.ClickAction = unchecked((byte)(sbyte)row["ClickAction"]); |
938 | 943 | ||
939 | prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); | 944 | prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); |
940 | prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); | 945 | prim.CollisionSoundVolume = (float)(double)row["CollisionSoundVolume"]; |
941 | 946 | ||
942 | if (Convert.ToInt16(row["PassTouches"]) != 0) | 947 | if ((sbyte)row["PassTouches"] != 0) |
943 | prim.PassTouches = true; | 948 | prim.PassTouches = true; |
944 | prim.LinkNum = Convert.ToInt32(row["LinkNumber"]); | 949 | prim.LinkNum = (int)row["LinkNumber"]; |
945 | 950 | ||
946 | return prim; | 951 | return prim; |
947 | } | 952 | } |