Compare commits
462 Commits
Author | SHA1 | Date |
---|---|---|
Dan Lake | bcd7f30089 | |
Dan Lake | 0b60cb84ea | |
Dan Lake | 1091001cf6 | |
Dan Lake | d0c5d592c2 | |
Dan Lake | b844abf852 | |
Dan Lake | 2aaad3c91a | |
Dan Lake | a8a31616f4 | |
Huaiyu (Kitty) Liu | a08bf6a12c | |
Dan Lake | 191ef5daf1 | |
Dan Lake | d0dd597351 | |
Dan Lake | cc7f04ea47 | |
Dan Lake | 5171f3adf7 | |
Dan Lake | 90562f0735 | |
Dan Lake | a311ba0483 | |
Dan Lake | 30a9cee425 | |
Dan Lake | 19678da2ec | |
Dan Lake | 396f4408cd | |
Dan Lake | eb95762769 | |
Dan Lake | 7447765f4d | |
Dan Lake | 333fa2f072 | |
Robert Adams | 5a78c715ea | |
Huaiyu (Kitty) Liu | aa5208b78f | |
Huaiyu (Kitty) Liu | f029bd7782 | |
Dan Lake | c06d9569d2 | |
Robert Adams | 6574690c7b | |
BlueWall | 60798f77a8 | |
Dan Lake | 7127910b3d | |
Huaiyu (Kitty) Liu | 5e8f24a44a | |
Huaiyu (Kitty) Liu | 1da0f6e9d9 | |
Huaiyu (Kitty) Liu | 64b39bf0f3 | |
Huaiyu (Kitty) Liu | 981ac91393 | |
Huaiyu (Kitty) Liu | 9817734adf | |
Robert Adams | 664f1ad2be | |
Dan Lake | c90c94e788 | |
Dan Lake | f5eb2ffe93 | |
Dan Lake | b71b7b2f7c | |
Dan Lake | 7573d3a1ac | |
Dan Lake | 974292996a | |
Dan Lake | e6141db0dc | |
Huaiyu (Kitty) Liu | c46f8ab291 | |
Huaiyu (Kitty) Liu | 492d684911 | |
Dan Lake | 2c27067dec | |
Dan Lake | b6d93d0c40 | |
Dan Lake | 66f905b09c | |
Dan Lake | 327f30e6d1 | |
Dan Lake | 97ea994a4b | |
Dan Lake | 8791e5dac0 | |
Huaiyu (Kitty) Liu | c0c9a1d9da | |
Dan Lake | 9c15c8897e | |
Dan Lake | fc67a9212e | |
Dan Lake | 32ddcefaca | |
Huaiyu (Kitty) Liu | 941cec5548 | |
Huaiyu (Kitty) Liu | 57a42508ec | |
Dan Lake | 0bd24d1f14 | |
Robert Adams | 6dc15dcb0c | |
Robert Adams | 16aa0f73e5 | |
Huaiyu (Kitty) Liu | 7c542be833 | |
Huaiyu (Kitty) Liu | d28c857232 | |
Huaiyu (Kitty) Liu | 90abbe26d3 | |
Huaiyu (Kitty) Liu | fb716dbd68 | |
Dan Lake | 71d991fe8a | |
Huaiyu (Kitty) Liu | 0319807820 | |
Huaiyu (Kitty) Liu | a48511ee30 | |
Huaiyu (Kitty) Liu | 7b8db83bd3 | |
Huaiyu (Kitty) Liu | 22f5f7962c | |
Dan Lake | 3eb13b6664 | |
Dan Lake | 6b31808f49 | |
Dan Lake | ef8b2f4711 | |
Huaiyu (Kitty) Liu | 8ab8969d82 | |
Huaiyu (Kitty) Liu | 06d002cc3b | |
Huaiyu (Kitty) Liu | fa892e4afb | |
Huaiyu (Kitty) Liu | fdb4e92dc3 | |
Huaiyu (Kitty) Liu | fd99eea0af | |
Huaiyu (Kitty) Liu | ee7b965bf9 | |
Huaiyu (Kitty) Liu | b03ecf24c4 | |
Huaiyu (Kitty) Liu | 1cbbb010b0 | |
Huaiyu (Kitty) Liu | e2b6c5d199 | |
Huaiyu (Kitty) Liu | 3c58a1c244 | |
Huaiyu (Kitty) Liu | 8dc3b85828 | |
Dan Lake | 3a582a4cec | |
Robert Adams | b3efab2bbd | |
Robert Adams | bfb1068eca | |
Huaiyu (Kitty) Liu | a17f0a0ea1 | |
Huaiyu (Kitty) Liu | 0be7f9d804 | |
Huaiyu (Kitty) Liu | dc572c770c | |
Huaiyu (Kitty) Liu | 83e3a6a59a | |
Huaiyu (Kitty) Liu | d375491142 | |
Huaiyu (Kitty) Liu | 40809775dd | |
Huaiyu (Kitty) Liu | 67eaa574a3 | |
Huaiyu (Kitty) Liu | 1cca4a978d | |
Huaiyu (Kitty) Liu | c3c566cd24 | |
Huaiyu (Kitty) Liu | 486497331c | |
Huaiyu (Kitty) Liu | d79a37e0ca | |
Huaiyu (Kitty) Liu | 8fa03afb5c | |
Huaiyu (Kitty) Liu | 384e39f225 | |
Huaiyu (Kitty) Liu | 4a68faf243 | |
Huaiyu (Kitty) Liu | a664835b03 | |
Robert Adams | 53fa87ad76 | |
Dan Lake | 080db3019e | |
Dan Lake | 17cc7563ad | |
Huaiyu (Kitty) Liu | 41317dda8e | |
Huaiyu (Kitty) Liu | f1800824eb | |
Huaiyu (Kitty) Liu | ef4caa2c75 | |
Huaiyu (Kitty) Liu | ab0630ed81 | |
Robert Adams | 95ce0caa76 | |
Dan Lake | 973d0fcdaa | |
Dan Lake | cfee54ffa0 | |
Robert Adams | 105e5913f6 | |
Robert Adams | 05dbf31567 | |
Robert Adams | b0173de7ec | |
Robert Adams | 83d67391f1 | |
Huaiyu (Kitty) Liu | 2f7ecf359b | |
Huaiyu (Kitty) Liu | 0e1efc3250 | |
Dan Lake | a0a8654c07 | |
Huaiyu (Kitty) Liu | 6ec6fe6745 | |
Huaiyu (Kitty) Liu | 3f07bf204b | |
Dan Lake | cd6f261d11 | |
Dan Lake | 7b94264798 | |
Huaiyu (Kitty) Liu | d04c298c0b | |
Huaiyu (Kitty) Liu | cf6c9e77a0 | |
Huaiyu (Kitty) Liu | 33fe1e9f76 | |
Huaiyu (Kitty) Liu | ef66b29e95 | |
Huaiyu (Kitty) Liu | 6c945ae38f | |
Huaiyu (Kitty) Liu | 4fc36b0748 | |
Huaiyu (Kitty) Liu | ba948251fe | |
Huaiyu (Kitty) Liu | 7aaacbc4a6 | |
Huaiyu (Kitty) Liu | ff5c86c90a | |
Huaiyu (Kitty) Liu | a7d7ca9b0f | |
Huaiyu (Kitty) Liu | 9b955d8e95 | |
Huaiyu (Kitty) Liu | 8497ecd28d | |
Huaiyu (Kitty) Liu | c979fdd3cb | |
Huaiyu (Kitty) Liu | 9f6c0e7622 | |
Dan Lake | 9556e0079b | |
Dan Lake | ee16ca551d | |
Huaiyu (Kitty) Liu | 75c97acab8 | |
Huaiyu (Kitty) Liu | f5e648f54a | |
Huaiyu (Kitty) Liu | 854cb58d6d | |
Huaiyu (Kitty) Liu | cd70c3ff56 | |
Huaiyu (Kitty) Liu | 04d406a7c8 | |
Huaiyu (Kitty) Liu | 4afd3f6602 | |
Huaiyu (Kitty) Liu | 4acd23f0f9 | |
Huaiyu (Kitty) Liu | eeb09f33e3 | |
Huaiyu (Kitty) Liu | f8bf6c2cc4 | |
Huaiyu (Kitty) Liu | 54ba7a61f8 | |
Huaiyu (Kitty) Liu | c07c46c147 | |
Huaiyu (Kitty) Liu | 7157398d77 | |
Huaiyu (Kitty) Liu | bceafb4291 | |
Huaiyu (Kitty) Liu | 49139f53bb | |
Dan Lake | c9b0a79f88 | |
Dan Lake | 5aaccf793d | |
Dan Lake | 3e74a72d2e | |
Dan Lake | c7fa637f0d | |
Huaiyu (Kitty) Liu | cb6630aa35 | |
Huaiyu (Kitty) Liu | 3076761d77 | |
Huaiyu (Kitty) Liu | 68375822cd | |
Huaiyu (Kitty) Liu | b182e3bf30 | |
Huaiyu (Kitty) Liu | 1c1d3893fc | |
opensim | 4319d974b2 | |
Huaiyu (Kitty) Liu | a5ebd04d9d | |
Huaiyu (Kitty) Liu | 3676b5fbef | |
Dan Lake | da6044b6be | |
Huaiyu (Kitty) Liu | 3d7cece491 | |
Huaiyu (Kitty) Liu | 85085977ac | |
Dan Lake | f47d1c84cb | |
Huaiyu (Kitty) Liu | 28f401d95a | |
Huaiyu (Kitty) Liu | 8b08e4b176 | |
Huaiyu (Kitty) Liu | e84a7157b4 | |
Huaiyu (Kitty) Liu | 21c48088d8 | |
Huaiyu (Kitty) Liu | 9dfc0e92b8 | |
Huaiyu (Kitty) Liu | d0938f57eb | |
Huaiyu (Kitty) Liu | b9bfe6ba51 | |
Huaiyu (Kitty) Liu | c244bbe143 | |
Huaiyu (Kitty) Liu | 9d3de471a5 | |
Huaiyu (Kitty) Liu | a06dad37fd | |
Huaiyu (Kitty) Liu | a06ddb9e88 | |
Huaiyu (Kitty) Liu | 2f41b216d3 | |
Huaiyu (Kitty) Liu | 7c033f9d08 | |
Huaiyu (Kitty) Liu | 2dccc3205d | |
Huaiyu (Kitty) Liu | 2f17a9d224 | |
Huaiyu (Kitty) Liu | fe3d4ec9a8 | |
Huaiyu (Kitty) Liu | 2bea8bb4bc | |
Robert Adams | e5a022c8d7 | |
Robert Adams | d71b49c2a4 | |
Dan Lake | 2d775f9a52 | |
Huaiyu (Kitty) Liu | 2abffd867f | |
Huaiyu (Kitty) Liu | 8df517454d | |
Robert Adams | fa7a8fb9c1 | |
Huaiyu (Kitty) Liu | 170a230e51 | |
Huaiyu (Kitty) Liu | cce9a12dbe | |
Dan Lake | ecee306d3c | |
Dan Lake | a0be3e2c5f | |
Dan Lake | fe623f0900 | |
Dan Lake | f89ae8700d | |
Dan Lake | 8e6425dad7 | |
Dan Lake | 396ea3ba65 | |
Huaiyu (Kitty) Liu | 5b79e15285 | |
Dan Lake | 13057c3751 | |
Dan Lake | 0445e6e251 | |
Huaiyu (Kitty) Liu | eed53e8a56 | |
Huaiyu (Kitty) Liu | 0ad9366abb | |
Dan Lake | 71566e31c2 | |
Dan Lake | 6e13ddf072 | |
Huaiyu (Kitty) Liu | fb8a91bc8d | |
Huaiyu (Kitty) Liu | 83b4d4121e | |
Dan Lake | 9704793a1c | |
Huaiyu (Kitty) Liu | b7dc2af5e6 | |
Huaiyu (Kitty) Liu | 4076cb4a3c | |
Dan Lake | ab6b9e5812 | |
Robert Adams | 6e251b13c4 | |
Robert Adams | 74903876eb | |
Huaiyu (Kitty) Liu | 0df0e92ff0 | |
Huaiyu (Kitty) Liu | 271f460bae | |
Huaiyu (Kitty) Liu | a8c722bead | |
Huaiyu (Kitty) Liu | 04ef2366c2 | |
Huaiyu (Kitty) Liu | 3d17bd5654 | |
Dan Lake | afca24acbe | |
Dan Lake | 10e405704a | |
Dan Lake | 7bcab8e975 | |
Dan Lake | 7a89cf5a68 | |
Dan Lake | 3bdc04acf3 | |
Robert Adams | d5acb9a214 | |
Huaiyu (Kitty) Liu | 4803745c0d | |
Robert Adams | d70deaaa64 | |
Robert Adams | e72f08e02a | |
Robert Adams | 9edbbf2728 | |
Huaiyu (Kitty) Liu | 37dd39fd5d | |
Huaiyu (Kitty) Liu | 48ad2010e5 | |
Huaiyu (Kitty) Liu | 1ab4df9954 | |
Huaiyu (Kitty) Liu | 13798f9f7d | |
Robert Adams | 7f6529af4e | |
Robert Adams | a1fa5c28c3 | |
Robert Adams | cc2a679121 | |
Huaiyu (Kitty) Liu | b848df2a3a | |
Huaiyu (Kitty) Liu | e4bdaaaa83 | |
Robert Adams | d514c31cc2 | |
Robert Adams | e0f28ac5ba | |
Huaiyu (Kitty) Liu | ae258a21e4 | |
Huaiyu (Kitty) Liu | 052af34a52 | |
Dan Lake | b1114dcb98 | |
Dan Lake | e21176f974 | |
Dan Lake | 7210b7f517 | |
Huaiyu (Kitty) Liu | 3fe31ad457 | |
Robert Adams | 59fbb9cbef | |
Robert Adams | b76c233db3 | |
Huaiyu (Kitty) Liu | 91e8fc50d3 | |
Robert Adams | 6b9d58b99b | |
Robert Adams | 400c9b5293 | |
Robert Adams | 11db34313d | |
Robert Adams | 319c48f112 | |
Huaiyu (Kitty) Liu | a5c55a19ef | |
Huaiyu (Kitty) Liu | f7de4f37ce | |
Huaiyu (Kitty) Liu | 9d613a20c0 | |
Robert Adams | 153fd02f0f | |
unknown | 784cb6c95c | |
Robert Adams | f212a60067 | |
Robert Adams | 2335968271 | |
Robert Adams | 1ff16c93a3 | |
Huaiyu (Kitty) Liu | 513ca97eb0 | |
Huaiyu (Kitty) Liu | 1d2a25689a | |
Huaiyu (Kitty) Liu | 10a41ad5b5 | |
Robert Adams | a25eac0a40 | |
Robert Adams | c9c94a5f23 | |
Huaiyu (Kitty) Liu | 3d1048f1e2 | |
Huaiyu (Kitty) Liu | 7b9bd89a5c | |
Huaiyu (Kitty) Liu | f99b516eec | |
Huaiyu (Kitty) Liu | e66668ad7e | |
Huaiyu (Kitty) Liu | 21a1000da6 | |
Huaiyu (Kitty) Liu | 94e433315e | |
Huaiyu (Kitty) Liu | 7229aa204e | |
Huaiyu (Kitty) Liu | f05502f3fe | |
Huaiyu (Kitty) Liu | 41c85d9fd1 | |
Dan Lake | 1837778cf9 | |
Dan Lake | 4be96bc3d2 | |
Huaiyu (Kitty) Liu | 2b2eb4dbe3 | |
Huaiyu (Kitty) Liu | b31fa7d8fe | |
Huaiyu (Kitty) Liu | 411fa60b2b | |
Robert Adams | 4d343d0fea | |
Huaiyu (Kitty) Liu | 63e35d53f7 | |
Huaiyu (Kitty) Liu | f47c301a56 | |
Robert Adams | 9970677ed8 | |
Huaiyu (Kitty) Liu | 7a331b6a8f | |
Huaiyu (Kitty) Liu | 5ef659520e | |
Huaiyu (Kitty) Liu | 88e42011af | |
Huaiyu (Kitty) Liu | 1da933041c | |
Robert Adams | 4fe0bd32d4 | |
Huaiyu (Kitty) Liu | 3cd1ec8752 | |
Huaiyu (Kitty) Liu | a9ebb3ebae | |
Huaiyu (Kitty) Liu | 2dc857b31d | |
Huaiyu (Kitty) Liu | e8e9a0fb43 | |
Huaiyu (Kitty) Liu | 29053b19d8 | |
Huaiyu (Kitty) Liu | 9ee4a7e9f3 | |
Huaiyu (Kitty) Liu | e9b831b8f4 | |
Huaiyu (Kitty) Liu | 6cb8b01bef | |
Huaiyu (Kitty) Liu | 396486a93b | |
Huaiyu (Kitty) Liu | c929348668 | |
Huaiyu (Kitty) Liu | 2ae8917c2e | |
Huaiyu (Kitty) Liu | 4fe0c6d0d2 | |
Robert Adams | f5870a1e23 | |
Huaiyu (Kitty) Liu | 62a9e0b7c4 | |
Huaiyu (Kitty) Liu | 3cff68340f | |
Huaiyu (Kitty) Liu | 97b01dcf75 | |
Robert Adams | 4a4ecb1cde | |
Huaiyu (Kitty) Liu | c84551ae2c | |
Huaiyu (Kitty) Liu | 9ca061b25a | |
Huaiyu (Kitty) Liu | ce4c8e4b6f | |
Huaiyu (Kitty) Liu | f36f1010b7 | |
Dan Lake | a7d4c974dd | |
Dan Lake | e709b55f01 | |
Dan Lake | a23ffa2262 | |
Dan Lake | ee10e23fc3 | |
Robert Adams | af29f4083f | |
Huaiyu (Kitty) Liu | 2ffa91d72a | |
Huaiyu (Kitty) Liu | 1252df6f1e | |
Huaiyu (Kitty) Liu | 1b99c33e6c | |
Robert Adams | 270f7e653a | |
Robert Adams | 8d87d9e42d | |
Robert Adams | cfab010b10 | |
Huaiyu (Kitty) Liu | 85b7bb916f | |
Huaiyu (Kitty) Liu | 441551e7c6 | |
Huaiyu (Kitty) Liu | 101d67c45b | |
Huaiyu (Kitty) Liu | 4860eba0ba | |
Huaiyu (Kitty) Liu | ea2dc04bac | |
Dan Lake | cf15fc0b97 | |
Huaiyu (Kitty) Liu | 65c4889474 | |
Huaiyu (Kitty) Liu | 005c743fae | |
Robert Adams | 3123671651 | |
Huaiyu (Kitty) Liu | 677889d3b6 | |
Huaiyu (Kitty) Liu | e39d2ab14f | |
Huaiyu (Kitty) Liu | 67858f0dcd | |
Huaiyu (Kitty) Liu | 43edf89a34 | |
Huaiyu (Kitty) Liu | a0eddfcf61 | |
Huaiyu (Kitty) Liu | d874e4338f | |
Dan Lake | af07881a9f | |
Dan Lake | e9e36e2964 | |
Dan Lake | 7a1a21cd15 | |
Dan Lake | b02d3090b3 | |
Dan Lake | f09f74c224 | |
Huaiyu (Kitty) Liu | b3179d34da | |
Robert Adams | 8256caad3f | |
Robert Adams | c541b42f7e | |
Robert Adams | 42563e77fa | |
Huaiyu (Kitty) Liu | c8dc14fb01 | |
Huaiyu (Kitty) Liu | 719f59db3f | |
Huaiyu (Kitty) Liu | 69476339df | |
Huaiyu (Kitty) Liu | 0be2fe7f13 | |
Huaiyu (Kitty) Liu | c1e19ead74 | |
Dan Lake | e7e2a62641 | |
Dan Lake | 039d919284 | |
Huaiyu (Kitty) Liu | 9e08ede0bd | |
Huaiyu (Kitty) Liu | 95be9c1f7d | |
Huaiyu (Kitty) Liu | b5f1137a7d | |
Huaiyu (Kitty) Liu | b29e7c6e5e | |
Dan Lake | 86235e200e | |
Dan Lake | 217b28195c | |
Dan Lake | 9d5888e0f6 | |
Dan Lake | b5463e042c | |
Dan Lake | ed380196ea | |
Dan Lake | 6a24d0eb2d | |
Huaiyu (Kitty) Liu | f8a0de591d | |
Huaiyu (Kitty) Liu | 5c31e0bdd3 | |
Huaiyu (Kitty) Liu | 7eb9affbd3 | |
Huaiyu (Kitty) Liu | 4bb99b3df5 | |
Huaiyu (Kitty) Liu | 739bb1dc43 | |
Dan Lake | 4f45dcf711 | |
Dan Lake | 9d7fd472c0 | |
Dan Lake | 046ec22924 | |
Dan Lake | a7ec095063 | |
Robert Adams | ce4b095a1a | |
Dan Lake | 17504fcccb | |
Dan Lake | a339598bad | |
Huaiyu (Kitty) Liu | 9ecf1c21aa | |
Huaiyu (Kitty) Liu | e4ab31e004 | |
Dan Lake | 247bed199f | |
Dan Lake | f2013d3c93 | |
Robert Adams | 2152a5ab7b | |
Robert Adams | 9669aa93f8 | |
Huaiyu (Kitty) Liu | 731a09bf95 | |
Robert Adams | 251592e54a | |
Huaiyu (Kitty) Liu | 837a77b24a | |
Huaiyu (Kitty) Liu | 9b34d50643 | |
Robert Adams | 254436e914 | |
Huaiyu (Kitty) Liu | 42645acab9 | |
Robert Adams | 7441fbfa3a | |
Robert Adams | 0dbd96a12f | |
Huaiyu (Kitty) Liu | d84e69fefe | |
Robert Adams | 7da71bd30d | |
Huaiyu (Kitty) Liu | f5df61162f | |
Robert Adams | e68d9a25b1 | |
Dan Lake | 0b164072b3 | |
Robert Adams | ae8f8d60a6 | |
Dan Lake | 7bec1f71cf | |
Robert Adams | be2af26231 | |
Dan Lake | a34e152e9b | |
Robert Adams | 8aded5bdd0 | |
Dan Lake | f0c2fe6569 | |
Dan Lake | adeab48e7e | |
Dan Lake | 9df74cf726 | |
Dan Lake | a5c321a548 | |
Huaiyu (Kitty) Liu | 5acaba2974 | |
Huaiyu (Kitty) Liu | 2ce7d982fa | |
Huaiyu (Kitty) Liu | 994d70f9d8 | |
Huaiyu (Kitty) Liu | 821f80bf3f | |
Huaiyu (Kitty) Liu | 130915f669 | |
Huaiyu (Kitty) Liu | 384895cbdd | |
Huaiyu (Kitty) Liu | f10059ccd9 | |
Huaiyu (Kitty) Liu | e68a8f7710 | |
Huaiyu (Kitty) Liu | d0b429c186 | |
Huaiyu (Kitty) Liu | d63e3db533 | |
Huaiyu (Kitty) Liu | 650b0bfe54 | |
Huaiyu (Kitty) Liu | 0a9a8cc680 | |
Huaiyu (Kitty) Liu | dc6964444e | |
Robert Adams | bdeeead120 | |
Huaiyu (Kitty) Liu | f97fe18648 | |
Huaiyu (Kitty) Liu | c1af982ff4 | |
Huaiyu (Kitty) Liu | cb49cfe6c5 | |
Robert Adams | a2ca47d7eb | |
Huaiyu (Kitty) Liu | e96625c8ca | |
Robert Adams | e1c3650634 | |
Robert Adams | 420aeb9b6a | |
Robert Adams | 7c6bca1668 | |
Dan Lake | 2b390f2436 | |
Dan Lake | c7923338bc | |
Dan Lake | dc86adbd17 | |
Robert Adams | a036426f18 | |
Robert Adams | 5c6f0878a1 | |
Robert Adams | 24bef963c7 | |
Robert Adams | b56b0c3086 | |
Dan Lake | 681190f682 | |
Robert Adams | 9e68de6b8f | |
Huaiyu (Kitty) Liu | f8ccfaf046 | |
Huaiyu (Kitty) Liu | bca02499dc | |
Robert Adams | 49d7ff0307 | |
Robert Adams | 46a01d9550 | |
Robert Adams | 9f515cb623 | |
Robert Adams | 838ffc27ed | |
Robert Adams | 5eca61585d | |
Robert Adams | 3b9a6a565f | |
Robert Adams | 62fbd2ef08 | |
Robert Adams | cf5aeb9a68 | |
Robert Adams | de9427e545 | |
hliu19 | a9608ba49a | |
Dan Lake | 32b9a8d78d | |
Dan Lake | f5d25981ac | |
Dan Lake | 1c93854b47 | |
Dan Lake | 188a2db02a | |
Dan Lake | 8f8ef75034 | |
Dan Lake | ae4964050b | |
Dan Lake | 9ada2a1f34 | |
Dan Lake | 9afa8b990d | |
Dan Lake | 7f9bb06b03 | |
Dan Lake | 6818427f1c | |
Dan Lake | 82a71fb7e2 | |
Dan Lake | 2283b85bcf | |
Dan Lake | 79327a6299 | |
Dan Lake | 031bc35c06 | |
Dan Lake | bcce66ad1f | |
Dan Lake | 6236d24d14 | |
Dan Lake | 9eee902637 | |
Dan Lake | bba803e39d | |
Dan Lake | d2fd36b2a5 | |
Dan Lake | 8027b7c1a5 | |
Dan Lake | 4216eacd6c |
|
@ -9,8 +9,6 @@
|
||||||
*.pdb
|
*.pdb
|
||||||
*.pidb
|
*.pidb
|
||||||
*.dll.build
|
*.dll.build
|
||||||
*.dll
|
|
||||||
*.VisualState.xml
|
|
||||||
*/*/obj
|
*/*/obj
|
||||||
*/*/*/obj
|
*/*/*/obj
|
||||||
*/*/*/*/obj
|
*/*/*/*/obj
|
||||||
|
@ -53,7 +51,6 @@ bin/OpenSim.Grid.InventoryServer.log
|
||||||
bin/OpenSim.Grid.MessagingServer.log
|
bin/OpenSim.Grid.MessagingServer.log
|
||||||
bin/OpenSim.Grid.UserServer.log
|
bin/OpenSim.Grid.UserServer.log
|
||||||
bin/OpenSim.log
|
bin/OpenSim.log
|
||||||
bin/*.manifest
|
|
||||||
bin/crashes/
|
bin/crashes/
|
||||||
Examples/*.dll
|
Examples/*.dll
|
||||||
OpenSim.build
|
OpenSim.build
|
||||||
|
|
|
@ -10,7 +10,7 @@ people that make the day to day of OpenSim happen.
|
||||||
* dahlia
|
* dahlia
|
||||||
* Melanie Thielker
|
* Melanie Thielker
|
||||||
* Diva (Crista Lopes, University of California, Irvine)
|
* Diva (Crista Lopes, University of California, Irvine)
|
||||||
* Dan Lake (Intel)
|
* dslake (Dan Lake, Intel)
|
||||||
* Marck
|
* Marck
|
||||||
* Mic Bowman (Intel)
|
* Mic Bowman (Intel)
|
||||||
* BlueWall (James Hughes)
|
* BlueWall (James Hughes)
|
||||||
|
@ -75,7 +75,7 @@ what it is today.
|
||||||
* daTwitch
|
* daTwitch
|
||||||
* devalnor-#708
|
* devalnor-#708
|
||||||
* dmiles (Daxtron Labs)
|
* dmiles (Daxtron Labs)
|
||||||
* dslake (Intel)
|
* dslake (Dan Lake, Intel)
|
||||||
* FredoChaplin
|
* FredoChaplin
|
||||||
* Gerhard
|
* Gerhard
|
||||||
* Godfrey
|
* Godfrey
|
||||||
|
@ -184,6 +184,10 @@ Some plugins are based on Cable Beach
|
||||||
Cable Beach is Copyright (c) 2008 Intel Corporation
|
Cable Beach is Copyright (c) 2008 Intel Corporation
|
||||||
see http://forge.opensimulator.org/gf/project/assetserver/
|
see http://forge.opensimulator.org/gf/project/assetserver/
|
||||||
|
|
||||||
|
Some plugins are based on Distributed Scene Graph (DSG)
|
||||||
|
Distributed Scene Graph is Copyright (c) 2011 Intel Corporation
|
||||||
|
|
||||||
|
|
||||||
In addition, we would like to thank:
|
In addition, we would like to thank:
|
||||||
* The Mono Project
|
* The Mono Project
|
||||||
* The NANT Developers
|
* The NANT Developers
|
||||||
|
|
|
@ -2077,5 +2077,12 @@ VALUES
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
public List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#endregion REGION SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,6 +540,148 @@ namespace OpenSim.Data.MySQL
|
||||||
return new List<SceneObjectGroup>(objects.Values);
|
return new List<SceneObjectGroup>(objects.Values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
public List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY)
|
||||||
|
{
|
||||||
|
const int ROWS_PER_QUERY = 5000;
|
||||||
|
|
||||||
|
Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(ROWS_PER_QUERY);
|
||||||
|
Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>();
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
#region Prim Loading
|
||||||
|
|
||||||
|
lock (m_dbLock)
|
||||||
|
{
|
||||||
|
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||||
|
{
|
||||||
|
dbcon.Open();
|
||||||
|
|
||||||
|
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||||
|
{
|
||||||
|
//cmd.CommandText =
|
||||||
|
// "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID";
|
||||||
|
cmd.CommandText = "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID " +
|
||||||
|
"and GroupPositionX>=?lowerX " +
|
||||||
|
"and GroupPositionX<=?upperX and GroupPositionY>=?lowerY and GroupPositionY<=?upperY ";
|
||||||
|
cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
|
||||||
|
cmd.Parameters.AddWithValue("lowerX", lowerX);
|
||||||
|
cmd.Parameters.AddWithValue("lowerY", lowerY);
|
||||||
|
cmd.Parameters.AddWithValue("upperX", upperX);
|
||||||
|
cmd.Parameters.AddWithValue("upperY", upperY);
|
||||||
|
|
||||||
|
using (IDataReader reader = ExecuteReader(cmd))
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
SceneObjectPart prim = BuildPrim(reader);
|
||||||
|
if (reader["Shape"] is DBNull)
|
||||||
|
prim.Shape = PrimitiveBaseShape.Default;
|
||||||
|
else
|
||||||
|
prim.Shape = BuildShape(reader);
|
||||||
|
|
||||||
|
UUID parentID = DBGuid.FromDB(reader["SceneGroupID"].ToString());
|
||||||
|
if (parentID != prim.UUID)
|
||||||
|
prim.ParentUUID = parentID;
|
||||||
|
|
||||||
|
prims[prim.UUID] = prim;
|
||||||
|
|
||||||
|
++count;
|
||||||
|
if (count % ROWS_PER_QUERY == 0)
|
||||||
|
m_log.Debug("[REGION DB]: Loaded " + count + " prims...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Prim Loading
|
||||||
|
|
||||||
|
#region SceneObjectGroup Creation
|
||||||
|
|
||||||
|
// Create all of the SOGs from the root prims first
|
||||||
|
foreach (SceneObjectPart prim in prims.Values)
|
||||||
|
{
|
||||||
|
if (prim.ParentUUID == UUID.Zero)
|
||||||
|
objects[prim.UUID] = new SceneObjectGroup(prim);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all of the children objects to the SOGs
|
||||||
|
foreach (SceneObjectPart prim in prims.Values)
|
||||||
|
{
|
||||||
|
SceneObjectGroup sog;
|
||||||
|
if (prim.UUID != prim.ParentUUID)
|
||||||
|
{
|
||||||
|
if (objects.TryGetValue(prim.ParentUUID, out sog))
|
||||||
|
{
|
||||||
|
int originalLinkNum = prim.LinkNum;
|
||||||
|
|
||||||
|
sog.AddPart(prim);
|
||||||
|
|
||||||
|
// SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum.
|
||||||
|
// We override that here
|
||||||
|
if (originalLinkNum != 0)
|
||||||
|
prim.LinkNum = originalLinkNum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[REGION DB]: Database contains an orphan child prim {0} {1} in region {2} pointing to missing parent {3}. This prim will not be loaded.",
|
||||||
|
prim.Name, prim.UUID, regionID, prim.ParentUUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion SceneObjectGroup Creation
|
||||||
|
|
||||||
|
m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count);
|
||||||
|
|
||||||
|
#region Prim Inventory Loading
|
||||||
|
|
||||||
|
// Instead of attempting to LoadItems on every prim,
|
||||||
|
// most of which probably have no items... get a
|
||||||
|
// list from DB of all prims which have items and
|
||||||
|
// LoadItems only on those
|
||||||
|
List<SceneObjectPart> primsWithInventory = new List<SceneObjectPart>();
|
||||||
|
lock (m_dbLock)
|
||||||
|
{
|
||||||
|
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||||
|
{
|
||||||
|
dbcon.Open();
|
||||||
|
|
||||||
|
using (MySqlCommand itemCmd = dbcon.CreateCommand())
|
||||||
|
{
|
||||||
|
itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems";
|
||||||
|
using (IDataReader itemReader = ExecuteReader(itemCmd))
|
||||||
|
{
|
||||||
|
while (itemReader.Read())
|
||||||
|
{
|
||||||
|
if (!(itemReader["primID"] is DBNull))
|
||||||
|
{
|
||||||
|
UUID primID = DBGuid.FromDB(itemReader["primID"].ToString());
|
||||||
|
if (prims.ContainsKey(primID))
|
||||||
|
primsWithInventory.Add(prims[primID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectPart prim in primsWithInventory)
|
||||||
|
{
|
||||||
|
LoadItems(prim);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Prim Inventory Loading
|
||||||
|
|
||||||
|
m_log.DebugFormat("[REGION DB]: Loaded inventory from {0} objects", primsWithInventory.Count);
|
||||||
|
|
||||||
|
return new List<SceneObjectGroup>(objects.Values);
|
||||||
|
}
|
||||||
|
#endregion REGION SYNC
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load in a prim's persisted inventory.
|
/// Load in a prim's persisted inventory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -127,5 +127,12 @@ namespace OpenSim.Data.Null
|
||||||
public void Shutdown()
|
public void Shutdown()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
public List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#endregion REGION SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2363,5 +2363,11 @@ namespace OpenSim.Data.SQLite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
public List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#endregion REGION SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace OpenSim.Framework
|
||||||
public delegate void ViewerEffectEventHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args);
|
public delegate void ViewerEffectEventHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args);
|
||||||
|
|
||||||
public delegate void ChatMessage(Object sender, OSChatMessage e);
|
public delegate void ChatMessage(Object sender, OSChatMessage e);
|
||||||
|
public delegate void ChatMessageRaw(Object sender, byte[] chatData);
|
||||||
|
|
||||||
public delegate void GenericMessage(Object sender, string method, List<String> args);
|
public delegate void GenericMessage(Object sender, string method, List<String> args);
|
||||||
|
|
||||||
|
@ -82,6 +83,9 @@ namespace OpenSim.Framework
|
||||||
public delegate void TeleportLocationRequest(
|
public delegate void TeleportLocationRequest(
|
||||||
IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags);
|
IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags);
|
||||||
|
|
||||||
|
//DSG:
|
||||||
|
public delegate void SameRegionTeleportlRequest(IClientAPI remoteClient, byte[] tpLocReq);
|
||||||
|
|
||||||
public delegate void TeleportLandmarkRequest(
|
public delegate void TeleportLandmarkRequest(
|
||||||
IClientAPI remoteClient, AssetLandmark lm);
|
IClientAPI remoteClient, AssetLandmark lm);
|
||||||
|
|
||||||
|
@ -149,6 +153,7 @@ namespace OpenSim.Framework
|
||||||
public delegate void NewAvatar(IClientAPI remoteClient, UUID agentID, bool status);
|
public delegate void NewAvatar(IClientAPI remoteClient, UUID agentID, bool status);
|
||||||
|
|
||||||
public delegate void UpdateAgent(IClientAPI remoteClient, AgentUpdateArgs agentData);
|
public delegate void UpdateAgent(IClientAPI remoteClient, AgentUpdateArgs agentData);
|
||||||
|
public delegate void UpdateAgentRaw(IClientAPI remoteClient, byte[] agentData);
|
||||||
|
|
||||||
public delegate void AgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset);
|
public delegate void AgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset);
|
||||||
|
|
||||||
|
@ -748,12 +753,15 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
IPEndPoint RemoteEndPoint { get; }
|
IPEndPoint RemoteEndPoint { get; }
|
||||||
|
|
||||||
|
uint MaxCoarseLocations { get; }
|
||||||
|
|
||||||
event GenericMessage OnGenericMessage;
|
event GenericMessage OnGenericMessage;
|
||||||
|
|
||||||
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")]
|
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")]
|
||||||
event ImprovedInstantMessage OnInstantMessage;
|
event ImprovedInstantMessage OnInstantMessage;
|
||||||
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments. Rename OnChat.")]
|
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments. Rename OnChat.")]
|
||||||
event ChatMessage OnChatFromClient;
|
event ChatMessage OnChatFromClient;
|
||||||
|
event ChatMessageRaw OnChatFromClientRaw;
|
||||||
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")]
|
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")]
|
||||||
event TextureRequest OnRequestTexture;
|
event TextureRequest OnRequestTexture;
|
||||||
// [Obsolete("LLClientView Specific - Remove bitbuckets. Adam, can you be more specific here.. as I don't see any bit buckets.")]
|
// [Obsolete("LLClientView Specific - Remove bitbuckets. Adam, can you be more specific here.. as I don't see any bit buckets.")]
|
||||||
|
@ -779,6 +787,9 @@ namespace OpenSim.Framework
|
||||||
event RequestMapBlocks OnRequestMapBlocks;
|
event RequestMapBlocks OnRequestMapBlocks;
|
||||||
event RequestMapName OnMapNameRequest;
|
event RequestMapName OnMapNameRequest;
|
||||||
event TeleportLocationRequest OnTeleportLocationRequest;
|
event TeleportLocationRequest OnTeleportLocationRequest;
|
||||||
|
//DSG:
|
||||||
|
event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
|
||||||
|
//end of DSG
|
||||||
event DisconnectUser OnDisconnectUser;
|
event DisconnectUser OnDisconnectUser;
|
||||||
event RequestAvatarProperties OnRequestAvatarProperties;
|
event RequestAvatarProperties OnRequestAvatarProperties;
|
||||||
event SetAlwaysRun OnSetAlwaysRun;
|
event SetAlwaysRun OnSetAlwaysRun;
|
||||||
|
@ -789,6 +800,7 @@ namespace OpenSim.Framework
|
||||||
event GenericCall1 OnCompleteMovementToRegion;
|
event GenericCall1 OnCompleteMovementToRegion;
|
||||||
event UpdateAgent OnPreAgentUpdate;
|
event UpdateAgent OnPreAgentUpdate;
|
||||||
event UpdateAgent OnAgentUpdate;
|
event UpdateAgent OnAgentUpdate;
|
||||||
|
event UpdateAgentRaw OnAgentUpdateRaw;
|
||||||
event AgentRequestSit OnAgentRequestSit;
|
event AgentRequestSit OnAgentRequestSit;
|
||||||
event AgentSit OnAgentSit;
|
event AgentSit OnAgentSit;
|
||||||
event AvatarPickerRequest OnAvatarPickerRequest;
|
event AvatarPickerRequest OnAvatarPickerRequest;
|
||||||
|
|
|
@ -141,6 +141,19 @@ namespace OpenSim.Framework
|
||||||
public string RemotingAddress;
|
public string RemotingAddress;
|
||||||
public UUID ScopeID = UUID.Zero;
|
public UUID ScopeID = UUID.Zero;
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
//IP:port for the symmetric sync listener this actor is configured to connect to
|
||||||
|
private string m_syncServerAddr = String.Empty;
|
||||||
|
private int m_syncServerPort;
|
||||||
|
//IP:port for the avatar sync server this actor is configured to connect to
|
||||||
|
private string m_avatarSyncServerAddr = String.Empty;
|
||||||
|
private int m_avatarSyncServerPort;
|
||||||
|
//IP:port for the physics sync server this actor is configured to connect to
|
||||||
|
private string m_physicsSyncServerAddr = String.Empty;
|
||||||
|
private int m_physicsSyncServerPort;
|
||||||
|
private uint m_quarkLocX;
|
||||||
|
private uint m_quarkLocY;
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
// Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
|
// Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
|
||||||
|
|
||||||
|
@ -436,6 +449,45 @@ namespace OpenSim.Framework
|
||||||
get { return Util.UIntsToLong((RegionLocX * (uint) Constants.RegionSize), (RegionLocY * (uint) Constants.RegionSize)); }
|
get { return Util.UIntsToLong((RegionLocX * (uint) Constants.RegionSize), (RegionLocY * (uint) Constants.RegionSize)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
public string SyncServerAddress
|
||||||
|
{
|
||||||
|
get { return m_syncServerAddr; }
|
||||||
|
}
|
||||||
|
public int SyncServerPort
|
||||||
|
{
|
||||||
|
get { return m_syncServerPort; }
|
||||||
|
}
|
||||||
|
public string AvatarSyncServerAddress
|
||||||
|
{
|
||||||
|
get { return m_avatarSyncServerAddr; }
|
||||||
|
}
|
||||||
|
public int AvatarSyncServerPort
|
||||||
|
{
|
||||||
|
get { return m_avatarSyncServerPort; }
|
||||||
|
}
|
||||||
|
public string PhysicsSyncServerAddress
|
||||||
|
{
|
||||||
|
get { return m_physicsSyncServerAddr; }
|
||||||
|
}
|
||||||
|
public int PhysicsSyncServerPort
|
||||||
|
{
|
||||||
|
get { return m_physicsSyncServerPort; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint SyncQuarkLocationX
|
||||||
|
{
|
||||||
|
get { return m_quarkLocX; }
|
||||||
|
set { m_quarkLocX = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint SyncQuarkLocationY
|
||||||
|
{
|
||||||
|
get { return m_quarkLocY; }
|
||||||
|
set { m_quarkLocY = value; }
|
||||||
|
}
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
public void SetEndPoint(string ipaddr, int port)
|
public void SetEndPoint(string ipaddr, int port)
|
||||||
{
|
{
|
||||||
IPAddress tmpIP = IPAddress.Parse(ipaddr);
|
IPAddress tmpIP = IPAddress.Parse(ipaddr);
|
||||||
|
@ -588,6 +640,34 @@ namespace OpenSim.Framework
|
||||||
// Multi-tenancy
|
// Multi-tenancy
|
||||||
//
|
//
|
||||||
ScopeID = new UUID(config.GetString("ScopeID", UUID.Zero.ToString()));
|
ScopeID = new UUID(config.GetString("ScopeID", UUID.Zero.ToString()));
|
||||||
|
|
||||||
|
// DSG SYNC
|
||||||
|
m_syncServerAddr = config.GetString("SyncServerAddress", String.Empty);
|
||||||
|
m_syncServerPort = config.GetInt("SyncServerPort", -1);
|
||||||
|
//if either IP or port is not configured, we set IP to empty to raise warning later
|
||||||
|
if (m_syncServerPort == -1)
|
||||||
|
m_syncServerAddr = String.Empty;
|
||||||
|
|
||||||
|
m_avatarSyncServerAddr = config.GetString("AvatarSyncServerAddress", String.Empty);
|
||||||
|
m_avatarSyncServerPort = config.GetInt("AvatarSyncServerPort", -1);
|
||||||
|
if (m_avatarSyncServerPort == -1)
|
||||||
|
m_avatarSyncServerAddr = String.Empty;
|
||||||
|
|
||||||
|
m_physicsSyncServerAddr = config.GetString("PhysicsSyncServerAddress", String.Empty);
|
||||||
|
m_physicsSyncServerPort = config.GetInt("PhysicsSyncServerPort", -1);
|
||||||
|
if (m_physicsSyncServerPort == -1)
|
||||||
|
m_physicsSyncServerAddr = String.Empty;
|
||||||
|
|
||||||
|
string quarkLocation = config.GetString("SyncQuarkLocation", "1000,1000");
|
||||||
|
|
||||||
|
string[] quarkLocElements = quarkLocation.Split(new char[] { ',' });
|
||||||
|
|
||||||
|
m_quarkLocX = Convert.ToUInt32(quarkLocElements[0]);
|
||||||
|
m_quarkLocY = Convert.ToUInt32(quarkLocElements[1]);
|
||||||
|
|
||||||
|
|
||||||
|
// end of DSG SYNC
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteNiniConfig(IConfigSource source)
|
private void WriteNiniConfig(IConfigSource source)
|
||||||
|
@ -957,4 +1037,4 @@ namespace OpenSim.Framework
|
||||||
return kvp;
|
return kvp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace OpenSim
|
||||||
|
|
||||||
public static string GetVersionString(string versionNumber, Flavour flavour)
|
public static string GetVersionString(string versionNumber, Flavour flavour)
|
||||||
{
|
{
|
||||||
string versionString = "OpenSim " + versionNumber + " " + flavour;
|
string versionString = "OpenSim DSG " + versionNumber + " " + flavour;
|
||||||
return versionString.PadRight(VERSIONINFO_VERSION_LENGTH);
|
return versionString.PadRight(VERSIONINFO_VERSION_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -388,8 +388,58 @@ namespace OpenSim
|
||||||
"kill uuid <UUID>",
|
"kill uuid <UUID>",
|
||||||
"Kill an object by UUID", KillUUID);
|
"Kill an object by UUID", KillUUID);
|
||||||
|
|
||||||
|
//REGION SYNC
|
||||||
|
//Add one more command handler for "sync start", to pass simulator-wise information to one valide Scene.
|
||||||
|
//A trick to enable Script Engine to run scripts in several adjacent regions (all objects and their scripts
|
||||||
|
//exisited in the valid region, but all regions have their Scene data structure up and hold the RegionInfo.
|
||||||
|
m_console.Commands.AddCommand("region", false, "sync start",
|
||||||
|
"sync start",
|
||||||
|
"start synchronization with the authoratative Scene", SyncStart);
|
||||||
|
//End REGION SYNC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
protected void SyncStart(string module, string[] cmdparams)
|
||||||
|
{
|
||||||
|
m_log.Debug("OpenSim: receives sync start command, do something");
|
||||||
|
|
||||||
|
//string validLocalScene = m_config.
|
||||||
|
IConfig regionSyncConfig = m_config.Source.Configs["RegionSyncModule"];
|
||||||
|
|
||||||
|
if (regionSyncConfig == null || regionSyncConfig.GetString("Enabled", "").ToLower() != "true")
|
||||||
|
{
|
||||||
|
m_log.Warn("[OpenSim] Not in sync mode. Ignore cmmand.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regionSyncConfig.GetString("Mode", "").ToLower() == "server")
|
||||||
|
{
|
||||||
|
m_log.Warn("[OpenSim] In server mode. Should not initiate sync start. Ignore command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regionSyncConfig.GetString("Mode", "").ToLower() == "script_engine")
|
||||||
|
{
|
||||||
|
//if this is a remote script engine, proceed with following actions
|
||||||
|
string validSceneName = regionSyncConfig.GetString("ValidScriptEngineScene", "");
|
||||||
|
|
||||||
|
if (!validSceneName.Equals(""))
|
||||||
|
{
|
||||||
|
Scene validScene;
|
||||||
|
m_sceneManager.TryGetScene(validSceneName, out validScene);
|
||||||
|
|
||||||
|
List<Scene> localScenes = m_sceneManager.Scenes;
|
||||||
|
//First, let the valid scene's SEToSceneConnector be aware of all local scenes.
|
||||||
|
//The SEToSceneConnector will also pass a reference to all other scenes, so that they can
|
||||||
|
//call the appropriate IsBorderCrossing().
|
||||||
|
validScene.EventManager.TriggerPopulateLocalSceneList(localScenes); //TO BE FINISHED
|
||||||
|
//validScene.EventManager.TriggerPopulateLocalSceneList(localScenes, cmdparams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion REGION SYNC
|
||||||
|
|
||||||
|
|
||||||
public override void ShutdownSpecific()
|
public override void ShutdownSpecific()
|
||||||
{
|
{
|
||||||
if (m_shutdownCommandsFile != String.Empty)
|
if (m_shutdownCommandsFile != String.Empty)
|
||||||
|
|
|
@ -411,6 +411,12 @@ namespace OpenSim
|
||||||
|
|
||||||
scene.StartTimer();
|
scene.StartTimer();
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
//For INonSharedRegionModule, there is no more PostInitialise(). So we trigger OnPostSceneCreation event here
|
||||||
|
//to let the Sync modules to do their work once all modules are loaded and scene has interfaces to all of them.
|
||||||
|
scene.EventManager.TriggerOnPostSceneCreation(scene);
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
return clientServer;
|
return clientServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,12 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
{
|
{
|
||||||
Queue<OSD> queue = GetQueue(avatarID);
|
Queue<OSD> queue = GetQueue(avatarID);
|
||||||
if (queue != null)
|
if (queue != null)
|
||||||
queue.Enqueue(ev);
|
{
|
||||||
|
lock (queue)
|
||||||
|
{
|
||||||
|
queue.Enqueue(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(NullReferenceException e)
|
catch(NullReferenceException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,7 @@ using OSD = OpenMetaverse.StructuredData.OSD;
|
||||||
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
|
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
|
||||||
using OpenSim.Framework.Capabilities;
|
using OpenSim.Framework.Capabilities;
|
||||||
using ExtraParamType = OpenMetaverse.ExtraParamType;
|
using ExtraParamType = OpenMetaverse.ExtraParamType;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OpenSim.Region.ClientStack.Linden
|
namespace OpenSim.Region.ClientStack.Linden
|
||||||
{
|
{
|
||||||
|
@ -350,7 +351,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
rootGroup.LinkToGroup(allparts[j]);
|
rootGroup.LinkToGroup(allparts[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
rootGroup.ScheduleGroupForFullUpdate();
|
//rootGroup.ScheduleGroupForFullUpdate();
|
||||||
|
rootGroup.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate}); //seems like new object
|
||||||
pos
|
pos
|
||||||
= m_scene.GetNewRezLocation(
|
= m_scene.GetNewRezLocation(
|
||||||
Vector3.Zero, rootpos, UUID.Zero, rot, (byte)1, 1, true, allparts[0].GroupScale, false);
|
Vector3.Zero, rootpos, UUID.Zero, rot, (byte)1, 1, true, allparts[0].GroupScale, false);
|
||||||
|
@ -371,4 +373,4 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
return String.Format("<binary encoding=\"base64\">{0}</binary>", Convert.ToBase64String(resultbytes));
|
return String.Format("<binary encoding=\"base64\">{0}</binary>", Convert.ToBase64String(resultbytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -48,6 +49,7 @@ using OpenSim.Services.Interfaces;
|
||||||
using Timer = System.Timers.Timer;
|
using Timer = System.Timers.Timer;
|
||||||
using AssetLandmark = OpenSim.Framework.AssetLandmark;
|
using AssetLandmark = OpenSim.Framework.AssetLandmark;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
@ -76,6 +78,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public event ViewerEffectEventHandler OnViewerEffect;
|
public event ViewerEffectEventHandler OnViewerEffect;
|
||||||
public event ImprovedInstantMessage OnInstantMessage;
|
public event ImprovedInstantMessage OnInstantMessage;
|
||||||
public event ChatMessage OnChatFromClient;
|
public event ChatMessage OnChatFromClient;
|
||||||
|
public event ChatMessageRaw OnChatFromClientRaw;
|
||||||
public event TextureRequest OnRequestTexture;
|
public event TextureRequest OnRequestTexture;
|
||||||
public event RezObject OnRezObject;
|
public event RezObject OnRezObject;
|
||||||
public event DeRezObject OnDeRezObject;
|
public event DeRezObject OnDeRezObject;
|
||||||
|
@ -93,6 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public event GenericCall1 OnCompleteMovementToRegion;
|
public event GenericCall1 OnCompleteMovementToRegion;
|
||||||
public event UpdateAgent OnPreAgentUpdate;
|
public event UpdateAgent OnPreAgentUpdate;
|
||||||
public event UpdateAgent OnAgentUpdate;
|
public event UpdateAgent OnAgentUpdate;
|
||||||
|
public event UpdateAgentRaw OnAgentUpdateRaw;
|
||||||
public event AgentRequestSit OnAgentRequestSit;
|
public event AgentRequestSit OnAgentRequestSit;
|
||||||
public event AgentSit OnAgentSit;
|
public event AgentSit OnAgentSit;
|
||||||
public event AvatarPickerRequest OnAvatarPickerRequest;
|
public event AvatarPickerRequest OnAvatarPickerRequest;
|
||||||
|
@ -139,6 +143,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public event RequestMapBlocks OnRequestMapBlocks;
|
public event RequestMapBlocks OnRequestMapBlocks;
|
||||||
public event RequestMapName OnMapNameRequest;
|
public event RequestMapName OnMapNameRequest;
|
||||||
public event TeleportLocationRequest OnTeleportLocationRequest;
|
public event TeleportLocationRequest OnTeleportLocationRequest;
|
||||||
|
//DSG:
|
||||||
|
public event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
|
||||||
|
//end of DSG
|
||||||
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
|
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
|
||||||
public event DisconnectUser OnDisconnectUser;
|
public event DisconnectUser OnDisconnectUser;
|
||||||
public event RequestAvatarProperties OnRequestAvatarProperties;
|
public event RequestAvatarProperties OnRequestAvatarProperties;
|
||||||
|
@ -300,6 +307,73 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
|
/// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
|
||||||
private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
|
private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
|
||||||
|
|
||||||
|
// First log file or time has expired, start writing to a new log file
|
||||||
|
//<MIC>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public class QueueLogger
|
||||||
|
{
|
||||||
|
public Int32 start = 0;
|
||||||
|
public StreamWriter Log = null;
|
||||||
|
private Dictionary<UUID,int> m_idMap = new Dictionary<UUID,int>();
|
||||||
|
|
||||||
|
public QueueLogger()
|
||||||
|
{
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
String fname = String.Format("queue-{0}.log", now.ToString("yyyyMMddHHmmss"));
|
||||||
|
Log = new StreamWriter(fname);
|
||||||
|
|
||||||
|
start = Util.EnvironmentTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int LookupID(UUID uuid)
|
||||||
|
{
|
||||||
|
int localid;
|
||||||
|
if (! m_idMap.TryGetValue(uuid,out localid))
|
||||||
|
{
|
||||||
|
localid = m_idMap.Count + 1;
|
||||||
|
m_idMap[uuid] = localid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return localid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QueueLogger QueueLog = null;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void LogAvatarUpdateEvent(UUID client, UUID avatar)
|
||||||
|
{
|
||||||
|
if (QueueLog == null)
|
||||||
|
QueueLog = new QueueLogger();
|
||||||
|
|
||||||
|
Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
|
||||||
|
lock(QueueLog)
|
||||||
|
{
|
||||||
|
int cid = QueueLog.LookupID(client);
|
||||||
|
int aid = QueueLog.LookupID(avatar);
|
||||||
|
QueueLog.Log.WriteLine("{0},AU,AV{1:D4},AV{2:D4}",ticks,cid,aid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void LogQueueProcessEvent(UUID client, PriorityQueue queue, uint maxup)
|
||||||
|
{
|
||||||
|
if (QueueLog == null)
|
||||||
|
QueueLog = new QueueLogger();
|
||||||
|
|
||||||
|
Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
|
||||||
|
lock(QueueLog)
|
||||||
|
{
|
||||||
|
int cid = QueueLog.LookupID(client);
|
||||||
|
QueueLog.Log.WriteLine("{0},PQ,AV{1:D4},{2},{3}",ticks,cid,queue.Count,maxup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//</MIC>
|
||||||
|
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
|
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
|
||||||
|
|
||||||
|
@ -340,7 +414,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private int m_moneyBalance;
|
private int m_moneyBalance;
|
||||||
private int m_animationSequenceNumber = 1;
|
private int m_animationSequenceNumber = 1;
|
||||||
private bool m_SendLogoutPacketWhenClosing = true;
|
private bool m_SendLogoutPacketWhenClosing = true;
|
||||||
private AgentUpdateArgs lastarg;
|
private byte[] m_lastAgentUpdate;
|
||||||
private bool m_IsActive = true;
|
private bool m_IsActive = true;
|
||||||
private bool m_IsLoggingOut = false;
|
private bool m_IsLoggingOut = false;
|
||||||
|
|
||||||
|
@ -426,6 +500,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
|
public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
|
||||||
|
|
||||||
|
public uint MaxCoarseLocations { get { return 60; } }
|
||||||
|
|
||||||
#endregion Properties
|
#endregion Properties
|
||||||
|
|
||||||
// ~LLClientView()
|
// ~LLClientView()
|
||||||
|
@ -3433,6 +3509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
public void SendWearables(AvatarWearable[] wearables, int serial)
|
public void SendWearables(AvatarWearable[] wearables, int serial)
|
||||||
{
|
{
|
||||||
|
//m_log.WarnFormat("[LLCLIENTVIEW] Sending wearables to {0}", Name);
|
||||||
AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate);
|
AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate);
|
||||||
aw.AgentData.AgentID = AgentId;
|
aw.AgentData.AgentID = AgentId;
|
||||||
aw.AgentData.SerialNum = (uint)serial;
|
aw.AgentData.SerialNum = (uint)serial;
|
||||||
|
@ -3552,7 +3629,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
// Each packet can only hold around 60 avatar positions and the client clears the mini-map each time
|
// Each packet can only hold around 60 avatar positions and the client clears the mini-map each time
|
||||||
// a CoarseLocationUpdate packet is received. Oh well.
|
// a CoarseLocationUpdate packet is received. Oh well.
|
||||||
int total = Math.Min(CoarseLocations.Count, 60);
|
int total = Math.Min(CoarseLocations.Count, (int)MaxCoarseLocations);
|
||||||
|
|
||||||
CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock();
|
CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock();
|
||||||
|
|
||||||
|
@ -3659,6 +3736,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
int updatesThisCall = 0;
|
int updatesThisCall = 0;
|
||||||
|
|
||||||
|
//LogQueueProcessEvent(this.m_agentId,m_entityUpdates,m_maxUpdates);
|
||||||
|
|
||||||
// We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
|
// We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
|
||||||
// condition where a kill can be processed before an out-of-date update for the same object.
|
// condition where a kill can be processed before an out-of-date update for the same object.
|
||||||
lock (m_killRecord)
|
lock (m_killRecord)
|
||||||
|
@ -3762,6 +3841,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
#endregion UpdateFlags to packet type conversion
|
#endregion UpdateFlags to packet type conversion
|
||||||
|
|
||||||
#region Block Construction
|
#region Block Construction
|
||||||
|
|
||||||
|
//if (update.Entity is ScenePresence)
|
||||||
|
//LogAvatarUpdateEvent(this.m_agentId,update.Entity.UUID);
|
||||||
|
|
||||||
// TODO: Remove this once we can build compressed updates
|
// TODO: Remove this once we can build compressed updates
|
||||||
canUseCompressed = false;
|
canUseCompressed = false;
|
||||||
|
@ -5274,9 +5356,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
|
private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
|
||||||
{
|
{
|
||||||
if (OnAgentUpdate != null)
|
if (OnAgentUpdate != null || OnAgentUpdateRaw != null)
|
||||||
{
|
{
|
||||||
bool update = false;
|
|
||||||
AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
|
AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
|
||||||
|
|
||||||
#region Packet Session and User Check
|
#region Packet Session and User Check
|
||||||
|
@ -5285,61 +5366,76 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
|
AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
|
||||||
|
byte[] xb = new byte[x.Length];
|
||||||
|
int i = 0;
|
||||||
|
x.ToBytes(xb, ref i);
|
||||||
|
|
||||||
// We can only check when we have something to check
|
|
||||||
// against.
|
// If there was a previous update and this update is exactly the same, skip it
|
||||||
|
if (m_scene.IsSyncedClient() && m_lastAgentUpdate != null && Enumerable.SequenceEqual(xb, m_lastAgentUpdate))
|
||||||
if (lastarg != null)
|
|
||||||
{
|
{
|
||||||
update =
|
//m_log.Warn("LLClientView: HandleAgentUpdate (IDENTICAL TO LAST)");
|
||||||
(
|
return true;
|
||||||
(x.BodyRotation != lastarg.BodyRotation) ||
|
|
||||||
(x.CameraAtAxis != lastarg.CameraAtAxis) ||
|
|
||||||
(x.CameraCenter != lastarg.CameraCenter) ||
|
|
||||||
(x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
|
|
||||||
(x.CameraUpAxis != lastarg.CameraUpAxis) ||
|
|
||||||
(x.ControlFlags != lastarg.ControlFlags) ||
|
|
||||||
(x.Far != lastarg.Far) ||
|
|
||||||
(x.Flags != lastarg.Flags) ||
|
|
||||||
(x.State != lastarg.State) ||
|
|
||||||
(x.HeadRotation != lastarg.HeadRotation) ||
|
|
||||||
(x.SessionID != lastarg.SessionID) ||
|
|
||||||
(x.AgentID != lastarg.AgentID)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
update = true;
|
// What is different?? (only interesting for client managers)
|
||||||
|
/*
|
||||||
// These should be ordered from most-likely to
|
if(m_scene.IsSyncedClient() && m_lastAgentUpdate != null)
|
||||||
// least likely to change. I've made an initial
|
|
||||||
// guess at that.
|
|
||||||
|
|
||||||
if (update)
|
|
||||||
{
|
{
|
||||||
AgentUpdateArgs arg = new AgentUpdateArgs();
|
AgentUpdatePacket.AgentDataBlock lastarg = new AgentUpdatePacket.AgentDataBlock();
|
||||||
arg.AgentID = x.AgentID;
|
i = 0;
|
||||||
arg.BodyRotation = x.BodyRotation;
|
lastarg.FromBytes(m_lastAgentUpdate, ref i);
|
||||||
arg.CameraAtAxis = x.CameraAtAxis;
|
m_log.WarnFormat("LLClientView: HandleAgentUpdate |{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}|",
|
||||||
arg.CameraCenter = x.CameraCenter;
|
(x.BodyRotation != lastarg.BodyRotation) ? "X" : " ",
|
||||||
arg.CameraLeftAxis = x.CameraLeftAxis;
|
(x.CameraAtAxis != lastarg.CameraAtAxis) ? "X" : " ",
|
||||||
arg.CameraUpAxis = x.CameraUpAxis;
|
(x.CameraCenter != lastarg.CameraCenter) ? "X" : " ",
|
||||||
arg.ControlFlags = x.ControlFlags;
|
(x.CameraLeftAxis != lastarg.CameraLeftAxis) ? "X" : " ",
|
||||||
arg.Far = x.Far;
|
(x.CameraUpAxis != lastarg.CameraUpAxis) ? "X" : " ",
|
||||||
arg.Flags = x.Flags;
|
(x.ControlFlags != lastarg.ControlFlags) ? "X" : " ",
|
||||||
arg.HeadRotation = x.HeadRotation;
|
(x.Far != lastarg.Far) ? "X" : " ",
|
||||||
arg.SessionID = x.SessionID;
|
(x.Flags != lastarg.Flags) ? "X" : " ",
|
||||||
arg.State = x.State;
|
(x.State != lastarg.State) ? "X" : " ",
|
||||||
UpdateAgent handlerAgentUpdate = OnAgentUpdate;
|
(x.HeadRotation != lastarg.HeadRotation) ? "X" : " ",
|
||||||
UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
|
(x.SessionID != lastarg.SessionID) ? "X" : " ",
|
||||||
lastarg = arg; // save this set of arguments for nexttime
|
(x.AgentID != lastarg.AgentID) ? "X" : " ");
|
||||||
if (handlerPreAgentUpdate != null)
|
|
||||||
OnPreAgentUpdate(this, arg);
|
|
||||||
if (handlerAgentUpdate != null)
|
|
||||||
OnAgentUpdate(this, arg);
|
|
||||||
|
|
||||||
handlerAgentUpdate = null;
|
|
||||||
handlerPreAgentUpdate = null;
|
|
||||||
}
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
|
// save this set of arguments for next time
|
||||||
|
m_lastAgentUpdate = xb;
|
||||||
|
|
||||||
|
// If we have a raw handler, call it
|
||||||
|
UpdateAgentRaw handlerAgentUpdateRaw = OnAgentUpdateRaw;
|
||||||
|
if (handlerAgentUpdateRaw != null)
|
||||||
|
{
|
||||||
|
handlerAgentUpdateRaw(this, xb);
|
||||||
|
handlerAgentUpdateRaw = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AgentUpdateArgs arg = new AgentUpdateArgs();
|
||||||
|
arg.AgentID = x.AgentID;
|
||||||
|
arg.BodyRotation = x.BodyRotation;
|
||||||
|
arg.CameraAtAxis = x.CameraAtAxis;
|
||||||
|
arg.CameraCenter = x.CameraCenter;
|
||||||
|
arg.CameraLeftAxis = x.CameraLeftAxis;
|
||||||
|
arg.CameraUpAxis = x.CameraUpAxis;
|
||||||
|
arg.ControlFlags = x.ControlFlags;
|
||||||
|
arg.Far = x.Far;
|
||||||
|
arg.Flags = x.Flags;
|
||||||
|
arg.HeadRotation = x.HeadRotation;
|
||||||
|
arg.SessionID = x.SessionID;
|
||||||
|
arg.State = x.State;
|
||||||
|
|
||||||
|
UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
|
||||||
|
UpdateAgent handlerAgentUpdate = OnAgentUpdate;
|
||||||
|
if (handlerPreAgentUpdate != null)
|
||||||
|
OnPreAgentUpdate(this, arg);
|
||||||
|
if (handlerAgentUpdate != null)
|
||||||
|
OnAgentUpdate(this, arg);
|
||||||
|
|
||||||
|
handlerPreAgentUpdate = null;
|
||||||
|
handlerAgentUpdate = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -5596,6 +5692,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
int channel = inchatpack.ChatData.Channel;
|
int channel = inchatpack.ChatData.Channel;
|
||||||
|
|
||||||
|
// If we have a raw handler, call it
|
||||||
|
ChatMessageRaw handlerChatFromClientRaw = OnChatFromClientRaw;
|
||||||
|
if (handlerChatFromClientRaw != null)
|
||||||
|
{
|
||||||
|
ChatFromViewerPacket.ChatDataBlock x = inchatpack.ChatData;
|
||||||
|
byte[] xb = new byte[x.Length];
|
||||||
|
int i = 0;
|
||||||
|
x.ToBytes(xb, ref i);
|
||||||
|
|
||||||
|
handlerChatFromClientRaw(this, xb);
|
||||||
|
handlerChatFromClientRaw = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (OnChatFromClient != null)
|
if (OnChatFromClient != null)
|
||||||
{
|
{
|
||||||
OSChatMessage args = new OSChatMessage();
|
OSChatMessage args = new OSChatMessage();
|
||||||
|
@ -5970,14 +6079,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
SetAppearance handlerSetAppearance = OnSetAppearance;
|
SetAppearance handlerSetAppearance = OnSetAppearance;
|
||||||
if (handlerSetAppearance != null)
|
//if (handlerSetAppearance != null)
|
||||||
{
|
{
|
||||||
// Temporarily protect ourselves from the mantis #951 failure.
|
// Temporarily protect ourselves from the mantis #951 failure.
|
||||||
// However, we could do this for several other handlers where a failure isn't terminal
|
// However, we could do this for several other handlers where a failure isn't terminal
|
||||||
// for the client session anyway, in order to protect ourselves against bad code in plugins
|
// for the client session anyway, in order to protect ourselves against bad code in plugins
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
byte[] visualparams = new byte[appear.VisualParam.Length];
|
byte[] visualparams = new byte[appear.VisualParam.Length];
|
||||||
for (int i = 0; i < appear.VisualParam.Length; i++)
|
for (int i = 0; i < appear.VisualParam.Length; i++)
|
||||||
visualparams[i] = appear.VisualParam[i].ParamValue;
|
visualparams[i] = appear.VisualParam[i].ParamValue;
|
||||||
|
@ -8415,6 +8523,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
|
TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
|
||||||
|
|
||||||
|
//DSG: KittyL -- added to support same region teleport
|
||||||
|
if (tpLocReq.Info.RegionHandle == m_scene.RegionInfo.RegionHandle)
|
||||||
|
{
|
||||||
|
SameRegionTeleportlRequest handlerSameRegionTeleportlRequest = OnSameRegionTeleportlRequest;
|
||||||
|
if (handlerSameRegionTeleportlRequest != null)
|
||||||
|
{
|
||||||
|
byte[] xb = new byte[tpLocReq.Length];
|
||||||
|
int i = 0;
|
||||||
|
xb = tpLocReq.ToBytes();
|
||||||
|
handlerSameRegionTeleportlRequest(this, xb);
|
||||||
|
//return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (handlerTeleportLocationRequest != null)
|
if (handlerTeleportLocationRequest != null)
|
||||||
{
|
{
|
||||||
handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
|
handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
|
||||||
|
|
|
@ -924,6 +924,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
|
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
|
||||||
{
|
{
|
||||||
|
// REGION SYNC (Load Balancing)
|
||||||
|
//ScenePresence presence;
|
||||||
|
//m_scene.TryGetScenePresence(agentID, out presence);
|
||||||
|
//bool syncedAvatar = (presence != null && presence.IsSyncedAvatar);
|
||||||
|
|
||||||
// In priciple there shouldn't be more than one thread here, ever.
|
// In priciple there shouldn't be more than one thread here, ever.
|
||||||
// But in case that happens, we need to synchronize this piece of code
|
// But in case that happens, we need to synchronize this piece of code
|
||||||
// because it's too important
|
// because it's too important
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
using System;
|
using System;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
|
|
|
@ -475,6 +475,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
group.HasGroupChanged = true;
|
group.HasGroupChanged = true;
|
||||||
|
|
||||||
UpdateKnownItem(remoteClient, group, group.GetFromItemID(), group.OwnerID);
|
UpdateKnownItem(remoteClient, group, group.GetFromItemID(), group.OwnerID);
|
||||||
|
|
||||||
m_scene.DeleteSceneObject(group, false);
|
m_scene.DeleteSceneObject(group, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -609,7 +610,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
}
|
}
|
||||||
|
|
||||||
so.IsSelected = false; // fudge....
|
so.IsSelected = false; // fudge....
|
||||||
so.ScheduleGroupForFullUpdate();
|
//so.ScheduleGroupForFullUpdate();
|
||||||
|
so.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate}); //just force it to sychronize all properties
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case it is later dropped again, don't let
|
// In case it is later dropped again, don't let
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
{
|
{
|
||||||
m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
|
m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
|
||||||
m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
|
m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
|
||||||
// m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
|
m_log.WarnFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,8 +261,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void QueueAppearanceSend(UUID agentid)
|
public void QueueAppearanceSend(UUID agentid)
|
||||||
{
|
{
|
||||||
// m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
|
|
||||||
|
|
||||||
// 10000 ticks per millisecond, 1000 milliseconds per second
|
// 10000 ticks per millisecond, 1000 milliseconds per second
|
||||||
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
|
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
|
||||||
lock (m_sendqueue)
|
lock (m_sendqueue)
|
||||||
|
@ -270,6 +268,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
m_sendqueue[agentid] = timestamp;
|
m_sendqueue[agentid] = timestamp;
|
||||||
m_updateTimer.Start();
|
m_updateTimer.Start();
|
||||||
}
|
}
|
||||||
|
//m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0} at {1} (now is {2})", agentid, timestamp,DateTime.Now.Ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueAppearanceSave(UUID agentid)
|
public void QueueAppearanceSave(UUID agentid)
|
||||||
|
@ -285,6 +284,58 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RefreshAppearance(UUID agentid)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[AVFACTORY]: FireAndForget called for RefreshAppearance on agentid {0}", agentid);
|
||||||
|
Util.FireAndForget(delegate(object o)
|
||||||
|
{
|
||||||
|
int maxtries = 10;
|
||||||
|
int trycount = maxtries;
|
||||||
|
int interval = 5000;
|
||||||
|
ScenePresence sp;
|
||||||
|
while (!m_scene.TryGetScenePresence(agentid, out sp))
|
||||||
|
{
|
||||||
|
//m_log.WarnFormat("[AVFACTORY]: RefreshAppearance unable to find presence for {0}", agentid);
|
||||||
|
Thread.Sleep(interval);
|
||||||
|
if (trycount-- <= 0)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[AVFACTORY]: RefreshAppearance unable to find presence for {0} after {1} attempts at {2}ms intervals", agentid, maxtries, interval);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trycount = maxtries;
|
||||||
|
AvatarAppearance appearance = null;
|
||||||
|
while (appearance == null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
appearance = m_scene.AvatarService.GetAppearance(agentid);
|
||||||
|
}
|
||||||
|
catch (System.Net.WebException e)
|
||||||
|
{
|
||||||
|
if (trycount-- <= 0)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[AVFACTORY]: RefreshAppearance unable to get appearance from AvatarService for {0} after {1} attempts at {2}ms intervals: {3}", agentid, maxtries, interval, e.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Thread.Sleep(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appearance.Texture != null && appearance.VisualParams != null)
|
||||||
|
{
|
||||||
|
sp.Appearance = appearance;
|
||||||
|
if (sp.Appearance.AvatarHeight > 0)
|
||||||
|
sp.SetHeight(sp.Appearance.AvatarHeight);
|
||||||
|
QueueAppearanceSend(agentid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[AVFACTORY]: RefreshAppearance received null appearance data from grid for {0}", agentid);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleAppearanceSend(UUID agentid)
|
private void HandleAppearanceSend(UUID agentid)
|
||||||
{
|
{
|
||||||
ScenePresence sp = m_scene.GetScenePresence(agentid);
|
ScenePresence sp = m_scene.GetScenePresence(agentid);
|
||||||
|
@ -311,10 +362,18 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
|
m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (sp.IsSyncedAvatar)
|
||||||
|
return;
|
||||||
|
|
||||||
// m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
|
// m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
|
||||||
|
|
||||||
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
|
// Disable saving of appearance for demonstrations
|
||||||
|
// m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
|
||||||
|
// REGION SYNC
|
||||||
|
// If this is a client manager, we have received new appearance from a client and saved
|
||||||
|
// it to the avatar service. Now let's tell the parent scene about it.
|
||||||
|
if (m_scene.IsSyncedClient())
|
||||||
|
m_scene.RegionSyncClientModule.SendAppearanceToScene(agentid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
|
private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
|
||||||
|
@ -328,6 +387,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
{
|
{
|
||||||
if (kvp.Value < now)
|
if (kvp.Value < now)
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat("[AVFACTORY]: send appearance for {0} at time {1}", kvp.Key, now);
|
||||||
Util.FireAndForget(delegate(object o) { HandleAppearanceSend(kvp.Key); });
|
Util.FireAndForget(delegate(object o) { HandleAppearanceSend(kvp.Key); });
|
||||||
m_sendqueue.Remove(kvp.Key);
|
m_sendqueue.Remove(kvp.Key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,16 @@ using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Services.Interfaces;
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
//DSG
|
||||||
|
using Nwc.XmlRpc;
|
||||||
|
using System.Net;
|
||||||
|
using System.Collections;
|
||||||
|
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||||
|
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.Avatar.Dialog
|
namespace OpenSim.Region.CoreModules.Avatar.Dialog
|
||||||
{
|
{
|
||||||
public class DialogModule : IRegionModule, IDialogModule
|
public class DialogModule : IRegionModule, IDialogModule
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
|
|
@ -222,6 +222,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//DSG: make this function public, so that we can call from outside to
|
||||||
|
//use the Grid Service to send the instant message.
|
||||||
|
public virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID)
|
protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID)
|
||||||
|
|
|
@ -446,7 +446,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
|
//protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
|
||||||
|
//DSG: make this function public, so that we can call from outside to
|
||||||
|
//use the Grid Service to send the instant message.
|
||||||
|
public virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
|
||||||
{
|
{
|
||||||
GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync;
|
GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync;
|
||||||
|
|
||||||
|
@ -533,8 +536,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||||
|
|
||||||
if (upd != null)
|
if (upd != null)
|
||||||
{
|
{
|
||||||
GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID,
|
GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID);
|
||||||
upd.RegionID);
|
|
||||||
|
// If we found the reginfo, send the IM to the region
|
||||||
if (reginfo != null)
|
if (reginfo != null)
|
||||||
{
|
{
|
||||||
Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
|
Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
|
||||||
|
@ -623,6 +627,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), reginfo.ServerURI.ToString());
|
m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), reginfo.ServerURI.ToString());
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error doIMSending to {0}, Error Message -- {1} ", reginfo.ServerURI.ToString(), e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1363,6 +1363,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
protected List<GridRegion> RequestNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
|
protected List<GridRegion> RequestNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
|
||||||
{
|
{
|
||||||
Scene pScene = avatar.Scene;
|
Scene pScene = avatar.Scene;
|
||||||
|
m_log.DebugFormat("[ENTITY TRANSFER MODULE] Request neighbors for {0} at {1}/{2}",
|
||||||
|
pScene.RegionInfo.RegionName, pRegionLocX, pRegionLocY);
|
||||||
RegionInfo m_regionInfo = pScene.RegionInfo;
|
RegionInfo m_regionInfo = pScene.RegionInfo;
|
||||||
|
|
||||||
Border[] northBorders = pScene.NorthBorders.ToArray();
|
Border[] northBorders = pScene.NorthBorders.ToArray();
|
||||||
|
@ -1682,7 +1684,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, silent))
|
if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, silent))
|
||||||
{
|
{
|
||||||
grp.OffsetForNewRegion(oldGroupPosition);
|
grp.OffsetForNewRegion(oldGroupPosition);
|
||||||
grp.ScheduleGroupForFullUpdate();
|
//grp.ScheduleGroupForFullUpdate();
|
||||||
|
grp.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.GroupPosition});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -692,8 +692,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
|
UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
|
||||||
bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
|
bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
|
// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
|
||||||
|
|
||||||
byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
|
byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
|
||||||
Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
|
Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
|
||||||
Vector3 pos = m_Scene.GetNewRezLocation(
|
Vector3 pos = m_Scene.GetNewRezLocation(
|
||||||
|
@ -779,15 +779,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
itemId, n.OuterXml);
|
itemId, n.OuterXml);
|
||||||
objlist.Add(g);
|
objlist.Add(g);
|
||||||
XmlElement el = (XmlElement)n;
|
XmlElement el = (XmlElement)n;
|
||||||
|
|
||||||
string rawX = el.GetAttribute("offsetx");
|
string rawX = el.GetAttribute("offsetx");
|
||||||
string rawY = el.GetAttribute("offsety");
|
string rawY = el.GetAttribute("offsety");
|
||||||
string rawZ = el.GetAttribute("offsetz");
|
string rawZ = el.GetAttribute("offsetz");
|
||||||
//
|
//
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
|
// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
|
||||||
// g.Name, rawX, rawY, rawZ);
|
// g.Name, rawX, rawY, rawZ);
|
||||||
|
|
||||||
float x = Convert.ToSingle(rawX);
|
float x = Convert.ToSingle(rawX);
|
||||||
float y = Convert.ToSingle(rawY);
|
float y = Convert.ToSingle(rawY);
|
||||||
float z = Convert.ToSingle(rawZ);
|
float z = Convert.ToSingle(rawZ);
|
||||||
|
@ -814,7 +814,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0 ; i < objlist.Count; i++)
|
for (int i = 0; i < objlist.Count; i++)
|
||||||
{
|
{
|
||||||
group = objlist[i];
|
group = objlist[i];
|
||||||
|
|
||||||
|
@ -850,14 +850,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
// one full update during the attachment
|
// one full update during the attachment
|
||||||
// process causes some clients to fail to display the
|
// process causes some clients to fail to display the
|
||||||
// attachment properly.
|
// attachment properly.
|
||||||
m_Scene.AddNewSceneObject(group, true, false);
|
//m_Scene.AddNewSceneObject(group, true, false);
|
||||||
|
//DSG SYNC: tell RegionSyncModule not to call SyncNewObject
|
||||||
|
// yet, as not all properties have been set yet
|
||||||
|
bool triggerSyncNewObject = false;
|
||||||
|
m_Scene.AddNewSceneObjectByRez(group, true, false, triggerSyncNewObject);
|
||||||
|
|
||||||
// if attachment we set it's asset id so object updates
|
// if attachment we set it's asset id so object updates
|
||||||
// can reflect that, if not, we set it's position in world.
|
// can reflect that, if not, we set it's position in world.
|
||||||
if (!attachment)
|
if (!attachment)
|
||||||
{
|
{
|
||||||
group.ScheduleGroupForFullUpdate();
|
group.ScheduleGroupForFullUpdate(null);
|
||||||
|
|
||||||
group.AbsolutePosition = pos + veclist[i];
|
group.AbsolutePosition = pos + veclist[i];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -914,7 +918,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
}
|
}
|
||||||
part.GroupMask = 0; // DO NOT propagate here
|
part.GroupMask = 0; // DO NOT propagate here
|
||||||
}
|
}
|
||||||
|
|
||||||
group.ApplyNextOwnerPermissions();
|
group.ApplyNextOwnerPermissions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -939,12 +943,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
{
|
{
|
||||||
if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
|
if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
|
||||||
group.ClearPartAttachmentData();
|
group.ClearPartAttachmentData();
|
||||||
|
|
||||||
// Fire on_rez
|
// Fire on_rez
|
||||||
group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
|
group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
|
||||||
rootPart.ParentGroup.ResumeScripts();
|
rootPart.ParentGroup.ResumeScripts();
|
||||||
|
rootPart.ScheduleFullUpdate(null);
|
||||||
rootPart.ScheduleFullUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,6 +966,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DSG SYNC: now all properties have been set, sending NewObject message,
|
||||||
|
if (m_Scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
m_Scene.RegionSyncModule.SyncNewObject(group);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
@ -970,6 +979,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void AddUserData(SceneObjectGroup sog)
|
protected void AddUserData(SceneObjectGroup sog)
|
||||||
{
|
{
|
||||||
UserManagementModule.AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);
|
UserManagementModule.AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);
|
||||||
|
@ -1072,4 +1082,4 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
// Class queues updates for UUID's.
|
||||||
|
// The updates could be JSON, serialized object data, or any string.
|
||||||
|
// Updates are queued to the end and dequeued from the front of the queue
|
||||||
|
// Enqueuing an update with the same UUID will replace the previous update
|
||||||
|
// so it will not lose its place.
|
||||||
|
class BlockingUpdateQueue
|
||||||
|
{
|
||||||
|
private object m_syncRoot = new object();
|
||||||
|
private Queue<UUID> m_queue = new Queue<UUID>();
|
||||||
|
private Dictionary<UUID, byte[]> m_updates = new Dictionary<UUID, byte[]>();
|
||||||
|
|
||||||
|
// Enqueue an update
|
||||||
|
public void Enqueue(UUID id, byte[] update)
|
||||||
|
{
|
||||||
|
lock(m_syncRoot)
|
||||||
|
{
|
||||||
|
if (!m_updates.ContainsKey(id))
|
||||||
|
m_queue.Enqueue(id);
|
||||||
|
m_updates[id] = update;
|
||||||
|
Monitor.Pulse(m_syncRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dequeue an update
|
||||||
|
public byte[] Dequeue()
|
||||||
|
{
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
// If the queue is empty, wait for it to contain something
|
||||||
|
while (m_queue.Count == 0)
|
||||||
|
Monitor.Wait(m_syncRoot);
|
||||||
|
UUID id = m_queue.Dequeue();
|
||||||
|
byte[] update = m_updates[id];
|
||||||
|
m_updates.Remove(id);
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count of number of items currently queued
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (m_syncRoot)
|
||||||
|
return m_queue.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using log4net;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
class DSGClientManagerLoadBalancer
|
||||||
|
{
|
||||||
|
private List<RegionSyncClientView> m_cvs = new List<RegionSyncClientView>();
|
||||||
|
private ILog m_log;
|
||||||
|
private int m_maxClientsPerClientManager;
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
// The list of clients and the threads handling IO for each client
|
||||||
|
// The list is read most of the time and only updated when a new client manager
|
||||||
|
// connects, so we just replace the list when it changes. Iterators on this
|
||||||
|
// list need to be able to handle if an element is shutting down.
|
||||||
|
private object m_clientview_lock = new object();
|
||||||
|
private HashSet<RegionSyncClientView> m_client_views = new HashSet<RegionSyncClientView>();
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return m_client_views.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReportStats(System.IO.TextWriter tw)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DSGClientManagerLoadBalancer(int maxClientsPerClientManager, Scene scene)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
m_maxClientsPerClientManager = maxClientsPerClientManager;
|
||||||
|
m_scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the client view to the list and increment synced client counter
|
||||||
|
public void AddSyncedClient(RegionSyncClientView rscv)
|
||||||
|
{
|
||||||
|
lock (m_clientview_lock)
|
||||||
|
{
|
||||||
|
HashSet<RegionSyncClientView> currentlist = m_client_views;
|
||||||
|
HashSet<RegionSyncClientView> newlist = new HashSet<RegionSyncClientView>(currentlist);
|
||||||
|
newlist.Add(rscv);
|
||||||
|
// Anyone holding the previous version of the list can keep using it since
|
||||||
|
// they will not hold it for long and get a new copy next time they need to iterate
|
||||||
|
m_client_views = newlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A CV is essentially requesting to be shut down.
|
||||||
|
// Other than a hard disconnect, this is the only way a CV will close its connection to CM
|
||||||
|
// Making this request prompts the balancer to shift all connected clients on that CM to another CM if one exists
|
||||||
|
// Remove the client view from the list and decrement synced client counter
|
||||||
|
public void RemoveSyncedClient(RegionSyncClientView rscv)
|
||||||
|
{
|
||||||
|
lock (m_clientview_lock)
|
||||||
|
{
|
||||||
|
HashSet<RegionSyncClientView> currentlist = m_client_views;
|
||||||
|
HashSet<RegionSyncClientView> newlist = new HashSet<RegionSyncClientView>(currentlist);
|
||||||
|
newlist.Remove(rscv);
|
||||||
|
// Anyone holding the previous version of the list can keep using it since
|
||||||
|
// they will not hold it for long and get a new copy next time they need to iterate
|
||||||
|
m_client_views = newlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForEachClientManager(Action<RegionSyncClientView> action)
|
||||||
|
{
|
||||||
|
foreach (RegionSyncClientView cv in m_client_views)
|
||||||
|
{
|
||||||
|
action(cv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BalanceLoad()
|
||||||
|
{
|
||||||
|
// If we have 1 - 10 agents connected, we are just testing things all. Move all of them to another region
|
||||||
|
if (m_scene.SceneGraph.GetRootAgentCount() > 0 && m_scene.SceneGraph.GetRootAgentCount() < 10)
|
||||||
|
{
|
||||||
|
SpecialRebalance();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Dictionary<RegionSyncClientView, int> avSourceRegionCounts = new Dictionary<RegionSyncClientView, int>();
|
||||||
|
KeyValuePair<RegionSyncClientView, int> destinationRegionCount = new KeyValuePair<RegionSyncClientView,int>(null, m_maxClientsPerClientManager);
|
||||||
|
foreach (RegionSyncClientView client in m_client_views)
|
||||||
|
{
|
||||||
|
int clientCount = client.SyncedAvCount;
|
||||||
|
if (clientCount > m_maxClientsPerClientManager)
|
||||||
|
{
|
||||||
|
avSourceRegionCounts.Add(client, clientCount);
|
||||||
|
}
|
||||||
|
else if (clientCount < destinationRegionCount.Value)
|
||||||
|
{
|
||||||
|
destinationRegionCount = new KeyValuePair<RegionSyncClientView, int>(client, clientCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now we should have a list of regions over the limit and a target region with the lowest number of clients
|
||||||
|
// Find average load of overloaded and least loaded regions
|
||||||
|
int currentLoad = 0;
|
||||||
|
foreach (KeyValuePair<RegionSyncClientView, int> kvp in avSourceRegionCounts)
|
||||||
|
currentLoad += kvp.Value;
|
||||||
|
currentLoad += destinationRegionCount.Value;
|
||||||
|
int targetLoad = (int)(currentLoad/(avSourceRegionCounts.Count + 1));
|
||||||
|
foreach (KeyValuePair<RegionSyncClientView, int> kvp in avSourceRegionCounts)
|
||||||
|
{
|
||||||
|
kvp.Key.BalanceClients(targetLoad, destinationRegionCount.Key.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SpecialRebalance()
|
||||||
|
{
|
||||||
|
m_log.Warn("[CLIENT LOAD BALANCER] Begin special rebalance.");
|
||||||
|
if (m_client_views.Count < 2)
|
||||||
|
{
|
||||||
|
m_log.Error("[CLIENT LOAD BALANCER] Could not special balance because there are not at least 2 client managers.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RegionSyncClientView src = null;
|
||||||
|
RegionSyncClientView dst = null;
|
||||||
|
// Find the one client
|
||||||
|
foreach (RegionSyncClientView client in m_client_views)
|
||||||
|
{
|
||||||
|
//m_log.WarnFormat("[CLIENT LOAD BALANCER] Client RSCV {0} SyncedAvCount = {1}.", client.Name, client.SyncedAvCount);
|
||||||
|
if (src != null && dst != null)
|
||||||
|
break;
|
||||||
|
// Find a src region with some avatars
|
||||||
|
if (src == null && client.SyncedAvCount > 0)
|
||||||
|
src = client;
|
||||||
|
// Find a dst region with no avatars
|
||||||
|
else if (dst == null && client.SyncedAvCount == 0)
|
||||||
|
dst = client;
|
||||||
|
}
|
||||||
|
if (src == null || dst == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[CLIENT LOAD BALANCER] Could not special balance because a src and dst client manager region could not be identified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send all clients from src to dst
|
||||||
|
m_log.WarnFormat("[CLIENT LOAD BALANCER] Moving all clients from client manager region {0} to region {1}", src.Name, dst.Name);
|
||||||
|
src.BalanceClients(0, dst.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,526 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.Packets;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Types;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
|
||||||
|
// The RegionSyncPhysEngine has a receive thread to process messages from the RegionSyncServer.
|
||||||
|
// It is the client side of the synchronization channel, and send to and receive updates from the
|
||||||
|
// Auth. Scene. The server side thread handling the sync channel is implemented in RegionSyncScriptAPI.cs.
|
||||||
|
//
|
||||||
|
// The current implementation is very similar to RegionSyncClient.
|
||||||
|
// TODO: eventually the same RegionSyncSceneAPI should handle all traffic from different actors, e.g.
|
||||||
|
// using a pub/sub model.
|
||||||
|
public class PhysEngineToSceneConnector
|
||||||
|
{
|
||||||
|
#region PhysEngineToSceneConnector members
|
||||||
|
|
||||||
|
// Set the addr and port of RegionSyncServer
|
||||||
|
private IPAddress m_addr;
|
||||||
|
private string m_addrString;
|
||||||
|
private Int32 m_port;
|
||||||
|
|
||||||
|
// A reference to the local scene
|
||||||
|
private Scene m_validLocalScene;
|
||||||
|
|
||||||
|
// The avatars added to this client manager for clients on other client managers
|
||||||
|
object m_syncRoot = new object();
|
||||||
|
|
||||||
|
// The logfile
|
||||||
|
private ILog m_log;
|
||||||
|
|
||||||
|
private string LogHeader = "[PHYSICS ENGINE TO SCENE CONNECTOR]";
|
||||||
|
|
||||||
|
// The listener and the thread which listens for connections from client managers
|
||||||
|
private Thread m_rcvLoop;
|
||||||
|
|
||||||
|
// The client connection to the RegionSyncServer
|
||||||
|
private TcpClient m_client = new TcpClient();
|
||||||
|
|
||||||
|
// The queue of incoming messages which need handling
|
||||||
|
//private Queue<string> m_inQ = new Queue<string>();
|
||||||
|
|
||||||
|
//KittyL: added to identify different actors
|
||||||
|
private ActorType m_actorType = ActorType.PhysicsEngine;
|
||||||
|
|
||||||
|
private bool m_debugWithViewer = false;
|
||||||
|
private long m_messagesSent = 0;
|
||||||
|
private long m_messagesReceived = 0;
|
||||||
|
|
||||||
|
private IConfig m_sysConfig;
|
||||||
|
|
||||||
|
//members for load balancing purpose
|
||||||
|
//private TcpClient m_loadMigrationSouceEnd = null;
|
||||||
|
//private LoadMigrationEndPoint m_loadMigrationSouceEnd = null;
|
||||||
|
private Thread m_loadMigrationSrcRcvLoop;
|
||||||
|
//private LoadMigrationListener m_loadMigrationListener = null;
|
||||||
|
|
||||||
|
//List of queued messages, when the space that the updated object is located is being migrated
|
||||||
|
private List<RegionSyncMessage> m_updateMsgQueue = new List<RegionSyncMessage>();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public PhysEngineToSceneConnector(Scene validLocalScene, string addr, int port, bool debugWithViewer,
|
||||||
|
IConfig sysConfig)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
m_validLocalScene = validLocalScene;
|
||||||
|
m_addr = IPAddress.Parse(addr);
|
||||||
|
m_addrString = addr;
|
||||||
|
m_port = port;
|
||||||
|
m_debugWithViewer = debugWithViewer;
|
||||||
|
m_sysConfig = sysConfig;
|
||||||
|
|
||||||
|
SceneToPhysEngineSyncServer.logEnabled = m_sysConfig.GetBoolean("PhysLogEnabled", false);
|
||||||
|
SceneToPhysEngineSyncServer.logDir = m_sysConfig.GetString("PhysLogDir", ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the RegionSyncPhysEngine client thread
|
||||||
|
public bool Start()
|
||||||
|
{
|
||||||
|
if (EstablishConnection())
|
||||||
|
{
|
||||||
|
StartStateSync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool EstablishConnection()
|
||||||
|
{
|
||||||
|
if (m_client.Connected)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": already connected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_client.Connect(m_addr, m_port);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} [Start] Could not connect to SceneToPhysEngineSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
|
||||||
|
m_log.Warn(e.Message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.WarnFormat("{0} Connected to SceneToPhysEngineSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
|
||||||
|
|
||||||
|
m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop));
|
||||||
|
m_rcvLoop.Name = "PhysEngineToSceneConnector ReceiveLoop";
|
||||||
|
m_log.WarnFormat("{0} Starting {1} thread", LogHeader, m_rcvLoop.Name);
|
||||||
|
m_rcvLoop.Start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartStateSync()
|
||||||
|
{
|
||||||
|
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStatus, Convert.ToString((int)ActorStatus.Sync));
|
||||||
|
Send(msg);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
DoInitialSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterIdle()
|
||||||
|
{
|
||||||
|
EstablishConnection();
|
||||||
|
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStatus, Convert.ToString((int)ActorStatus.Idle));
|
||||||
|
Send(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoInitialSync()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnect from the RegionSyncServer and close client thread
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStop, "stop"));
|
||||||
|
// The remote scene will remove the SceneToPhysEngineConnector when we disconnect
|
||||||
|
m_rcvLoop.Abort();
|
||||||
|
ShutdownClient();
|
||||||
|
|
||||||
|
//stop the migration connections
|
||||||
|
//ShutdownClient(m_loadMigrationSouceEnd);
|
||||||
|
//if (m_loadMigrationListener != null)
|
||||||
|
// m_loadMigrationListener.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReportStatus()
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Synchronized to RegionSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
|
||||||
|
m_log.WarnFormat("{0} Received={1}, Sent={2}", LogHeader, m_messagesReceived, m_messagesSent);
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
//TODO: should be reporting about the information of the objects/scripts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShutdownClient()
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Disconnected from RegionSyncServer. Shutting down.", LogHeader);
|
||||||
|
|
||||||
|
//TODO: remove the objects and scripts
|
||||||
|
//lock (m_syncRoot)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (m_client != null)
|
||||||
|
{
|
||||||
|
// Close the connection
|
||||||
|
m_client.Client.Close();
|
||||||
|
m_client.Close();
|
||||||
|
}
|
||||||
|
SceneToPhysEngineSyncServer.PhysLogMessageClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for messages from a RegionSyncServer
|
||||||
|
// *** This is the main thread loop for each connected client
|
||||||
|
private void ReceiveLoop()
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name);
|
||||||
|
while (true && m_client.Connected)
|
||||||
|
{
|
||||||
|
RegionSyncMessage msg;
|
||||||
|
// Try to get the message from the network stream
|
||||||
|
try
|
||||||
|
{
|
||||||
|
msg = new RegionSyncMessage(m_client.GetStream());
|
||||||
|
//m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString());
|
||||||
|
}
|
||||||
|
// If there is a problem reading from the client, shut 'er down.
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ShutdownClient();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Try handling the message
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//lock (m_syncRoot) -- KittyL: why do we need to lock here? We could lock inside HandleMessage if necessary, and lock on different objects for better performance
|
||||||
|
m_messagesReceived++;
|
||||||
|
HandleMessage(msg);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Encountered an exception: {1} (MSGTYPE = {2})", LogHeader, e.Message, msg.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region SEND
|
||||||
|
//DSG-TODO: for Scene based DSG, Send() also needs to figure out which Scene to send to, e.g. needs a switching function based on object position
|
||||||
|
|
||||||
|
// Send a message to a single connected RegionSyncServer
|
||||||
|
private void Send(string msg)
|
||||||
|
{
|
||||||
|
byte[] bmsg = System.Text.Encoding.ASCII.GetBytes(msg + System.Environment.NewLine);
|
||||||
|
Send(bmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Send(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
Send(msg.ToBytes());
|
||||||
|
//m_log.WarnFormat("{0} Sent {1}", LogHeader, msg.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Send(byte[] data)
|
||||||
|
{
|
||||||
|
if (m_client.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_client.GetStream().Write(data, 0, data.Length);
|
||||||
|
m_messagesSent++;
|
||||||
|
}
|
||||||
|
// If there is a problem reading from the client, shut 'er down.
|
||||||
|
// *** Still need to alert the module that it's no longer connected!
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ShutdownClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion SEND
|
||||||
|
|
||||||
|
//KittyL: Has to define SendCoarseLocations() here, since it's defined in IRegionSyncClientModule.
|
||||||
|
// But should not do much as being PhysEngine, not ClientManager
|
||||||
|
public void SendCoarseLocations()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle an incoming message
|
||||||
|
// Dan-TODO: This should not be synchronous with the receive!
|
||||||
|
// Instead, handle messages from an incoming Queue so server doesn't block sending
|
||||||
|
//
|
||||||
|
// KittyL: This is the function that PhysEngine and ClientManager have the most different implementations
|
||||||
|
private void HandleMessage(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
//TO FINISH:
|
||||||
|
|
||||||
|
SceneToPhysEngineSyncServer.PhysLogMessage(false, msg);
|
||||||
|
switch (msg.Type)
|
||||||
|
{
|
||||||
|
case RegionSyncMessage.MsgType.RegionName:
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.PhysUpdateAttributes:
|
||||||
|
{
|
||||||
|
HandlePhysUpdateAttributes(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, String.Format("{0} Unsupported message type: {1}", LogHeader, ((int)msg.Type).ToString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The physics engine has some updates to the attributes. Unpack the parameters, find the
|
||||||
|
/// correct PhysicsActor and plug in the new values;
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="msg"></param>
|
||||||
|
private void HandlePhysUpdateAttributes(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UUID uuid = data["uuid"].AsUUID();
|
||||||
|
string actorID = data["actorID"].AsString();
|
||||||
|
// m_log.DebugFormat("{0}: HandlPhysUpdateAttributes for {1}", LogHeader, uuid);
|
||||||
|
PhysicsActor pa = FindPhysicsActor(uuid);
|
||||||
|
if (pa != null)
|
||||||
|
{
|
||||||
|
if (pa.PhysicsActorType == (int)ActorTypes.Prim)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: HandlePhysUpdateAttributes for an prim: {1}", LogHeader, pa.UUID);
|
||||||
|
}
|
||||||
|
// pa.Size = data["size"].AsVector3();
|
||||||
|
pa.Position = data["position"].AsVector3();
|
||||||
|
pa.Force = data["force"].AsVector3();
|
||||||
|
// m_log.DebugFormat("{0}: HandlePhysUpdateAttributes: receiving velocity = {1}", LogHeader, data["velocity"].AsVector3());
|
||||||
|
pa.Velocity = data["velocity"].AsVector3();
|
||||||
|
pa.RotationalVelocity = data["rotationalVelocity"].AsVector3();
|
||||||
|
pa.Acceleration = data["acceleration"].AsVector3();
|
||||||
|
pa.Torque = data["torque"].AsVector3();
|
||||||
|
pa.Orientation = data["orientation"].AsQuaternion();
|
||||||
|
pa.IsPhysical = data["isPhysical"].AsBoolean(); // receive??
|
||||||
|
pa.Flying = data["flying"].AsBoolean(); // receive??
|
||||||
|
pa.Kinematic = data["kinematic"].AsBoolean(); // receive??
|
||||||
|
pa.Buoyancy = (float)(data["buoyancy"].AsReal());
|
||||||
|
SceneObjectPart sop = m_validLocalScene.GetSceneObjectPart(uuid);
|
||||||
|
if (sop != null)
|
||||||
|
{
|
||||||
|
pa.Shape = sop.Shape;
|
||||||
|
}
|
||||||
|
pa.ChangingActorID = actorID;
|
||||||
|
m_validLocalScene.PhysicsScene.AddPhysicsActorTaint(pa);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("HandlePhysUpdateAttributes, ChangingActorID = {0}, PA pos = {1}, data.position={2}", pa.ChangingActorID, pa.Position, data["position"].AsVector3().ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: attribute update for unknown uuid {1}", LogHeader, uuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: EXCEPTION processing UpdateAttributes: {1}", LogHeader, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the physics actor whether it is an object or a scene presence
|
||||||
|
private PhysicsActor FindPhysicsActor(UUID uuid)
|
||||||
|
{
|
||||||
|
ScenePresence sp = m_validLocalScene.GetScenePresence(uuid);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
return sp.PhysicsActor;
|
||||||
|
}
|
||||||
|
SceneObjectPart sop = m_validLocalScene.GetSceneObjectPart(uuid);
|
||||||
|
if (sop != null)
|
||||||
|
{
|
||||||
|
return sop.PhysActor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendPhysUpdateAttributes(PhysicsActor pa)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: SendPhysUpdateAttributes for {1}", LogHeader, pa.UUID);
|
||||||
|
if (pa.PhysicsActorType == (int)ActorTypes.Prim)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: SendPhysUpdateAttributes for an prim: {1}", LogHeader, pa.UUID);
|
||||||
|
}
|
||||||
|
OSDMap data = new OSDMap(17);
|
||||||
|
data["time"] = OSD.FromString(DateTime.Now.ToString("yyyyMMddHHmmssfff"));
|
||||||
|
data["localID"] = OSD.FromUInteger(pa.LocalID);
|
||||||
|
data["uuid"] = OSD.FromUUID(pa.UUID);
|
||||||
|
data["actorID"] = OSD.FromString(RegionSyncServerModule.ActorID);
|
||||||
|
data["size"] = OSD.FromVector3(pa.Size);
|
||||||
|
data["position"] = OSD.FromVector3(pa.Position);
|
||||||
|
data["force"] = OSD.FromVector3(pa.Force);
|
||||||
|
data["velocity"] = OSD.FromVector3(pa.Velocity);
|
||||||
|
// m_log.DebugFormat("{0}: HandlePhysUpdateAttributes: sending velocity = {1}", LogHeader, data["velocity"].AsVector3());
|
||||||
|
data["rotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity);
|
||||||
|
data["acceleration"] = OSD.FromVector3(pa.Acceleration);
|
||||||
|
data["torque"] = OSD.FromVector3(pa.Torque);
|
||||||
|
data["orientation"] = OSD.FromQuaternion(pa.Orientation);
|
||||||
|
data["isPhysical"] = OSD.FromBoolean(pa.IsPhysical);
|
||||||
|
data["flying"] = OSD.FromBoolean(pa.Flying);
|
||||||
|
data["buoyancy"] = OSD.FromReal(pa.Buoyancy);
|
||||||
|
data["isColliding"] = OSD.FromBoolean(pa.IsColliding);
|
||||||
|
data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround);
|
||||||
|
|
||||||
|
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,
|
||||||
|
OSDParser.SerializeJsonString(data));
|
||||||
|
Send(rsm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Utility functions
|
||||||
|
|
||||||
|
private OSDMap GetOSDMap(string strdata)
|
||||||
|
{
|
||||||
|
OSDMap args = null;
|
||||||
|
OSD buffer = OSDParser.DeserializeJson(strdata);
|
||||||
|
if (buffer.Type == OSDType.Map)
|
||||||
|
{
|
||||||
|
args = (OSDMap)buffer;
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<string> exceptions = new HashSet<string>();
|
||||||
|
private OSDMap DeserializeMessage(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
OSDMap data = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
lock (exceptions)
|
||||||
|
// If this is a new message, then print the underlying data that caused it
|
||||||
|
if (!exceptions.Contains(e.Message))
|
||||||
|
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public string GetServerAddressAndPort()
|
||||||
|
{
|
||||||
|
return m_addr.ToString() + ":" + m_port.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Utility functions
|
||||||
|
|
||||||
|
#region Handlers for Scene events
|
||||||
|
|
||||||
|
private void HandleAddOrUpdateObjectInLocalScene(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
// TODO: modify for physics
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
uint locX = data["locX"].AsUInteger();
|
||||||
|
uint locY = data["locY"].AsUInteger();
|
||||||
|
string sogxml = data["sogXml"].AsString();
|
||||||
|
SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Handlers for events/updates from Scene
|
||||||
|
|
||||||
|
public string StatisticIdentifier()
|
||||||
|
{
|
||||||
|
return "PhysEngineToSceneConnector";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StatisticLine(bool clearFlag)
|
||||||
|
{
|
||||||
|
string ret = "";
|
||||||
|
/*
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
ret = String.Format("{0},{1},{2},{3},{4},{5}",
|
||||||
|
msgsIn, msgsOut, bytesIn, bytesOut
|
||||||
|
);
|
||||||
|
if (clearFlag)
|
||||||
|
msgsIn = msgsOut = bytesIn = bytesOut = 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public string StatisticTitle()
|
||||||
|
{
|
||||||
|
return "msgsIn,msgsOut,bytesIn,bytesOut";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,432 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using log4net;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
//The connector that connects the local Scene (cache) and remote authoratative Scene
|
||||||
|
public class PhysEngineToSceneConnectorModule : IRegionModule, IPhysEngineToSceneConnectorModule, ICommandableModule
|
||||||
|
{
|
||||||
|
#region PhysEngineToSceneConnectorModule members and functions
|
||||||
|
|
||||||
|
private static int m_activeActors = 0;
|
||||||
|
private bool m_active = false;
|
||||||
|
private string m_serveraddr;
|
||||||
|
private int m_serverport;
|
||||||
|
private Scene m_scene;
|
||||||
|
private static List<Scene> m_allScenes = new List<Scene>();
|
||||||
|
private ILog m_log;
|
||||||
|
private Object m_client_lock = new Object();
|
||||||
|
//private PhysEngineToSceneConnector m_scriptEngineToSceneConnector = null;
|
||||||
|
private IConfig m_syncConfig = null;
|
||||||
|
public IConfig SyncConfig { get { return m_syncConfig; } }
|
||||||
|
private bool m_debugWithViewer = false;
|
||||||
|
public bool DebugWithViewer { get { return m_debugWithViewer; } }
|
||||||
|
private string m_regionSyncMode = "";
|
||||||
|
|
||||||
|
//Variables relavant for multi-scene subscription.
|
||||||
|
private Dictionary<string, PhysEngineToSceneConnector> m_PEToSceneConnectors = new Dictionary<string, PhysEngineToSceneConnector>(); //connector for each auth. scene
|
||||||
|
private string LogHeader = "[PhysEngineToSceneConnectorModule]";
|
||||||
|
private PhysEngineToSceneConnector m_idlePEToSceneConnector = null;
|
||||||
|
private PhysEngineToSceneConnector m_physEngineToSceneConnector = null;
|
||||||
|
|
||||||
|
private string m_subscriptionSpaceString;
|
||||||
|
|
||||||
|
#endregion PhysEngineToSceneConnectorModule members and functions
|
||||||
|
|
||||||
|
#region IRegionModule Members
|
||||||
|
|
||||||
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
m_active = false; //set to false unless this is the valid local scene
|
||||||
|
|
||||||
|
//Read in configuration
|
||||||
|
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||||
|
if (syncConfig != null
|
||||||
|
&& syncConfig.GetBoolean("Enabled", false)
|
||||||
|
// && syncConfig.GetString("Mode", "").ToLower() == "client"
|
||||||
|
&& syncConfig.GetBoolean("PhysEngineClient", false)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//scene.RegionSyncEnabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//scene.RegionSyncEnabled = false;
|
||||||
|
m_log.Warn(LogHeader + ": Not in physics engine client mode. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
m_activeActors++;
|
||||||
|
|
||||||
|
m_log.Debug(LogHeader + " Init PEToSceneConnectorModule, for local scene " + scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
|
m_scene = scene;
|
||||||
|
m_scene.RegisterModuleInterface<IPhysEngineToSceneConnectorModule>(this);
|
||||||
|
m_syncConfig = syncConfig;
|
||||||
|
m_debugWithViewer = syncConfig.GetBoolean("PhysEngineDebugWithViewer", false);
|
||||||
|
|
||||||
|
m_subscriptionSpaceString = syncConfig.GetString("InitSubscriptionSpace", "0_0,256_256");
|
||||||
|
|
||||||
|
|
||||||
|
// Setup the command line interface
|
||||||
|
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
|
InstallInterfaces();
|
||||||
|
|
||||||
|
m_log.Warn(LogHeader + " Initialised");
|
||||||
|
|
||||||
|
// collect all the scenes for later routing
|
||||||
|
if (!m_allScenes.Contains(scene))
|
||||||
|
{
|
||||||
|
m_allScenes.Add(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Start(); // fake a 'phys start' to get things going
|
||||||
|
|
||||||
|
//m_log.Warn(LogHeader + " Post-Initialised");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (m_active)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
m_scene = null;
|
||||||
|
m_active = false;
|
||||||
|
m_activeActors--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "RegionSyncPhysEngineModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSharedModule
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICommandableModule Members
|
||||||
|
private readonly Commander m_commander = new Commander("phys");
|
||||||
|
public ICommander CommandInterface
|
||||||
|
{
|
||||||
|
get { return m_commander; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IPhysEngineToSceneConnectorModule members
|
||||||
|
|
||||||
|
|
||||||
|
public bool Active
|
||||||
|
{
|
||||||
|
get { return m_active; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Synced
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock(m_client_lock)
|
||||||
|
{
|
||||||
|
return (m_PEToSceneConnectors.Count > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPhysEngineToSceneConnectorModule.IsPhysEngineActor()
|
||||||
|
{
|
||||||
|
return PhysEngineToSceneConnectorModule.IsPhysEngineActorS;
|
||||||
|
}
|
||||||
|
bool IPhysEngineToSceneConnectorModule.IsPhysEngineScene()
|
||||||
|
{
|
||||||
|
return PhysEngineToSceneConnectorModule.IsPhysEngineSceneS;
|
||||||
|
}
|
||||||
|
bool IPhysEngineToSceneConnectorModule.IsActivePhysEngineScene()
|
||||||
|
{
|
||||||
|
return PhysEngineToSceneConnectorModule.IsActivePhysEngineSceneS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsPhysEngineSceneS
|
||||||
|
{
|
||||||
|
get { return SceneToPhysEngineSyncServer.IsPhysEngineScene2S(); }
|
||||||
|
}
|
||||||
|
public static bool IsActivePhysEngineSceneS
|
||||||
|
{
|
||||||
|
get { return SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S(); }
|
||||||
|
}
|
||||||
|
public static bool IsPhysEngineActorS
|
||||||
|
{
|
||||||
|
get { return (m_activeActors != 0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scene is unknown by ODE so we have to look through the scenes to
|
||||||
|
/// find the one with this PhysicsActor so we can send the update.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pa"></param>
|
||||||
|
public static void RouteUpdate(PhysicsActor pa)
|
||||||
|
{
|
||||||
|
SceneObjectPart sop;
|
||||||
|
ScenePresence sp;
|
||||||
|
Scene s = null;
|
||||||
|
foreach (Scene ss in m_allScenes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sop = ss.GetSceneObjectPart(pa.UUID);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
sop = null;
|
||||||
|
}
|
||||||
|
if (sop != null)
|
||||||
|
{
|
||||||
|
s = ss;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sp = ss.GetScenePresence(pa.UUID);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
sp = null;
|
||||||
|
}
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
s = ss;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s != null)
|
||||||
|
{
|
||||||
|
if (s.PhysEngineToSceneConnectorModule != null)
|
||||||
|
{
|
||||||
|
s.PhysEngineToSceneConnectorModule.SendUpdate(pa);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("RouteUpdate: PhysEngineToSceneConnectorModule is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("RouteUpdate: no SOP found for {0}", pa.UUID);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Event Handlers
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void DebugSceneStats()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
List<ScenePresence> avatars = m_scene.GetAvatars();
|
||||||
|
List<EntityBase> entities = m_scene.GetEntities();
|
||||||
|
m_log.WarnFormat("{0} There are {1} avatars and {2} entities in the scene", LogHeader, avatars.Count, entities.Count);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendUpdate(PhysicsActor pa)
|
||||||
|
{
|
||||||
|
if (this.m_physEngineToSceneConnector != null)
|
||||||
|
{
|
||||||
|
this.m_physEngineToSceneConnector.SendPhysUpdateAttributes(pa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Console Command Interface
|
||||||
|
//IMPORTANT: these functions should only be actived for the PhysEngineToSceneConnectorModule that is associated with the valid local scene
|
||||||
|
|
||||||
|
private void InstallInterfaces()
|
||||||
|
{
|
||||||
|
Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer.");
|
||||||
|
//cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
|
||||||
|
|
||||||
|
Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer.");
|
||||||
|
//cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
|
||||||
|
//cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
|
||||||
|
|
||||||
|
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
|
||||||
|
|
||||||
|
m_commander.RegisterCommand("start", cmdSyncStart);
|
||||||
|
m_commander.RegisterCommand("stop", cmdSyncStop);
|
||||||
|
m_commander.RegisterCommand("status", cmdSyncStatus);
|
||||||
|
|
||||||
|
lock (m_scene)
|
||||||
|
{
|
||||||
|
// Add this to our scene so scripts can call these functions
|
||||||
|
m_scene.RegisterModuleCommander(m_commander);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes commandline input. Do not call directly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">Commandline arguments</param>
|
||||||
|
private void EventManager_OnPluginConsole(string[] args)
|
||||||
|
{
|
||||||
|
if (args[0] == "phys")
|
||||||
|
{
|
||||||
|
if (args.Length == 1)
|
||||||
|
{
|
||||||
|
m_commander.ProcessConsoleCommand("help", new string[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] tmpArgs = new string[args.Length - 2];
|
||||||
|
int i;
|
||||||
|
for (i = 2; i < args.Length; i++)
|
||||||
|
tmpArgs[i - 2] = args[i];
|
||||||
|
|
||||||
|
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStart(Object[] args)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
m_serveraddr = m_scene.RegionInfo.PhysicsSyncServerAddress;
|
||||||
|
m_serverport = m_scene.RegionInfo.PhysicsSyncServerPort;
|
||||||
|
|
||||||
|
lock (m_client_lock)
|
||||||
|
{
|
||||||
|
//m_log.Warn(LogHeader + " Starting synchronization");
|
||||||
|
m_log.Warn(LogHeader + ": Starting RegionSyncPhysEngine");
|
||||||
|
|
||||||
|
InitPhysEngineToSceneConnector(m_subscriptionSpaceString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void InitPhysEngineToSceneConnector(string space)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_physEngineToSceneConnector = new PhysEngineToSceneConnector(m_scene,
|
||||||
|
m_serveraddr, m_serverport, m_debugWithViewer, /* space,*/ m_syncConfig);
|
||||||
|
if (m_physEngineToSceneConnector.Start())
|
||||||
|
{
|
||||||
|
m_PEToSceneConnectors.Add(m_scene.RegionInfo.RegionName, m_physEngineToSceneConnector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStop(Object[] args)
|
||||||
|
{
|
||||||
|
lock (m_client_lock)
|
||||||
|
{
|
||||||
|
//if (m_scriptEngineToSceneConnector == null)
|
||||||
|
if(m_PEToSceneConnectors.Count==0 && m_idlePEToSceneConnector==null)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " Already stopped");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_PEToSceneConnectors.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, PhysEngineToSceneConnector> valPair in m_PEToSceneConnectors)
|
||||||
|
{
|
||||||
|
PhysEngineToSceneConnector connector = valPair.Value;
|
||||||
|
if (connector == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
connector.Stop();
|
||||||
|
}
|
||||||
|
m_PEToSceneConnectors.Clear();
|
||||||
|
}
|
||||||
|
else if (m_idlePEToSceneConnector != null)
|
||||||
|
{
|
||||||
|
m_idlePEToSceneConnector.Stop();
|
||||||
|
m_idlePEToSceneConnector = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_scriptEngineToSceneConnector.Stop();
|
||||||
|
//m_scriptEngineToSceneConnector = null;
|
||||||
|
m_log.Warn(LogHeader+": Stopping synchronization");
|
||||||
|
}
|
||||||
|
|
||||||
|
//save script state and stop script instances
|
||||||
|
// TODO: Load balancing. next line commented out to compile
|
||||||
|
// m_scene.EventManager.TriggerPhysEngineSyncStop();
|
||||||
|
//remove all objects
|
||||||
|
m_scene.DeleteAllSceneObjects();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStatus(Object[] args)
|
||||||
|
{
|
||||||
|
lock (m_client_lock)
|
||||||
|
{
|
||||||
|
if (m_PEToSceneConnectors.Count == 0)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " Not currently synchronized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<string, PhysEngineToSceneConnector> pair in m_PEToSceneConnectors)
|
||||||
|
{
|
||||||
|
PhysEngineToSceneConnector sceneConnector = pair.Value;
|
||||||
|
sceneConnector.ReportStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.Region.Examples.RegionSyncModule")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim.Region.Examples.RegionSyncModule")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (c) 2008")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("f0caca77-7818-4a43-9200-0a8548009a05")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("0.6.4.*")]
|
||||||
|
[assembly: AssemblyVersion("0.6.4.*")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,290 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using log4net;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
public class RegionSyncClientModule : IRegionModule, IRegionSyncClientModule, ICommandableModule
|
||||||
|
{
|
||||||
|
#region IRegionModule Members
|
||||||
|
|
||||||
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
|
{
|
||||||
|
/* This config parsing pattern should be used in each of these files:
|
||||||
|
OpenSim.cs
|
||||||
|
RegionSyncServerModule.cs
|
||||||
|
RegionSyncClientModule.cs
|
||||||
|
*/
|
||||||
|
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||||
|
m_active = false;
|
||||||
|
if (syncConfig == null)
|
||||||
|
m_log.Warn("[REGION SYNC CLIENT MODULE] No RegionSyncModule config section found. Shutting down.");
|
||||||
|
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||||
|
m_log.Warn("[REGION SYNC CLIENT MODULE] RegionSyncModule is not enabled. Shutting down.");
|
||||||
|
else if (!syncConfig.GetString("Mode", "").ToLower().Equals("client"))
|
||||||
|
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] RegionSyncModule is not in client mode. Shutting down.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_scene = scene;
|
||||||
|
m_active = true;
|
||||||
|
m_scene.RegionSyncEnabled = true;
|
||||||
|
m_scene.RegionSyncMode = "client";
|
||||||
|
|
||||||
|
//string serverAddrDefault = syncConfig.GetString("ServerIPAddress", "127.0.0.1");
|
||||||
|
//m_serveraddr = syncConfig.GetString(scene.RegionInfo.RegionName+"_ServerIPAddress", serverAddrDefault);
|
||||||
|
//int serverPortDefault = syncConfig.GetInt("ServerPort", 13000);
|
||||||
|
//m_serverport = syncConfig.GetInt(scene.RegionInfo.RegionName+"_ServerPort", serverPortDefault);
|
||||||
|
|
||||||
|
m_scene.RegisterModuleInterface<IRegionSyncClientModule>(this);
|
||||||
|
|
||||||
|
//m_symsync = syncConfig.GetBoolean("SymSync", false);
|
||||||
|
|
||||||
|
// Setup the command line interface
|
||||||
|
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
|
InstallInterfaces();
|
||||||
|
m_log.Warn("[REGION SYNC CLIENT MODULE] Initialised");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
// Go ahead and try to sync right away
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "RegionSyncModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSharedModule
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICommandableModule Members
|
||||||
|
private readonly Commander m_commander = new Commander("sync");
|
||||||
|
public ICommander CommandInterface
|
||||||
|
{
|
||||||
|
get { return m_commander; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IRegionSyncClientModule members
|
||||||
|
public void SendCoarseLocations()
|
||||||
|
{
|
||||||
|
m_client.SendCoarseLocations();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendAppearanceToScene(UUID agentID)
|
||||||
|
{
|
||||||
|
m_client.SendAppearanceToScene(agentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncomingLoadBalanceConnection(ScenePresence presence)
|
||||||
|
{
|
||||||
|
m_client.IncomingLoadBalanceConnection(presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Active
|
||||||
|
{
|
||||||
|
get { return m_active; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Synced
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock(m_client_lock)
|
||||||
|
{
|
||||||
|
return (m_client != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region RegionSyncClientModule members
|
||||||
|
private bool m_active = true;
|
||||||
|
private string m_serveraddr;
|
||||||
|
private int m_serverport;
|
||||||
|
private Scene m_scene;
|
||||||
|
private ILog m_log;
|
||||||
|
private Object m_client_lock = new Object();
|
||||||
|
private RegionSyncClient m_client = null;
|
||||||
|
|
||||||
|
//private bool m_symsync = false;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Event Handlers
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void DebugSceneStats()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
List<ScenePresence> avatars = m_scene.GetAvatars();
|
||||||
|
List<EntityBase> entities = m_scene.GetEntities();
|
||||||
|
m_log.WarnFormat("There are {0} avatars and {1} entities in the scene", avatars.Count, entities.Count);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Console Command Interface
|
||||||
|
private void InstallInterfaces()
|
||||||
|
{
|
||||||
|
Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer.");
|
||||||
|
//cmdSyncStart.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
|
||||||
|
//cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
|
||||||
|
|
||||||
|
Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer.");
|
||||||
|
//cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
|
||||||
|
//cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
|
||||||
|
|
||||||
|
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
|
||||||
|
|
||||||
|
m_commander.RegisterCommand("start", cmdSyncStart);
|
||||||
|
m_commander.RegisterCommand("stop", cmdSyncStop);
|
||||||
|
m_commander.RegisterCommand("status", cmdSyncStatus);
|
||||||
|
|
||||||
|
lock (m_scene)
|
||||||
|
{
|
||||||
|
// Add this to our scene so scripts can call these functions
|
||||||
|
m_scene.RegisterModuleCommander(m_commander);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes commandline input. Do not call directly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">Commandline arguments</param>
|
||||||
|
private void EventManager_OnPluginConsole(string[] args)
|
||||||
|
{
|
||||||
|
if (args[0] == "sync")
|
||||||
|
{
|
||||||
|
if (args.Length == 1)
|
||||||
|
{
|
||||||
|
m_commander.ProcessConsoleCommand("help", new string[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] tmpArgs = new string[args.Length - 2];
|
||||||
|
int i;
|
||||||
|
for (i = 2; i < args.Length; i++)
|
||||||
|
tmpArgs[i - 2] = args[i];
|
||||||
|
|
||||||
|
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStart(Object[] args)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
m_serveraddr = m_scene.RegionInfo.AvatarSyncServerAddress;
|
||||||
|
m_serverport = m_scene.RegionInfo.AvatarSyncServerPort;
|
||||||
|
|
||||||
|
if (m_serveraddr.Equals(String.Empty) || m_serverport == -1)
|
||||||
|
{
|
||||||
|
m_log.Warn("[REGION SYNC CLIENT MODULE] No IP or port of RegionSyncServer has been configured. Shut down.");
|
||||||
|
m_active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_client_lock)
|
||||||
|
{
|
||||||
|
if (m_client != null)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] Already synchronizing to {0}", m_client.GetServerAddressAndPort());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//m_log.Warn("[REGION SYNC CLIENT MODULE] Starting synchronization");
|
||||||
|
m_log.Warn("[REGION SYNC CLIENT MODULE] Starting RegionSyncClient");
|
||||||
|
|
||||||
|
m_client = new RegionSyncClient(m_scene, m_serveraddr, m_serverport);
|
||||||
|
m_client.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStop(Object[] args)
|
||||||
|
{
|
||||||
|
lock(m_client_lock)
|
||||||
|
{
|
||||||
|
if (m_client == null)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] Already stopped");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_log.Warn("[REGION SYNC CLIENT MODULE] Stopping synchronization");
|
||||||
|
m_client.Stop();
|
||||||
|
m_client = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStatus(Object[] args)
|
||||||
|
{
|
||||||
|
lock (m_client_lock)
|
||||||
|
{
|
||||||
|
if (m_client == null)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] Not currently synchronized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] Synchronized");
|
||||||
|
m_client.ReportStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,898 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.Packets;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
#region MsgHandlerStatus Enum
|
||||||
|
public enum MsgHandlerStatus
|
||||||
|
{
|
||||||
|
Success, // Everything went as expected
|
||||||
|
Trivial, // Minor issue, nothing to worry about
|
||||||
|
Warning, // Something went wrong, we can continue
|
||||||
|
Error // This should certainly not have happened! (A bug)
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// The RegionSyncClientView acts as a thread on the RegionSyncServer to handle incoming
|
||||||
|
// messages from RegionSyncClients.
|
||||||
|
public class RegionSyncClientView
|
||||||
|
{
|
||||||
|
#region RegionSyncClientView members
|
||||||
|
|
||||||
|
object stats = new object();
|
||||||
|
private DateTime lastStatTime;
|
||||||
|
private long queuedUpdates;
|
||||||
|
private long dequeuedUpdates;
|
||||||
|
private long msgsIn;
|
||||||
|
private long msgsOut;
|
||||||
|
private long bytesIn;
|
||||||
|
private long bytesOut;
|
||||||
|
private long pollBlocks;
|
||||||
|
private int lastTotalCount;
|
||||||
|
private int lastLocalCount;
|
||||||
|
private int lastRemoteCount;
|
||||||
|
|
||||||
|
private int msgCount = 0;
|
||||||
|
|
||||||
|
// The TcpClient this view uses to communicate with its RegionSyncClient
|
||||||
|
private TcpClient m_tcpclient;
|
||||||
|
// Set the addr and port for TcpListener
|
||||||
|
private IPAddress m_addr;
|
||||||
|
private Int32 m_port;
|
||||||
|
private int m_connection_number;
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
object m_syncRoot = new object();
|
||||||
|
Dictionary<UUID, RegionSyncAvatar> m_syncedAvatars = new Dictionary<UUID, RegionSyncAvatar>();
|
||||||
|
|
||||||
|
// A queue for incoming and outgoing traffic
|
||||||
|
//private OpenMetaverse.BlockingQueue<RegionSyncMessage> inbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
|
||||||
|
//private OpenMetaverse.BlockingQueue<RegionSyncMessage> outbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
|
||||||
|
|
||||||
|
private BlockingUpdateQueue m_outQ = new BlockingUpdateQueue();
|
||||||
|
|
||||||
|
private ILog m_log;
|
||||||
|
|
||||||
|
private Thread m_receive_loop;
|
||||||
|
private Thread m_send_loop;
|
||||||
|
private string m_regionName;
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return m_regionName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// A string of the format [REGION SYNC CLIENT VIEW (regionname)] for use in log headers
|
||||||
|
private string LogHeader
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(m_regionName == null)
|
||||||
|
return String.Format("[REGION SYNC CLIENT VIEW #{0}]", m_connection_number);
|
||||||
|
return String.Format("[REGION SYNC CLIENT VIEW #{0} ({1:10})]", m_connection_number, m_regionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A string of the format "RegionSyncClientView #X" for use in describing the object itself
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(m_regionName == null)
|
||||||
|
return String.Format("RegionSyncClientView #{0}", m_connection_number);
|
||||||
|
return String.Format("RegionSyncClientView #{0} ({1:10})", m_connection_number, m_regionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetStats()
|
||||||
|
{
|
||||||
|
int syncedAvCount = SyncedAvCount; ;
|
||||||
|
string ret;
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds;
|
||||||
|
lastStatTime = DateTime.Now;
|
||||||
|
int totalAvCount = m_scene.SceneGraph.GetRootAgentCount();
|
||||||
|
ret = String.Format("[{0,4}/{1,4}], [{2,4}/{3,4}], [{4,4}/{5,4}], [{6,4} ({7,4})], [{8,8} ({9,8:00.00})], [{10,4} ({11,4})], [{12,8} ({13,8:00.00})], [{14,8},{15,8},{16,8}]",
|
||||||
|
lastTotalCount, totalAvCount, // TOTAL AVATARS
|
||||||
|
lastLocalCount, syncedAvCount, // LOCAL TO THIS CLIENT VIEW
|
||||||
|
lastRemoteCount, totalAvCount - syncedAvCount, // REMOTE (SHOULD = TOTAL - LOCAL)
|
||||||
|
msgsIn, (int)(msgsIn / secondsSinceLastStats),
|
||||||
|
bytesIn, 8 * (bytesIn / secondsSinceLastStats / 1000000), // IN
|
||||||
|
msgsOut, (int)(msgsOut / secondsSinceLastStats),
|
||||||
|
bytesOut, 8 * (bytesOut / secondsSinceLastStats / 1000000), // OUT
|
||||||
|
m_outQ.Count, (int)(queuedUpdates / secondsSinceLastStats), (int)(dequeuedUpdates/secondsSinceLastStats)); // QUEUE ACTIVITY
|
||||||
|
msgsIn = msgsOut = bytesIn = bytesOut = pollBlocks = queuedUpdates = dequeuedUpdates = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the client is connected
|
||||||
|
public bool Connected
|
||||||
|
{ get { return m_tcpclient.Connected; } }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public RegionSyncClientView(int num, Scene scene, TcpClient client)
|
||||||
|
{
|
||||||
|
m_connection_number = num;
|
||||||
|
m_scene = scene;
|
||||||
|
m_tcpclient = client;
|
||||||
|
m_addr = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
|
||||||
|
m_port = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
|
||||||
|
|
||||||
|
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
//m_log.WarnFormat("{0} Constructed", LogHeader);
|
||||||
|
|
||||||
|
// Create a thread for the receive loop
|
||||||
|
m_receive_loop = new Thread(new ThreadStart(delegate() { ReceiveLoop(); }));
|
||||||
|
m_receive_loop.Name = Description + " (ReceiveLoop)";
|
||||||
|
//m_log.WarnFormat("{0} Started thread: {1}", LogHeader, m_receive_loop.Name);
|
||||||
|
m_receive_loop.Start();
|
||||||
|
|
||||||
|
m_send_loop = new Thread(new ThreadStart(delegate() { SendLoop(); }));
|
||||||
|
m_send_loop.Name = Description + " (SendLoop)";
|
||||||
|
m_send_loop.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the RegionSyncClientView, disconnecting the RegionSyncClient
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
m_scene.EventManager.OnChatFromClient -= EventManager_OnChatFromClient;
|
||||||
|
m_tcpclient.Client.Close();
|
||||||
|
m_tcpclient.Close();
|
||||||
|
//Logout any synced avatars
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
foreach (UUID agentID in m_syncedAvatars.Keys)
|
||||||
|
{
|
||||||
|
ScenePresence presence;
|
||||||
|
if (m_scene.TryGetScenePresence(agentID, out presence))
|
||||||
|
{
|
||||||
|
string name = presence.Name;
|
||||||
|
m_scene.RemoveClient(agentID);
|
||||||
|
m_log.WarnFormat("{0} Agent \"{1}\" ({2}) was removed from scene.", LogHeader, name, agentID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Agent {1} not found in the scene.", LogHeader, agentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for messages from a RegionSyncClient
|
||||||
|
// *** This is the main receive loop thread for each connected client
|
||||||
|
private void ReceiveLoop()
|
||||||
|
{
|
||||||
|
//DSG SYNC: commenting out the code for handling chats
|
||||||
|
// m_scene.EventManager.OnChatFromClient += new EventManager.ChatFromClientEvent(EventManager_OnChatFromClient);
|
||||||
|
// m_scene.EventManager.OnChatFromWorld += new EventManager.ChatFromWorldEvent(EventManager_OnChatFromClient);
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
|
|
||||||
|
// Reset stats and time
|
||||||
|
lastStatTime = DateTime.Now;
|
||||||
|
msgsIn = msgsOut = bytesIn = bytesOut = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
RegionSyncMessage msg = GetMessage();
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
msgsIn++;
|
||||||
|
bytesIn += msg.Length;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (m_syncRoot)
|
||||||
|
HandleMessage(msg);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0} Exception in HandleMessage({1}) (ReceiveLoop):{2}", LogHeader, msg.Type.ToString(), e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0} RegionSyncClient has disconnected: {1} (ReceiveLoop)", LogHeader, e.Message);
|
||||||
|
}
|
||||||
|
Shutdown();
|
||||||
|
// Thread exits here
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send messages from the update Q as fast as we can DeQueue them
|
||||||
|
// *** This is the main send loop thread for each connected client
|
||||||
|
private void SendLoop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Dequeue is thread safe
|
||||||
|
byte[] update = m_outQ.Dequeue();
|
||||||
|
lock (stats)
|
||||||
|
dequeuedUpdates++;
|
||||||
|
Send(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0} RegionSyncClient has disconnected: {1} (SendLoop)", LogHeader, e.Message);
|
||||||
|
}
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnqueuePresenceUpdate(UUID id, byte[] update)
|
||||||
|
{
|
||||||
|
lock (stats)
|
||||||
|
queuedUpdates++;
|
||||||
|
// Enqueue is thread safe
|
||||||
|
m_outQ.Enqueue(id, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EventManager_OnChatFromClient(object sender, OSChatMessage chat)
|
||||||
|
{
|
||||||
|
OSDMap data = new OSDMap(5);
|
||||||
|
data["channel"] = OSD.FromInteger(chat.Channel);
|
||||||
|
data["msg"] = OSD.FromString(chat.Message);
|
||||||
|
data["pos"] = OSD.FromVector3(chat.Position);
|
||||||
|
data["name"] = OSD.FromString(chat.From);
|
||||||
|
data["id"] = OSD.FromUUID(chat.SenderUUID);
|
||||||
|
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ChatFromClient, OSDParser.SerializeJsonString(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a message from the RegionSyncClient
|
||||||
|
private RegionSyncMessage GetMessage()
|
||||||
|
{
|
||||||
|
// Get a RegionSyncMessager from the incoming stream
|
||||||
|
RegionSyncMessage msg = new RegionSyncMessage(m_tcpclient.GetStream());
|
||||||
|
//m_log.WarnFormat("{0} Received {1}", LogHeader, msg.ToString());
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<string> exceptions = new HashSet<string>();
|
||||||
|
private OSDMap DeserializeMessage(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
OSDMap data = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
lock(exceptions)
|
||||||
|
// If this is a new message, then print the underlying data that caused it
|
||||||
|
if(!exceptions.Contains(e.Message))
|
||||||
|
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle an incoming message
|
||||||
|
// *** Perhaps this should not be synchronous with the receive
|
||||||
|
// We could handle messages from an incoming Queue
|
||||||
|
private void HandleMessage(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
msgCount++;
|
||||||
|
//string handlerMessage = "";
|
||||||
|
switch (msg.Type)
|
||||||
|
{
|
||||||
|
case RegionSyncMessage.MsgType.RegionName:
|
||||||
|
{
|
||||||
|
m_regionName = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
|
||||||
|
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.RegionName, m_scene.RegionInfo.RegionName));
|
||||||
|
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Syncing to region \"{0}\"", m_regionName));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.GetAvatars:
|
||||||
|
{
|
||||||
|
m_scene.ForEachScenePresence(delegate(ScenePresence presence)
|
||||||
|
{
|
||||||
|
// Let the client managers know about this avatar
|
||||||
|
OSDMap data = new OSDMap(1);
|
||||||
|
data["agentID"] = OSD.FromUUID(presence.ControllingClient.AgentId);
|
||||||
|
data["localID"] = OSD.FromUInteger(presence.LocalId);
|
||||||
|
data["first"] = OSD.FromString(presence.ControllingClient.FirstName);
|
||||||
|
data["last"] = OSD.FromString(presence.ControllingClient.LastName);
|
||||||
|
data["startPos"] = OSD.FromVector3(presence.ControllingClient.StartPos);
|
||||||
|
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.NewAvatar, OSDParser.SerializeJsonString(data)));
|
||||||
|
});
|
||||||
|
RegionSyncMessage.HandleSuccess(LogHeader, msg, "Sent all scene avatars");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.AgentAdd:
|
||||||
|
{
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
string first = data["first"].AsString();
|
||||||
|
string last = data["last"].AsString();
|
||||||
|
Vector3 startPos = data["startPos"].AsVector3();
|
||||||
|
|
||||||
|
if (agentID != null && first != null && last != null && startPos != null)
|
||||||
|
{
|
||||||
|
RegionSyncAvatar av = new RegionSyncAvatar(m_scene, agentID, first, last, startPos, this);
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
if (m_syncedAvatars.ContainsKey(agentID))
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Attempted to add duplicate avatar with agentID {0}", agentID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_syncedAvatars.Add(agentID, av);
|
||||||
|
}
|
||||||
|
//m_scene.AddNewClient(av);
|
||||||
|
m_scene.AddNewClient2(av, true, false);
|
||||||
|
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Handled AddAgent for UUID {0} at {1}", agentID, startPos.ToString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.AgentUpdate:
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
AgentUpdatePacket.AgentDataBlock agentData = new AgentUpdatePacket.AgentDataBlock();
|
||||||
|
agentData.FromBytes(msg.Data, ref len);
|
||||||
|
|
||||||
|
UUID agentID = agentData.AgentID;
|
||||||
|
|
||||||
|
RegionSyncAvatar av;
|
||||||
|
bool found;
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
found = m_syncedAvatars.TryGetValue(agentData.AgentID, out av);
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Received agent update for avatar not owned by this client view {0}", agentData.AgentID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AgentUpdateArgs arg = new AgentUpdateArgs();
|
||||||
|
arg.AgentID = agentData.AgentID;
|
||||||
|
arg.BodyRotation = agentData.BodyRotation;
|
||||||
|
arg.CameraAtAxis = agentData.CameraAtAxis;
|
||||||
|
arg.CameraCenter = agentData.CameraCenter;
|
||||||
|
arg.CameraLeftAxis = agentData.CameraLeftAxis;
|
||||||
|
arg.CameraUpAxis = agentData.CameraUpAxis;
|
||||||
|
arg.ControlFlags = agentData.ControlFlags;
|
||||||
|
arg.Far = agentData.Far;
|
||||||
|
arg.Flags = agentData.Flags;
|
||||||
|
arg.HeadRotation = agentData.HeadRotation;
|
||||||
|
arg.SessionID = agentData.SessionID;
|
||||||
|
arg.State = agentData.State;
|
||||||
|
|
||||||
|
if( av.AgentUpdate(arg) )
|
||||||
|
{
|
||||||
|
//RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Handled AgentUpdate for UUID {0}", agentID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Could not handle AgentUpdate UUID {0}", agentID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.AgentSameRegionTeleport:
|
||||||
|
//KittyL: added to support same region teleporting
|
||||||
|
int lent = 0;
|
||||||
|
TeleportLocationRequestPacket tpLocReq = new TeleportLocationRequestPacket(msg.Data, ref lent);
|
||||||
|
|
||||||
|
RegionSyncAvatar avatar;
|
||||||
|
bool avFound;
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
avFound = m_syncedAvatars.TryGetValue(tpLocReq.AgentData.AgentID, out avatar);
|
||||||
|
}
|
||||||
|
if (!avFound)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Received agent update for avatar not owned by this client view {0}", tpLocReq.AgentData.AgentID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_scene.RequestTeleportLocation(avatar, m_scene.RegionInfo.RegionHandle, tpLocReq.Info.Position,
|
||||||
|
tpLocReq.Info.LookAt, 16);
|
||||||
|
return;
|
||||||
|
case RegionSyncMessage.MsgType.AgentRemove:
|
||||||
|
{
|
||||||
|
// Get the data from message and error check
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the parameters from data and error check
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
if (agentID == null || agentID == UUID.Zero)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Missing or invalid JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
if (m_syncedAvatars.ContainsKey(agentID))
|
||||||
|
{
|
||||||
|
m_syncedAvatars.Remove(agentID);
|
||||||
|
// Find the presence in the scene
|
||||||
|
ScenePresence presence;
|
||||||
|
if (m_scene.TryGetScenePresence(agentID, out presence))
|
||||||
|
{
|
||||||
|
string name = presence.Name;
|
||||||
|
|
||||||
|
m_scene.SceneGraph.DeleteSceneObject(UUID.Zero, true);
|
||||||
|
m_scene.RemoveClient(agentID);
|
||||||
|
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Agent \"{0}\" was removed from scene.", name));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Agent {0} not found in the scene.", agentID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Agent {0} not in the list of synced avatars.", agentID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.AvatarAppearance:
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("{0} START of AvatarAppearance handler", LogHeader);
|
||||||
|
// Get the data from message and error check
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the parameters from data and error check
|
||||||
|
UUID agentID = data["id"].AsUUID();
|
||||||
|
if (agentID == null || agentID == UUID.Zero)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Missing or invalid JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells the avatar factory to pull an updated appearance from the avatar service
|
||||||
|
m_scene.AvatarFactory.RefreshAppearance(agentID);
|
||||||
|
|
||||||
|
m_log.DebugFormat("{0} END of AvatarAppearance handler", LogHeader);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.AgentRequestSit:
|
||||||
|
{
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
UUID targetID = data["targetID"].AsUUID();
|
||||||
|
Vector3 offset = data["offset"].AsVector3();
|
||||||
|
|
||||||
|
// m_log.DebugFormat("{0} AgentRequestSit for {1}", LogHeader, agentID.ToString());
|
||||||
|
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
sp.HandleAgentRequestSit(sp.ControllingClient, agentID, targetID, offset);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.AgentSit:
|
||||||
|
{
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
|
||||||
|
// m_log.DebugFormat("{0} AgentSit for {1}", LogHeader, agentID.ToString());
|
||||||
|
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
sp.HandleAgentSit(sp.ControllingClient, agentID);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.StartAnim:
|
||||||
|
{
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
UUID animID = data["id"].AsUUID();
|
||||||
|
|
||||||
|
// m_log.DebugFormat("{0} AnimStart for {1}", LogHeader, agentID.ToString());
|
||||||
|
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
sp.HandleStartAnim(sp.ControllingClient, animID);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.StopAnim:
|
||||||
|
{
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
UUID animID = data["id"].AsUUID();
|
||||||
|
|
||||||
|
// m_log.DebugFormat("{0} AnimStop for {1}", LogHeader, agentID.ToString());
|
||||||
|
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
sp.HandleStopAnim(sp.ControllingClient, animID);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.GrabObject:
|
||||||
|
{
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
uint localID = data["localID"].AsUInteger();
|
||||||
|
m_log.DebugFormat("{0} GrabObject for {1}. object={2}",
|
||||||
|
LogHeader, agentID.ToString(), localID);
|
||||||
|
Vector3 offsetPos = data["offsetPos"].AsVector3();
|
||||||
|
OSDArray surfaceArray = (OSDArray)data["surfaceArgs"];
|
||||||
|
List<SurfaceTouchEventArgs> surfaceArgs = ExtractSurfaceArgList(surfaceArray);
|
||||||
|
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
m_scene.ProcessObjectGrab(localID, offsetPos, sp.ControllingClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.GrabUpdate:
|
||||||
|
{
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
UUID objectID = data["objectID"].AsUUID();
|
||||||
|
// m_log.DebugFormat("{0} GrabUpdate for {1}. ObjectID={2}",
|
||||||
|
// LogHeader, agentID.ToString(), objectID.ToString());
|
||||||
|
Vector3 offset = data["offset"].AsVector3();
|
||||||
|
Vector3 pos = data["pos"].AsVector3();
|
||||||
|
OSDArray surfaceArray = (OSDArray)data["surfaceArgs"];
|
||||||
|
List<SurfaceTouchEventArgs> surfaceArgs = ExtractSurfaceArgList(surfaceArray);
|
||||||
|
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
m_scene.ProcessObjectGrabUpdate(objectID, offset, pos, sp.ControllingClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.DeGrabObject:
|
||||||
|
{
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
m_log.DebugFormat("{0} DeGrabUpdate for {1}", LogHeader, agentID.ToString());
|
||||||
|
uint localID = data["objectID"].AsUInteger();
|
||||||
|
OSDArray surfaceArray = (OSDArray)data["surfaceArgs"];
|
||||||
|
List<SurfaceTouchEventArgs> surfaceArgs = ExtractSurfaceArgList(surfaceArray);
|
||||||
|
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
m_scene.ProcessObjectDeGrab(localID, sp.ControllingClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.ChatFromClient:
|
||||||
|
{
|
||||||
|
// Get the data from message and error check
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OSChatMessage args = new OSChatMessage();
|
||||||
|
args.Channel = data["channel"].AsInteger();
|
||||||
|
args.Message = data["msg"].AsString();
|
||||||
|
args.Position = data["pos"].AsVector3();
|
||||||
|
args.From = data["name"].AsString();
|
||||||
|
UUID id = data["id"].AsUUID();
|
||||||
|
args.Scene = m_scene;
|
||||||
|
args.Type = ChatTypeEnum.Say;
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(id, out sp);
|
||||||
|
if(sp != null)
|
||||||
|
{
|
||||||
|
args.Sender = sp.ControllingClient;
|
||||||
|
args.SenderUUID = id;
|
||||||
|
m_scene.EventManager.TriggerOnChatFromClient(sp.ControllingClient,args);
|
||||||
|
}
|
||||||
|
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Received chat from \"{0}\"", args.From));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.RegionStatus:
|
||||||
|
{
|
||||||
|
// Get the data from message and error check
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int t = data["total"].AsInteger();
|
||||||
|
int l = data["local"].AsInteger();
|
||||||
|
int r = data["remote"].AsInteger();
|
||||||
|
lastTotalCount = t;
|
||||||
|
lastLocalCount = l;
|
||||||
|
lastRemoteCount = r;
|
||||||
|
//RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Received stats: {0},{1},{2}", t, l, r));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.AvatarTeleportIn:
|
||||||
|
{
|
||||||
|
// Get the data from message and error check
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Presence is not in scene");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sp.ControllingClient is RegionSyncAvatar)
|
||||||
|
{
|
||||||
|
m_syncedAvatars.Add(agentID, (RegionSyncAvatar)sp.ControllingClient);
|
||||||
|
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Avatar {0} now owned by region {1}", sp.Name, m_regionName));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Presence is not a RegionSyncAvatar");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.AvatarTeleportOut:
|
||||||
|
{
|
||||||
|
// Get the data from message and error check
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
|
ScenePresence sp;
|
||||||
|
m_scene.TryGetScenePresence(agentID, out sp);
|
||||||
|
if (sp == null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Presence is not in scene");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sp.ControllingClient is RegionSyncAvatar)
|
||||||
|
{
|
||||||
|
m_syncedAvatars.Remove(agentID);
|
||||||
|
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Avatar {0} is no longer owned by region {1}", sp.Name, m_regionName));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegionSyncMessage.HandleError(LogHeader, msg, "Presence is not a RegionSyncAvatar");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Unable to handle unsupported message type: {1}", LogHeader, msg.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SurfaceTouchEventArgs> ExtractSurfaceArgList(OSDArray args)
|
||||||
|
{
|
||||||
|
List<SurfaceTouchEventArgs> surfaceArgs = new List<SurfaceTouchEventArgs>();
|
||||||
|
for (int ii = 0; ii < args.Count; ii++)
|
||||||
|
{
|
||||||
|
SurfaceTouchEventArgs stea = new SurfaceTouchEventArgs();
|
||||||
|
OSDMap entry = (OSDMap)args[ii];
|
||||||
|
stea.Binormal = entry["binormal"].AsVector3();
|
||||||
|
stea.FaceIndex = entry["faceIndex"].AsInteger();
|
||||||
|
stea.Normal = entry["normal"].AsVector3();
|
||||||
|
stea.Position = entry["position"].AsVector3();
|
||||||
|
stea.STCoord = entry["stCoord"].AsVector3();
|
||||||
|
stea.UVCoord = entry["uvCoord"].AsVector3();
|
||||||
|
surfaceArgs.Add(stea);
|
||||||
|
}
|
||||||
|
return surfaceArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HandlerDebug(RegionSyncMessage msg, string handlerMessage)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} DBG ({1}): {2}", LogHeader, msg.ToString(), handlerMessage);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HandlerSuccess(RegionSyncMessage msg, string handlerMessage)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Handled {1}: {2}", LogHeader, msg.ToString(), handlerMessage);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HandlerFailure(RegionSyncMessage msg, string handlerMessage)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Unable to handle {1}: {2}", LogHeader, msg.ToString(), handlerMessage);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
//if (msg.Type == RegionSyncMessage.MsgType.AvatarAppearance)
|
||||||
|
//m_log.WarnFormat("{0} Sending AvatarAppearance to client manager", LogHeader);
|
||||||
|
Send(msg.ToBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Send(byte[] data)
|
||||||
|
{
|
||||||
|
if (m_tcpclient.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
msgsOut++;
|
||||||
|
bytesOut += data.Length;
|
||||||
|
}
|
||||||
|
m_tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar =>
|
||||||
|
{
|
||||||
|
if(m_tcpclient.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_tcpclient.GetStream().EndWrite(ar);
|
||||||
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} RegionSyncClient has disconnected.", LogHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SyncedAvCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (m_syncRoot)
|
||||||
|
return m_syncedAvatars.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReportStatus()
|
||||||
|
{
|
||||||
|
int syncedAvCount = SyncedAvCount;
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
bool localcheck = true;
|
||||||
|
bool remotecheck = true;
|
||||||
|
bool totalcheck = true;
|
||||||
|
if (syncedAvCount != lastLocalCount)
|
||||||
|
localcheck = false;
|
||||||
|
if (m_scene.SceneGraph.GetRootAgentCount() != lastTotalCount)
|
||||||
|
totalcheck = false;
|
||||||
|
if (m_scene.SceneGraph.GetRootAgentCount() - syncedAvCount != lastRemoteCount)
|
||||||
|
remotecheck = false;
|
||||||
|
m_log.ErrorFormat("{0} Syncing {1,4} remote presences. Remote scene reporting {2,4} locals, {3,4} remotes, {4,4} total ({5},{6},{7})",
|
||||||
|
LogHeader, syncedAvCount, lastLocalCount, lastRemoteCount, lastTotalCount, localcheck ? " " : "!", remotecheck ? " " : "!", totalcheck ? " " : "!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BalanceClients(int targetLoad, string destinationRegion)
|
||||||
|
{
|
||||||
|
OSDMap data = new OSDMap(2);
|
||||||
|
data["endCount"] = OSD.FromInteger(targetLoad);
|
||||||
|
data["toRegion"] = OSD.FromString(destinationRegion);
|
||||||
|
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.BalanceClientLoad, OSDParser.SerializeJsonString(data)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
#region ActorType Enum
|
||||||
|
public enum ActorType
|
||||||
|
{
|
||||||
|
Null,
|
||||||
|
ClientManager,
|
||||||
|
ScriptEngine,
|
||||||
|
PhysicsEngine
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ActorStatus Enum
|
||||||
|
public enum ActorStatus
|
||||||
|
{
|
||||||
|
Null,
|
||||||
|
Idle,
|
||||||
|
Sync
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A message for synchonization message between scenes
|
||||||
|
/// </summary>
|
||||||
|
public class RegionSyncMessage
|
||||||
|
{
|
||||||
|
//KittyL: added to help identify different actors
|
||||||
|
|
||||||
|
|
||||||
|
#region MsgType Enum
|
||||||
|
public enum MsgType
|
||||||
|
{
|
||||||
|
Null,
|
||||||
|
//ConnectSyncClient,
|
||||||
|
//DisconnectSyncClient,
|
||||||
|
// CM -> SIM(Scene)
|
||||||
|
ActorConnect,
|
||||||
|
AgentAdd,
|
||||||
|
AgentUpdate,
|
||||||
|
AgentSameRegionTeleport, //from CM to PSA
|
||||||
|
AgentRemove,
|
||||||
|
AgentRequestSit,
|
||||||
|
AgentSit,
|
||||||
|
GrabObject,
|
||||||
|
GrabUpdate,
|
||||||
|
DeGrabObject,
|
||||||
|
StartAnim,
|
||||||
|
StopAnim,
|
||||||
|
GetTerrain,
|
||||||
|
GetObjects,
|
||||||
|
SubscribeObjects,
|
||||||
|
GetAvatars,
|
||||||
|
SubscribeAvatars,
|
||||||
|
ChatFromClient,
|
||||||
|
AvatarTeleportOut, // An LLClientView (real client) was converted to a RegionSyncAvatar
|
||||||
|
AvatarTeleportIn, // A RegionSyncAvatar was converted to an LLClientView (real client)
|
||||||
|
AvatarTeleportSameRegion, //from PSA to PE
|
||||||
|
// SIM -> CM
|
||||||
|
//Terrain,
|
||||||
|
//NewObject, // objects
|
||||||
|
//UpdatedObject, // objects
|
||||||
|
//RemovedObject, // objects
|
||||||
|
NewAvatar, // avatars
|
||||||
|
UpdatedAvatar, // avatars
|
||||||
|
AnimateAvatar,
|
||||||
|
AvatarAppearance,
|
||||||
|
RemovedAvatar, // avatars
|
||||||
|
BalanceClientLoad, // Tells CM a client load target and a place to teleport the extras
|
||||||
|
ChatFromSim,
|
||||||
|
SitResponse,
|
||||||
|
SendAnimations,
|
||||||
|
// BIDIR
|
||||||
|
EchoRequest,
|
||||||
|
EchoResponse,
|
||||||
|
RegionName,
|
||||||
|
RegionStatus,
|
||||||
|
//Added by KittyL
|
||||||
|
// Actor -> Scene
|
||||||
|
ActorType, //to register the type (e.g. Client Manager or Script Engine) with Scene when sync channel is initialized
|
||||||
|
SetObjectProperty,
|
||||||
|
ActorStop,
|
||||||
|
ResetScene,
|
||||||
|
OnRezScript,
|
||||||
|
OnScriptReset,
|
||||||
|
OnUpdateScript,
|
||||||
|
// Scene -> Script Engine
|
||||||
|
NewObjectWithScript,
|
||||||
|
SceneLocation,
|
||||||
|
//For load balancing purpose (among script engines)
|
||||||
|
//Temorarily put here, for easier first round of implemention.
|
||||||
|
//Script engine --> Scene
|
||||||
|
ActorStatus, //if the actor is busying syncing with a Scene, or is just idle. Status: {sync, idle}
|
||||||
|
LoadBalanceRequest,
|
||||||
|
LoadMigrationListenerInitiated,
|
||||||
|
//Scene --> Script engine
|
||||||
|
LoadMigrationNotice,
|
||||||
|
LoadBalanceResponse,
|
||||||
|
LoadBalanceRejection,
|
||||||
|
// Physics Engine -> Scene
|
||||||
|
PhysTerseUpdate,
|
||||||
|
PhysOutOfBounds,
|
||||||
|
PhysCollisionUpdate,
|
||||||
|
// Scene -> Physics Engine
|
||||||
|
PhysUpdateAttributes,
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Member Data
|
||||||
|
private MsgType m_type;
|
||||||
|
private byte[] m_data;
|
||||||
|
static ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public RegionSyncMessage(MsgType type, byte[] data)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionSyncMessage(MsgType type, string msg)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_data = System.Text.Encoding.ASCII.GetBytes(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionSyncMessage(MsgType type)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_data = new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionSyncMessage(Stream stream)
|
||||||
|
{
|
||||||
|
//ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
//try
|
||||||
|
{
|
||||||
|
m_type = (MsgType)Utils.BytesToInt(GetBytesFromStream(stream, 4));
|
||||||
|
int length = Utils.BytesToInt(GetBytesFromStream(stream, 4));
|
||||||
|
m_data = GetBytesFromStream(stream, length);
|
||||||
|
//log.WarnFormat("RegionSyncMessage Constructed {0} ({1} bytes)", m_type.ToString(), length);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.WarnFormat("[REGION SYNC MESSAGE] RegionSyncMessage Constructor encountered an exception {0}", e.Message);
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] GetBytesFromStream(Stream stream, int count)
|
||||||
|
{
|
||||||
|
// Loop to receive the message length
|
||||||
|
byte[] ret = new byte[count];
|
||||||
|
int i = 0;
|
||||||
|
while (i < count)
|
||||||
|
{
|
||||||
|
i += stream.Read(ret, i, count - i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Accessors
|
||||||
|
public MsgType Type
|
||||||
|
{
|
||||||
|
get { return m_type; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Length
|
||||||
|
{
|
||||||
|
get { return m_data.Length; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Data
|
||||||
|
{
|
||||||
|
get { return m_data; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Conversions
|
||||||
|
public byte[] ToBytes()
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[m_data.Length + 8];
|
||||||
|
Utils.IntToBytes((int)m_type, buf, 0);
|
||||||
|
Utils.IntToBytes(m_data.Length, buf, 4);
|
||||||
|
Array.Copy(m_data, 0, buf, 8, m_data.Length);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return String.Format("{0} ({1} bytes)", m_type.ToString(), m_data.Length.ToString());
|
||||||
|
}
|
||||||
|
public string ToStringFull()
|
||||||
|
{
|
||||||
|
return String.Format("{0}:{1})", m_type.ToString(), Encoding.ASCII.GetString(m_data));
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static void HandleSuccess(string header, RegionSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Handled {1}: {2}", header, msg.ToString(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleTrivial(string header, RegionSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Issue handling {1}: {2}", header, msg.ToString(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleWarning(string header, RegionSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Warning handling {1}: {2}", header, msg.ToString(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleError(string header, RegionSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Error handling {1}: {2}", header, msg.ToString(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HandlerDebug(string header, RegionSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} DBG ({1}): {2}", header, msg.ToString(), message);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
// The RegionSyncServer has a listener thread which accepts connections from RegionSyncClients
|
||||||
|
// and an additional thread to process updates to/from each RegionSyncClient.
|
||||||
|
public class RegionSyncServer
|
||||||
|
{
|
||||||
|
#region RegionSyncServer members
|
||||||
|
// Set the addr and port for TcpListener
|
||||||
|
private IPAddress m_addr;
|
||||||
|
private Int32 m_port;
|
||||||
|
|
||||||
|
private int clientCounter;
|
||||||
|
|
||||||
|
// The local scene.
|
||||||
|
private Scene m_scene;
|
||||||
|
private ILog m_log;
|
||||||
|
|
||||||
|
// The listener and the thread which listens for connections from client managers
|
||||||
|
private TcpListener m_listener;
|
||||||
|
private Thread m_listenerThread;
|
||||||
|
|
||||||
|
private DSGClientManagerLoadBalancer m_ClientBalancer;
|
||||||
|
|
||||||
|
// Check if any of the client views are in a connected state
|
||||||
|
public bool Synced
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (m_ClientBalancer.Count > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string LogHeader()
|
||||||
|
{
|
||||||
|
return String.Format("[REGION SYNC SERVER ({0})]", m_scene.RegionInfo.RegionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReportStats(System.IO.TextWriter tw)
|
||||||
|
{
|
||||||
|
tw.WriteLine("{0}: {1} TOTAL LOCAL REMOTE TO_SCENE FROM_SCENE", DateTime.Now.ToLongTimeString(), LogHeader());
|
||||||
|
tw.WriteLine("{0}: {1} MSGS ( /s ) BYTES ( Mbps ) MSGS ( /s ) BYTES ( Mbps ) QUEUE", DateTime.Now.ToLongTimeString(), LogHeader());
|
||||||
|
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv) {
|
||||||
|
{
|
||||||
|
tw.WriteLine("{0}: [{1}] {2}", DateTime.Now.ToLongTimeString(), rscv.Description, rscv.GetStats());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tw.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReportStatus()
|
||||||
|
{
|
||||||
|
int cvcount = m_ClientBalancer.Count;
|
||||||
|
m_log.ErrorFormat("{0} Connected to {1} remote client managers", LogHeader(), cvcount);
|
||||||
|
m_log.ErrorFormat("{0} Local scene contains {1} presences", LogHeader(), m_scene.SceneGraph.GetRootAgentCount());
|
||||||
|
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv){rscv.ReportStatus();});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public RegionSyncServer(Scene scene, string addr, int port, int maxClientsPerManager)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
m_scene = scene;
|
||||||
|
m_addr = IPAddress.Parse(addr);
|
||||||
|
m_port = port;
|
||||||
|
m_ClientBalancer = new DSGClientManagerLoadBalancer(maxClientsPerManager, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the server
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
m_listenerThread = new Thread(new ThreadStart(Listen));
|
||||||
|
m_listenerThread.Name = "RegionSyncServer Listener";
|
||||||
|
m_log.WarnFormat("{0} Starting {1} thread", LogHeader(), m_listenerThread.Name);
|
||||||
|
m_listenerThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Stop the server and disconnect all RegionSyncClients
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
// Stop the listener and listening thread so no new clients are accepted
|
||||||
|
m_listener.Stop();
|
||||||
|
m_listenerThread.Abort();
|
||||||
|
m_listenerThread = null;
|
||||||
|
|
||||||
|
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv)
|
||||||
|
{
|
||||||
|
// Each client view will clean up after itself
|
||||||
|
rscv.Shutdown();
|
||||||
|
m_ClientBalancer.RemoveSyncedClient(rscv);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for connections from a new RegionSyncClient
|
||||||
|
// When connected, start the ReceiveLoop for the new client
|
||||||
|
private void Listen()
|
||||||
|
{
|
||||||
|
m_listener = new TcpListener(m_addr, m_port);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Start listening for clients
|
||||||
|
m_listener.Start();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// *** Move/Add TRY/CATCH to here, but we don't want to spin loop on the same error
|
||||||
|
m_log.WarnFormat("{0} Listening for new connections on {1}:{2}...", LogHeader(), m_addr.ToString(), m_port.ToString());
|
||||||
|
TcpClient tcpclient = m_listener.AcceptTcpClient();
|
||||||
|
IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address;
|
||||||
|
int port = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Port;
|
||||||
|
// Add the RegionSyncClientView to the list of clients
|
||||||
|
// *** Need to work on the timing order of starting the client view and adding to the server list
|
||||||
|
// so that messages coming from the scene do not get lost before the client view is added but
|
||||||
|
// not sent before it is ready to process them.
|
||||||
|
RegionSyncClientView rscv = new RegionSyncClientView(++clientCounter, m_scene, tcpclient);
|
||||||
|
m_log.WarnFormat("{0} New connection from {1}", LogHeader(), rscv.Description);
|
||||||
|
m_ClientBalancer.AddSyncedClient(rscv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SocketException e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} [Listen] SocketException: {1}", LogHeader(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast a message to all connected RegionSyncClients
|
||||||
|
public void Broadcast(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
List<RegionSyncClientView> closed = null;
|
||||||
|
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv)
|
||||||
|
{
|
||||||
|
// If connected, send the message.
|
||||||
|
if (rscv.Connected)
|
||||||
|
{
|
||||||
|
rscv.Send(msg);
|
||||||
|
}
|
||||||
|
// Else, remove the client view from the list
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (closed == null)
|
||||||
|
closed = new List<RegionSyncClientView>();
|
||||||
|
closed.Add(rscv);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (closed != null)
|
||||||
|
{
|
||||||
|
foreach (RegionSyncClientView rscv in closed)
|
||||||
|
m_ClientBalancer.RemoveSyncedClient(rscv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast a message to all connected RegionSyncClients
|
||||||
|
public void EnqueuePresenceUpdate(UUID id, byte[] update)
|
||||||
|
{
|
||||||
|
List<RegionSyncClientView> closed = null;
|
||||||
|
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv)
|
||||||
|
{
|
||||||
|
// If connected, send the message.
|
||||||
|
if (rscv.Connected)
|
||||||
|
{
|
||||||
|
rscv.EnqueuePresenceUpdate(id, update);
|
||||||
|
}
|
||||||
|
// Else, remove the client view from the list
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (closed == null)
|
||||||
|
closed = new List<RegionSyncClientView>();
|
||||||
|
closed.Add(rscv);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (closed != null)
|
||||||
|
{
|
||||||
|
foreach (RegionSyncClientView rscv in closed)
|
||||||
|
m_ClientBalancer.RemoveSyncedClient(rscv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BalanceClients()
|
||||||
|
{
|
||||||
|
m_ClientBalancer.BalanceLoad();
|
||||||
|
}
|
||||||
|
//KittyL:
|
||||||
|
public void BroadcastToCM(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
|
||||||
|
{
|
||||||
|
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
|
||||||
|
|
||||||
|
//m_log.Debug("SOG " + sog.UUID);
|
||||||
|
|
||||||
|
RegionSyncMessage rsm = new RegionSyncMessage(msgType, sogxml);
|
||||||
|
Broadcast(rsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,559 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
using log4net;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
public class RegionSyncServerModule : IRegionModule, IRegionSyncServerModule, ICommandableModule
|
||||||
|
{
|
||||||
|
private static int DefaultPort = 13000;
|
||||||
|
public static string ActorID = "XX";
|
||||||
|
private static int PortUnknown = -1;
|
||||||
|
private static string IPAddrUnknown = "";
|
||||||
|
|
||||||
|
#region IRegionModule Members
|
||||||
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
// If no syncConfig, do not start up server mode
|
||||||
|
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||||
|
if (syncConfig == null)
|
||||||
|
{
|
||||||
|
scene.RegionSyncEnabled = false;
|
||||||
|
m_active = false;
|
||||||
|
m_log.Warn("[REGION SYNC SERVER MODULE] No RegionSyncModule config section found. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If syncConfig does not indicate "enabled", do not start up server mode
|
||||||
|
bool enabled = syncConfig.GetBoolean("Enabled", true);
|
||||||
|
if(!enabled)
|
||||||
|
{
|
||||||
|
scene.RegionSyncEnabled = false;
|
||||||
|
m_active = false;
|
||||||
|
m_log.Warn("[REGION SYNC SERVER MODULE] RegionSyncModule is not enabled. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get identifying actor ID whether in client or server mode
|
||||||
|
ActorID = syncConfig.GetString("ActorID", "ZZ");
|
||||||
|
|
||||||
|
// If syncConfig does not indicate "server", do not start up server mode
|
||||||
|
//string mode = syncConfig.GetString("Mode", "server").ToLower();
|
||||||
|
string mode = syncConfig.GetString("Mode", "").ToLower();
|
||||||
|
if(mode != "server")
|
||||||
|
{
|
||||||
|
//scene.RegionSyncEnabled = false;
|
||||||
|
m_active = false;
|
||||||
|
m_log.WarnFormat("[REGION SYNC SERVER MODULE] RegionSyncModule is in {0} mode. Shutting down.", mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable region sync in server mode on the scene and module
|
||||||
|
scene.RegionSyncEnabled = true;
|
||||||
|
scene.RegionSyncMode = mode;
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
// Init the sync statistics log file
|
||||||
|
string syncstats = "syncstats" + "_" + scene.RegionInfo.RegionName + ".txt";
|
||||||
|
m_statsWriter = File.AppendText(syncstats);
|
||||||
|
|
||||||
|
//Get sync server info for Client Manager actors
|
||||||
|
//string serverAddr = scene.RegionInfo.RegionName + "_ServerIPAddress";
|
||||||
|
//m_serveraddr = syncConfig.GetString(serverAddr, IPAddrUnknown);
|
||||||
|
//string serverPort = scene.RegionInfo.RegionName + "_ServerPort";
|
||||||
|
//m_serverport = syncConfig.GetInt(serverPort, PortUnknown);
|
||||||
|
|
||||||
|
// Client manager load balancing
|
||||||
|
m_maxClientsPerManager = syncConfig.GetInt("MaxClientsPerManager", 100);
|
||||||
|
DefaultPort++;
|
||||||
|
|
||||||
|
//Get sync server info for Script Engine actors
|
||||||
|
string seServerAddr = scene.RegionInfo.RegionName + "_SceneToSESyncServerIP";
|
||||||
|
m_seSyncServeraddr = syncConfig.GetString(seServerAddr, IPAddrUnknown);
|
||||||
|
string seServerPort = scene.RegionInfo.RegionName + "_SceneToSESyncServerPort";
|
||||||
|
m_seSyncServerport = syncConfig.GetInt(seServerPort, PortUnknown);
|
||||||
|
DefaultPort++;
|
||||||
|
|
||||||
|
//Get sync server info for Physics Engine actors
|
||||||
|
string peServerAddr = scene.RegionInfo.RegionName + "_SceneToPESyncServerIP";
|
||||||
|
m_peSyncServeraddr = syncConfig.GetString(peServerAddr, "127.0.0.1");
|
||||||
|
string peServerPort = scene.RegionInfo.RegionName + "_SceneToPESyncServerPort";
|
||||||
|
m_peSyncServerport = syncConfig.GetInt(peServerPort, DefaultPort);
|
||||||
|
DefaultPort++;
|
||||||
|
|
||||||
|
m_scene = scene;
|
||||||
|
m_scene.RegisterModuleInterface<IRegionSyncServerModule>(this);
|
||||||
|
|
||||||
|
// Setup the command line interface
|
||||||
|
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
|
InstallInterfaces();
|
||||||
|
|
||||||
|
//m_log.Warn("[REGION SYNC SERVER MODULE] Initialised");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//m_scene.EventManager.OnObjectBeingRemovedFromScene += new EventManager.ObjectBeingRemovedFromScene(EventManager_OnObjectBeingRemovedFromScene);
|
||||||
|
|
||||||
|
//m_scene.EventManager.OnAvatarEnteringNewParcel += new EventManager.AvatarEnteringNewParcel(EventManager_OnAvatarEnteringNewParcel);
|
||||||
|
//m_scene.EventManager.OnClientMovement += new EventManager.ClientMovement(EventManager_OnClientMovement);
|
||||||
|
//m_scene.EventManager.OnLandObjectAdded += new EventManager.LandObjectAdded(EventManager_OnLandObjectAdded);
|
||||||
|
//m_scene.EventManager.OnLandObjectRemoved += new EventManager.LandObjectRemoved(EventManager_OnLandObjectRemoved);
|
||||||
|
m_scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
|
||||||
|
//m_scene.EventManager.OnNewPresence += new EventManager.OnNewPresenceDelegate(EventManager_OnNewPresence);
|
||||||
|
m_scene.EventManager.OnRemovePresence += new EventManager.OnRemovePresenceDelegate(EventManager_OnRemovePresence);
|
||||||
|
|
||||||
|
// Start the server and listen for RegionSyncClients
|
||||||
|
m_serveraddr = m_scene.RegionInfo.AvatarSyncServerAddress;
|
||||||
|
m_serverport = m_scene.RegionInfo.AvatarSyncServerPort;
|
||||||
|
|
||||||
|
m_log.Debug("[REGION SYNC SERVER MODULE] to start server on " + m_serveraddr + ":" + m_serverport);
|
||||||
|
|
||||||
|
if (!m_serveraddr.Equals(IPAddrUnknown) && m_serverport != PortUnknown)
|
||||||
|
{
|
||||||
|
m_log.Warn("[REGION SYNC SERVER MODULE] Starting RegionSyncServer");
|
||||||
|
m_server = new RegionSyncServer(m_scene, m_serveraddr, m_serverport, m_maxClientsPerManager);
|
||||||
|
m_server.Start();
|
||||||
|
m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed);
|
||||||
|
m_statsTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_peSyncServeraddr = m_scene.RegionInfo.PhysicsSyncServerAddress;
|
||||||
|
m_peSyncServerport = m_scene.RegionInfo.PhysicsSyncServerPort;
|
||||||
|
if (!m_peSyncServeraddr.Equals(IPAddrUnknown) && m_peSyncServerport != PortUnknown)
|
||||||
|
{
|
||||||
|
m_log.Warn("[REGION SYNC SERVER MODULE] Starting SceneToPhysEngineSyncServer");
|
||||||
|
//Start the sync server for physics engines
|
||||||
|
m_sceneToPESyncServer = new SceneToPhysEngineSyncServer(m_scene, m_peSyncServeraddr, m_peSyncServerport);
|
||||||
|
m_sceneToPESyncServer.Start();
|
||||||
|
}
|
||||||
|
//m_log.Warn("[REGION SYNC SERVER MODULE] Post-Initialised");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StatsTimerElapsed(object source, System.Timers.ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
if (Synced)
|
||||||
|
m_server.ReportStats(m_statsWriter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRegionModule.Close()
|
||||||
|
{
|
||||||
|
m_scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "RegionSyncModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSharedModule
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//KittyL added
|
||||||
|
//Later, should make quarkIDs the argument to the function call
|
||||||
|
//public void SendResetScene()
|
||||||
|
//{
|
||||||
|
// m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.ResetScene, "reset"));
|
||||||
|
//}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICommandableModule Members
|
||||||
|
private readonly Commander m_commander = new Commander("sync");
|
||||||
|
public ICommander CommandInterface
|
||||||
|
{
|
||||||
|
get { return m_commander; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IRegionSyncServerModule members
|
||||||
|
// Lock is used to synchronize access to the update status and both update queues
|
||||||
|
private object m_updateLock = new object();
|
||||||
|
private int m_sendingUpdates;
|
||||||
|
//private Dictionary<UUID, SceneObjectGroup> m_primUpdates = new Dictionary<UUID, SceneObjectGroup>();
|
||||||
|
private Dictionary<UUID, ScenePresence> m_presenceUpdates = new Dictionary<UUID, ScenePresence>();
|
||||||
|
|
||||||
|
private System.Timers.Timer m_statsTimer = new System.Timers.Timer(1000);
|
||||||
|
//private TextWriter m_statsWriter = File.AppendText("syncstats.txt");
|
||||||
|
private TextWriter m_statsWriter;
|
||||||
|
|
||||||
|
|
||||||
|
public void QueuePresenceForTerseUpdate(ScenePresence presence)
|
||||||
|
{
|
||||||
|
if (!Active || !Synced)
|
||||||
|
return;
|
||||||
|
lock (m_updateLock)
|
||||||
|
{
|
||||||
|
m_presenceUpdates[presence.UUID] = presence;
|
||||||
|
}
|
||||||
|
//m_log.DebugFormat("[REGION SYNC SERVER MODULE] QueuePresenceForUpdate: {0}", presence.UUID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a teleport message out. This should only be called when teleporting within the same region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="presence"></param>
|
||||||
|
public void SendTeleportUpdate(ScenePresence presence)
|
||||||
|
{
|
||||||
|
if (!Active || !Synced)
|
||||||
|
return;
|
||||||
|
|
||||||
|
System.Threading.ThreadPool.QueueUserWorkItem(delegate
|
||||||
|
{
|
||||||
|
OSDMap data = new OSDMap(10);
|
||||||
|
data["id"] = OSD.FromUUID(presence.UUID);
|
||||||
|
// Do not include offset for appearance height. That will be handled by RegionSyncClient before sending to viewers
|
||||||
|
if (presence.AbsolutePosition.IsFinite())
|
||||||
|
data["pos"] = OSD.FromVector3(presence.AbsolutePosition);
|
||||||
|
else
|
||||||
|
data["pos"] = OSD.FromVector3(Vector3.Zero);
|
||||||
|
/*
|
||||||
|
if (presence.Velocity.IsFinite())
|
||||||
|
data["vel"] = OSD.FromVector3(presence.Velocity);
|
||||||
|
else
|
||||||
|
data["vel"] = OSD.FromVector3(Vector3.Zero);
|
||||||
|
if (System.Single.IsNaN(presence.Rotation.X))
|
||||||
|
data["rot"] = OSD.FromQuaternion(Quaternion.Identity);
|
||||||
|
else
|
||||||
|
data["rot"] = OSD.FromQuaternion(presence.Rotation);
|
||||||
|
data["fly"] = OSD.FromBoolean(presence.Flying);
|
||||||
|
data["flags"] = OSD.FromUInteger((uint)presence.AgentControlFlags);
|
||||||
|
data["anim"] = OSD.FromString(presence.Animator.CurrentMovementAnimation);
|
||||||
|
// needed for a full update
|
||||||
|
if (presence.ParentID != presence.lastSentParentID)
|
||||||
|
{
|
||||||
|
data["coll"] = OSD.FromVector4(presence.CollisionPlane);
|
||||||
|
data["off"] = OSD.FromVector3(presence.OffsetPosition);
|
||||||
|
data["pID"] = OSD.FromUInteger(presence.ParentID);
|
||||||
|
presence.lastSentParentID = presence.ParentID;
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
|
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.AvatarTeleportSameRegion, OSDParser.SerializeJsonString(data));
|
||||||
|
|
||||||
|
m_server.Broadcast(rsm);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendUpdates()
|
||||||
|
{
|
||||||
|
if (!Active || !Synced)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Existing value of 1 indicates that updates are currently being sent so skip updates this pass
|
||||||
|
if (Interlocked.Exchange(ref m_sendingUpdates, 1) == 1)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[REGION SYNC SERVER MODULE] SendUpdates(): An update thread is already running.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SceneObjectGroup> primUpdates;
|
||||||
|
List<ScenePresence> presenceUpdates;
|
||||||
|
|
||||||
|
lock (m_updateLock)
|
||||||
|
{
|
||||||
|
//primUpdates = new List<SceneObjectGroup>(m_primUpdates.Values);
|
||||||
|
presenceUpdates = new List<ScenePresence>(m_presenceUpdates.Values);
|
||||||
|
//m_primUpdates.Clear();
|
||||||
|
m_presenceUpdates.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This could be another thread for sending outgoing messages or just have the Queue functions
|
||||||
|
// create and queue the messages directly into the outgoing server thread.
|
||||||
|
System.Threading.ThreadPool.QueueUserWorkItem(delegate
|
||||||
|
{
|
||||||
|
// Sending the message when it's first queued would yield lower latency but much higher load on the simulator
|
||||||
|
// as parts may be updated many many times very quickly. Need to implement a higher resolution send in heartbeat
|
||||||
|
|
||||||
|
foreach (ScenePresence presence in presenceUpdates)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!presence.IsDeleted)
|
||||||
|
{
|
||||||
|
OSDMap data = new OSDMap(10);
|
||||||
|
data["id"] = OSD.FromUUID(presence.UUID);
|
||||||
|
// Do not include offset for appearance height. That will be handled by RegionSyncClient before sending to viewers
|
||||||
|
if(presence.AbsolutePosition.IsFinite())
|
||||||
|
data["pos"] = OSD.FromVector3(presence.AbsolutePosition);
|
||||||
|
else
|
||||||
|
data["pos"] = OSD.FromVector3(Vector3.Zero);
|
||||||
|
if(presence.Velocity.IsFinite())
|
||||||
|
data["vel"] = OSD.FromVector3(presence.Velocity);
|
||||||
|
else
|
||||||
|
data["vel"] = OSD.FromVector3(Vector3.Zero);
|
||||||
|
if(System.Single.IsNaN(presence.Rotation.X))
|
||||||
|
data["rot"] = OSD.FromQuaternion(Quaternion.Identity);
|
||||||
|
else
|
||||||
|
data["rot"] = OSD.FromQuaternion(presence.Rotation);
|
||||||
|
data["fly"] = OSD.FromBoolean(presence.Flying);
|
||||||
|
data["flags"] = OSD.FromUInteger((uint)presence.AgentControlFlags);
|
||||||
|
data["anim"] = OSD.FromString(presence.Animator.CurrentMovementAnimation);
|
||||||
|
// needed for a full update
|
||||||
|
if (presence.ParentID != presence.lastSentParentID)
|
||||||
|
{
|
||||||
|
data["coll"] = OSD.FromVector4(presence.CollisionPlane);
|
||||||
|
data["off"] = OSD.FromVector3(presence.OffsetPosition);
|
||||||
|
data["pID"] = OSD.FromUInteger(presence.ParentID);
|
||||||
|
presence.lastSentParentID = presence.ParentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.UpdatedAvatar, OSDParser.SerializeJsonString(data));
|
||||||
|
m_server.EnqueuePresenceUpdate(presence.UUID, rsm.ToBytes());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[REGION SYNC SERVER MODULE] Caught exception sending presence updates for {0}: {1}", presence.Name, e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Indicate that the current batch of updates has been completed
|
||||||
|
Interlocked.Exchange(ref m_sendingUpdates, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<UUID, System.Threading.Timer> m_appearanceTimers = new Dictionary<UUID, Timer>();
|
||||||
|
|
||||||
|
public void SendAppearance(UUID agentID)
|
||||||
|
{
|
||||||
|
OSDMap data = new OSDMap(1);
|
||||||
|
data["id"] = OSDUUID.FromUUID(agentID);
|
||||||
|
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.AvatarAppearance, OSDParser.SerializeJsonString(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendAnimations(UUID agentID, UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
|
||||||
|
{
|
||||||
|
OSDMap data = new OSDMap();
|
||||||
|
data["agentID"] = OSD.FromUUID(agentID);
|
||||||
|
OSDArray animatA = new OSDArray();
|
||||||
|
foreach (UUID uu in animations) animatA.Add(OSD.FromUUID(uu));
|
||||||
|
data["animations"] = animatA;
|
||||||
|
OSDArray seqsA = new OSDArray();
|
||||||
|
foreach (int ss in seqs) seqsA.Add(OSD.FromInteger(ss));
|
||||||
|
data["seqs"] = seqsA;
|
||||||
|
data["sourceAgentID"] = OSD.FromUUID(sourceAgentId);
|
||||||
|
OSDArray obIDA = new OSDArray();
|
||||||
|
foreach (UUID ii in objectIDs) obIDA.Add(OSD.FromUUID(ii));
|
||||||
|
data["objectIDs"] = obIDA;
|
||||||
|
// m_log.DebugFormat("[REGION SYNC SERVER MODULE] Broadcast animations for {0}", agentID.ToString());
|
||||||
|
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.SendAnimations, OSDParser.SerializeJsonString(data));
|
||||||
|
m_server.Broadcast(rsm);
|
||||||
|
// m_clientView.Send(rsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Active
|
||||||
|
{
|
||||||
|
get { return m_active; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the sync server module is connected to any clients (KittyL: edited for testing if connected to any actors)
|
||||||
|
public bool Synced
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_server == null || !m_server.Synced)
|
||||||
|
//if((m_server == null || !m_server.Synced) && (m_sceneToSESyncServer==null || !m_sceneToSESyncServer.Synced))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public void SendLoadWorldMap(ITerrainChannel heightMap)
|
||||||
|
{
|
||||||
|
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString());
|
||||||
|
if(m_server!=null)
|
||||||
|
m_server.Broadcast(msg);
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region RegionSyncServerModule members
|
||||||
|
private bool m_active = true;
|
||||||
|
private string m_serveraddr;
|
||||||
|
private int m_serverport;
|
||||||
|
private int m_maxClientsPerManager;
|
||||||
|
private Scene m_scene;
|
||||||
|
//private IClientAPI m_clientAggregator;
|
||||||
|
private ILog m_log;
|
||||||
|
//private int m_moveCounter = 0;
|
||||||
|
private RegionSyncServer m_server = null;
|
||||||
|
|
||||||
|
//Sync-server for script engines
|
||||||
|
private string m_seSyncServeraddr;
|
||||||
|
private int m_seSyncServerport;
|
||||||
|
//private SceneToScriptEngineSyncServer m_sceneToSESyncServer = null;
|
||||||
|
|
||||||
|
//Sync-server for physics engines
|
||||||
|
private string m_peSyncServeraddr;
|
||||||
|
private int m_peSyncServerport;
|
||||||
|
private SceneToPhysEngineSyncServer m_sceneToPESyncServer = null;
|
||||||
|
|
||||||
|
//a boolean variable to indicate in symmetric sync is configured
|
||||||
|
//private bool m_symsync = false;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Event Handlers
|
||||||
|
|
||||||
|
// A ficticious event
|
||||||
|
public void Scene_AddNewPrim(SceneObjectGroup sog)
|
||||||
|
{
|
||||||
|
if (!Synced)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EventManager_OnNewPresence(ScenePresence presence)
|
||||||
|
{
|
||||||
|
if (!Synced)
|
||||||
|
return;
|
||||||
|
m_log.WarnFormat("[REGION SYNC SERVER MODULE] (OneNewPresence) \"{0}\"", presence.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EventManager_OnNewClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
if (!Synced)
|
||||||
|
return;
|
||||||
|
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Agent \"{0}\" {1} has joined the scene", client.FirstName + " " + client.LastName, client.AgentId.ToString());
|
||||||
|
// Let the client managers know that a new agent has connected
|
||||||
|
OSDMap data = new OSDMap(1);
|
||||||
|
data["agentID"] = OSD.FromUUID(client.AgentId);
|
||||||
|
data["localID"] = OSD.FromUInteger(m_scene.GetScenePresence(client.AgentId).LocalId);
|
||||||
|
data["first"] = OSD.FromString(client.FirstName);
|
||||||
|
data["last"] = OSD.FromString(client.LastName);
|
||||||
|
data["startPos"] = OSD.FromVector3(client.StartPos);
|
||||||
|
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.NewAvatar, OSDParser.SerializeJsonString(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EventManager_OnRemovePresence(UUID agentID)
|
||||||
|
{
|
||||||
|
if (!Synced)
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
ScenePresence avatar;
|
||||||
|
if (m_scene.TryGetScenePresence(agentID, out avatar))
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Avatar \"{0}\" {1} {2} has left the scene", avatar.Firstname + " " + avatar.Lastname, agentID.ToString(), avatar.UUID.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Avatar \"unknown\" has left the scene");
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
OSDMap data = new OSDMap();
|
||||||
|
data["agentID"] = OSD.FromUUID(agentID);
|
||||||
|
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.RemovedAvatar, OSDParser.SerializeJsonString(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Console Command Interface
|
||||||
|
private void InstallInterfaces()
|
||||||
|
{
|
||||||
|
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Reports current status of the RegionSyncServer.");
|
||||||
|
Command cmdBalanceClients = new Command("balance", CommandIntentions.COMMAND_HAZARDOUS, BalanceClients, "Balance client load across available client managers.");
|
||||||
|
m_commander.RegisterCommand("status", cmdSyncStatus);
|
||||||
|
m_commander.RegisterCommand("balance", cmdBalanceClients);
|
||||||
|
|
||||||
|
lock (m_scene)
|
||||||
|
{
|
||||||
|
// Add this to our scene so scripts can call these functions
|
||||||
|
m_scene.RegisterModuleCommander(m_commander);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes commandline input. Do not call directly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">Commandline arguments</param>
|
||||||
|
private void EventManager_OnPluginConsole(string[] args)
|
||||||
|
{
|
||||||
|
if (args[0] == "sync")
|
||||||
|
{
|
||||||
|
if (args.Length == 1)
|
||||||
|
{
|
||||||
|
m_commander.ProcessConsoleCommand("help", new string[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] tmpArgs = new string[args.Length - 2];
|
||||||
|
int i;
|
||||||
|
for (i = 2; i < args.Length; i++)
|
||||||
|
tmpArgs[i - 2] = args[i];
|
||||||
|
|
||||||
|
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStatus(Object[] args)
|
||||||
|
{
|
||||||
|
if (Synced)
|
||||||
|
m_server.ReportStatus();
|
||||||
|
else
|
||||||
|
m_log.Error("No RegionSyncClients connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BalanceClients(Object[] args)
|
||||||
|
{
|
||||||
|
if (Synced)
|
||||||
|
m_server.BalanceClients();
|
||||||
|
else
|
||||||
|
m_log.Error("No RegionSyncClients connected");
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
class RegionSyncUtil
|
||||||
|
{
|
||||||
|
// The logfile
|
||||||
|
private static ILog m_log;
|
||||||
|
|
||||||
|
//HashSet<string> exceptions = new HashSet<string>();
|
||||||
|
public static OSDMap DeserializeMessage(RegionSyncMessage msg, string logHeader)
|
||||||
|
{
|
||||||
|
OSDMap data = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Error(logHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,535 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.Packets;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//KittyL: NOTE -- We need to define an interface for all actors to connect into the Scene,
|
||||||
|
// e.g. IActorConnector, that runs on the Scene side, processes messages from actors,
|
||||||
|
// and apply Scene/Object operations.
|
||||||
|
|
||||||
|
// The SceneToPhysEngineConnector acts as a thread on the RegionSyncServer to handle incoming
|
||||||
|
// messages from PhysEngineToSceneConnectors that run on Physics Engines. It connects the
|
||||||
|
// authoratative Scene with remote script engines.
|
||||||
|
public class SceneToPhysEngineConnector : ISyncStatistics
|
||||||
|
{
|
||||||
|
#region SceneToPhysEngineConnector members
|
||||||
|
|
||||||
|
object stats = new object();
|
||||||
|
private DateTime lastStatTime;
|
||||||
|
private long msgsIn;
|
||||||
|
private long msgsOut;
|
||||||
|
private long bytesIn;
|
||||||
|
private long bytesOut;
|
||||||
|
private long pollBlocks;
|
||||||
|
|
||||||
|
private int msgCount = 0;
|
||||||
|
|
||||||
|
// The TcpClient this view uses to communicate with its RegionSyncClient
|
||||||
|
private TcpClient m_tcpclient;
|
||||||
|
// Set the addr and port for TcpListener
|
||||||
|
private IPAddress m_addr;
|
||||||
|
private Int32 m_port;
|
||||||
|
private static int m_connection_number = 0;
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
object m_syncRoot = new object();
|
||||||
|
Dictionary<UUID, RegionSyncAvatar> m_syncedAvatars = new Dictionary<UUID, RegionSyncAvatar>();
|
||||||
|
|
||||||
|
// A queue for incoming and outgoing traffic
|
||||||
|
private OpenMetaverse.BlockingQueue<RegionSyncMessage> inbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
|
||||||
|
private OpenMetaverse.BlockingQueue<RegionSyncMessage> outbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
|
||||||
|
|
||||||
|
private ILog m_log;
|
||||||
|
|
||||||
|
private Thread m_receive_loop;
|
||||||
|
private string m_regionName;
|
||||||
|
|
||||||
|
private SceneToPhysEngineSyncServer m_syncServer = null;
|
||||||
|
|
||||||
|
// A string of the format [REGION SYNC SCRIPT API (regionname)] for use in log headers
|
||||||
|
private string LogHeader
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_regionName == null)
|
||||||
|
return String.Format("[SceneToPhysEngineConnector #{0}]", m_connection_number);
|
||||||
|
return String.Format("[SceneToPhysEngineConnector #{0} ({1:10})]", m_connection_number, m_regionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A string of the format "RegionSyncClientView #X" for use in describing the object itself
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_regionName == null)
|
||||||
|
return String.Format("RegionSyncPhysAPI #{0}", m_connection_number);
|
||||||
|
return String.Format("RegionSyncPhysAPI #{0} ({1:10})", m_connection_number, m_regionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ConnectionNum
|
||||||
|
{
|
||||||
|
get { return m_connection_number; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StatisticIdentifier()
|
||||||
|
{
|
||||||
|
return "SceneToPhysEngineConnector" + ConnectionNum.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StatisticLine(bool clearFlag)
|
||||||
|
{
|
||||||
|
string ret = "";
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds;
|
||||||
|
lastStatTime = DateTime.Now;
|
||||||
|
|
||||||
|
ret = String.Format("{0},{1},{2},{3},{4}",
|
||||||
|
msgsIn, msgsOut, bytesIn, bytesOut, pollBlocks
|
||||||
|
);
|
||||||
|
if (clearFlag)
|
||||||
|
msgsIn = msgsOut = bytesIn = bytesOut = pollBlocks = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StatisticTitle()
|
||||||
|
{
|
||||||
|
return "msgsIn,msgsOut,bytesIn,bytesOut,pollBlocks";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the client is connected
|
||||||
|
public bool Connected
|
||||||
|
{ get { return m_tcpclient.Connected; } }
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public SceneToPhysEngineConnector(int num, Scene scene, TcpClient client, SceneToPhysEngineSyncServer syncServer)
|
||||||
|
{
|
||||||
|
m_connection_number = num;
|
||||||
|
m_scene = scene;
|
||||||
|
m_tcpclient = client;
|
||||||
|
m_addr = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
|
||||||
|
m_port = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
|
||||||
|
m_syncServer = syncServer;
|
||||||
|
|
||||||
|
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
//m_log.WarnFormat("{0} Constructed", LogHeader);
|
||||||
|
|
||||||
|
//Register for events from Scene.EventManager
|
||||||
|
//m_scene.EventManager.OnRezScript += SEConnectorOnRezScript;
|
||||||
|
//m_scene.EventManager.OnScriptReset += SEConnectorOnScriptReset;
|
||||||
|
//m_scene.EventManager.OnUpdateScript += SEConnectorOnUpdateScript;
|
||||||
|
|
||||||
|
// Create a thread for the receive loop
|
||||||
|
m_receive_loop = new Thread(new ThreadStart(delegate() { ReceiveLoop(); }));
|
||||||
|
m_receive_loop.Name = Description;
|
||||||
|
//m_log.WarnFormat("{0} Started thread: {1}", LogHeader, m_receive_loop.Name);
|
||||||
|
m_receive_loop.Start();
|
||||||
|
|
||||||
|
SyncStatisticCollector.Register(this);
|
||||||
|
|
||||||
|
//tell the remote script engine about the locX, locY of this authoritative scene
|
||||||
|
// SendSceneLoc();
|
||||||
|
m_log.DebugFormat("{0}: SceneToPhysEngineConnector initialized", LogHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the listening thread, disconnecting the RegionSyncPhysEngine
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
m_syncServer.RemoveSyncedPhysEngine(this);
|
||||||
|
// m_scene.EventManager.OnChatFromClient -= EventManager_OnChatFromClient;
|
||||||
|
// Abort ReceiveLoop Thread, close Socket and TcpClient
|
||||||
|
m_receive_loop.Abort();
|
||||||
|
m_tcpclient.Client.Close();
|
||||||
|
m_tcpclient.Close();
|
||||||
|
|
||||||
|
//m_scene.EventManager.OnRezScript -= SEConnectorOnRezScript;
|
||||||
|
//m_scene.EventManager.OnScriptReset -= SEConnectorOnScriptReset;
|
||||||
|
//m_scene.EventManager.OnUpdateScript -= SEConnectorOnUpdateScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Send/Receive messages to/from the remote Physics Engine
|
||||||
|
|
||||||
|
// Listen for messages from a RegionSyncClient
|
||||||
|
// *** This is the main thread loop for each connected client
|
||||||
|
private void ReceiveLoop()
|
||||||
|
{
|
||||||
|
//m_scene.EventManager.OnChatFromClient += new EventManager.ChatFromClientEvent(EventManager_OnChatFromClient);
|
||||||
|
|
||||||
|
// Reset stats and time
|
||||||
|
lastStatTime = DateTime.Now;
|
||||||
|
msgsIn = msgsOut = bytesIn = bytesOut = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
RegionSyncMessage msg = GetMessage();
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
msgsIn++;
|
||||||
|
bytesIn += msg.Length;
|
||||||
|
}
|
||||||
|
lock (m_syncRoot)
|
||||||
|
HandleMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: has disconnected: {1}", LogHeader, e.Message);
|
||||||
|
}
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a message from the RegionSyncClient
|
||||||
|
private RegionSyncMessage GetMessage()
|
||||||
|
{
|
||||||
|
// Get a RegionSyncMessager from the incoming stream
|
||||||
|
RegionSyncMessage msg = new RegionSyncMessage(m_tcpclient.GetStream());
|
||||||
|
//m_log.WarnFormat("{0} Received {1}", LogHeader, msg.ToString());
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle an incoming message
|
||||||
|
// *** Perhaps this should not be synchronous with the receive
|
||||||
|
// We could handle messages from an incoming Queue
|
||||||
|
private void HandleMessage(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
SceneToPhysEngineSyncServer.PhysLogMessage(true, msg);
|
||||||
|
msgCount++;
|
||||||
|
//string handlerMessage = "";
|
||||||
|
switch (msg.Type)
|
||||||
|
{
|
||||||
|
case RegionSyncMessage.MsgType.ActorStop:
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
case RegionSyncMessage.MsgType.LoadBalanceRequest:
|
||||||
|
{
|
||||||
|
m_syncServer.HandleLoadBalanceRequest(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RegionSyncMessage.MsgType.ActorStatus:
|
||||||
|
{
|
||||||
|
string status = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
|
||||||
|
ActorStatus actorStatus = (ActorStatus)Convert.ToInt32(status);
|
||||||
|
if (actorStatus == ActorStatus.Sync)
|
||||||
|
{
|
||||||
|
m_log.Debug(LogHeader + ": received ActorStatus " + actorStatus.ToString());
|
||||||
|
m_syncServer.AddSyncedPhysEngine(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": not supposed to received RegionSyncMessage.MsgType.ActorStatus==" + status.ToString());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
case RegionSyncMessage.MsgType.PhysTerseUpdate:
|
||||||
|
{
|
||||||
|
HandlePhysTerseUpdate(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.PhysOutOfBounds:
|
||||||
|
{
|
||||||
|
HandlePhysOutOfBounds(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.PhysCollisionUpdate:
|
||||||
|
{
|
||||||
|
HandlePhysCollisionUpdate(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RegionSyncMessage.MsgType.PhysUpdateAttributes:
|
||||||
|
{
|
||||||
|
HandlePhysUpdateAttributes(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Unable to handle unsupported message type", LogHeader);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandlePhysTerseUpdate(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UUID uuid = data["uuid"].AsUUID();
|
||||||
|
// m_log.DebugFormat("{0}: received PhysUpdateAttributes for {1}", LogHeader, uuid);
|
||||||
|
PhysicsActor pa = FindPhysicsActor(uuid);
|
||||||
|
if (pa != null)
|
||||||
|
{
|
||||||
|
pa.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: terse update for unknown uuid {1}", LogHeader, uuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: EXCEPTION processing PhysTerseUpdate: {1}", LogHeader, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandlePhysOutOfBounds(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandlePhysCollisionUpdate(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The physics engine has some updates to the attributes. Unpack the parameters, find the
|
||||||
|
/// correct PhysicsActor and plug in the new values;
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="msg"></param>
|
||||||
|
private void HandlePhysUpdateAttributes(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UUID uuid = data["uuid"].AsUUID();
|
||||||
|
string actorID = data["actorID"].AsString();
|
||||||
|
// m_log.DebugFormat("{0}: received PhysUpdateAttributes for {1}", LogHeader, uuid);
|
||||||
|
PhysicsActor pa = FindPhysicsActor(uuid);
|
||||||
|
if (pa != null)
|
||||||
|
{
|
||||||
|
if (pa.PhysicsActorType == (int)ActorTypes.Prim)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: HandlePhysUpdateAttributes for an prim: {1}", LogHeader, pa.UUID);
|
||||||
|
}
|
||||||
|
pa.Size = data["size"].AsVector3();
|
||||||
|
pa.Position = data["position"].AsVector3();
|
||||||
|
pa.Force = data["force"].AsVector3();
|
||||||
|
pa.Velocity = data["velocity"].AsVector3();
|
||||||
|
pa.RotationalVelocity = data["rotationalVelocity"].AsVector3();
|
||||||
|
pa.Acceleration = data["acceleration"].AsVector3();
|
||||||
|
pa.Torque = data["torque"].AsVector3();
|
||||||
|
pa.Orientation = data["orientation"].AsQuaternion();
|
||||||
|
pa.IsPhysical = data["isPhysical"].AsBoolean(); // receive??
|
||||||
|
pa.Flying = data["flying"].AsBoolean(); // receive??
|
||||||
|
pa.Kinematic = data["kinematic"].AsBoolean(); // receive??
|
||||||
|
pa.Buoyancy = (float)(data["buoyancy"].AsReal());
|
||||||
|
pa.CollidingGround = data["isCollidingGround"].AsBoolean();
|
||||||
|
pa.IsColliding = data["isColliding"].AsBoolean();
|
||||||
|
pa.ChangingActorID = actorID;
|
||||||
|
|
||||||
|
pa.RequestPhysicsterseUpdate(); // tell the system the values have changed
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: attribute update for unknown uuid {1}", LogHeader, uuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: EXCEPTION processing UpdateAttributes: {1}", LogHeader, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the physics actor whether it is an object or a scene presence
|
||||||
|
private PhysicsActor FindPhysicsActor(UUID uuid)
|
||||||
|
{
|
||||||
|
SceneObjectPart sop = m_scene.GetSceneObjectPart(uuid);
|
||||||
|
if (sop != null)
|
||||||
|
{
|
||||||
|
return sop.PhysActor;
|
||||||
|
}
|
||||||
|
ScenePresence sp = m_scene.GetScenePresence(uuid);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
return sp.PhysicsActor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendPhysUpdateAttributes(PhysicsActor pa)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: sending PhysUpdateAttributes for {1}", LogHeader, pa.UUID);
|
||||||
|
if (pa.PhysicsActorType == (int)ActorTypes.Prim)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: SendPhysUpdateAttributes for an prim: {1}", LogHeader, pa.UUID);
|
||||||
|
}
|
||||||
|
OSDMap data = new OSDMap(15);
|
||||||
|
data["time"] = OSD.FromString(DateTime.Now.ToString("yyyyMMddHHmmssfff"));
|
||||||
|
data["localID"] = OSD.FromUInteger(pa.LocalID);
|
||||||
|
data["uuid"] = OSD.FromUUID(pa.UUID);
|
||||||
|
data["actorID"] = OSD.FromString(RegionSyncServerModule.ActorID);
|
||||||
|
data["size"] = OSD.FromVector3(pa.Size);
|
||||||
|
data["position"] = OSD.FromVector3(pa.Position);
|
||||||
|
data["force"] = OSD.FromVector3(pa.Force);
|
||||||
|
data["velocity"] = OSD.FromVector3(pa.Velocity);
|
||||||
|
data["rotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity);
|
||||||
|
data["acceleration"] = OSD.FromVector3(pa.Acceleration);
|
||||||
|
data["torque"] = OSD.FromVector3(pa.Torque);
|
||||||
|
data["orientation"] = OSD.FromQuaternion(pa.Orientation);
|
||||||
|
data["isPhysical"] = OSD.FromBoolean(pa.IsPhysical);
|
||||||
|
data["flying"] = OSD.FromBoolean(pa.Flying);
|
||||||
|
data["buoyancy"] = OSD.FromReal(pa.Buoyancy);
|
||||||
|
data["isColliding"] = OSD.FromBoolean(pa.IsColliding);
|
||||||
|
data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("SendPhysUpdateAttributes, ChangingActorID = {0}, with PA at pos {1}, data.position={2}", pa.ChangingActorID, pa.Position, data["position"].AsVector3().ToString());
|
||||||
|
|
||||||
|
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,
|
||||||
|
OSDParser.SerializeJsonString(data));
|
||||||
|
Send(rsm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RegionSyncMessage PrepareObjectUpdateMessage(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
|
||||||
|
{
|
||||||
|
OSDMap data = new OSDMap(3);
|
||||||
|
data["locX"] = OSD.FromUInteger(m_scene.RegionInfo.RegionLocX);
|
||||||
|
data["locY"] = OSD.FromUInteger(m_scene.RegionInfo.RegionLocY);
|
||||||
|
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
|
||||||
|
data["sogXml"] = OSD.FromString(sogxml);
|
||||||
|
|
||||||
|
RegionSyncMessage rsm = new RegionSyncMessage(msgType, OSDParser.SerializeJsonString(data));
|
||||||
|
return rsm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendSceneLoc()
|
||||||
|
{
|
||||||
|
uint locX = m_scene.RegionInfo.RegionLocX;
|
||||||
|
uint locY = m_scene.RegionInfo.RegionLocY;
|
||||||
|
|
||||||
|
OSDMap data = new OSDMap(2);
|
||||||
|
data["locX"] = OSD.FromUInteger(locX);
|
||||||
|
data["locY"] = OSD.FromUInteger(locY);
|
||||||
|
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.SceneLocation, OSDParser.SerializeJsonString(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
if (msg.Type == RegionSyncMessage.MsgType.AvatarAppearance)
|
||||||
|
m_log.WarnFormat("{0} Sending AvatarAppearance to client manager", LogHeader);
|
||||||
|
|
||||||
|
Send(msg.ToBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Send(byte[] data)
|
||||||
|
{
|
||||||
|
if (m_tcpclient.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
msgsOut++;
|
||||||
|
bytesOut += data.Length;
|
||||||
|
}
|
||||||
|
m_tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar =>
|
||||||
|
{
|
||||||
|
if (m_tcpclient.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_tcpclient.GetStream().EndWrite(ar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Write to output stream failed", LogHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Physics Engine has disconnected.", LogHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("{0} Attempt to send with no connection", LogHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendObjectUpdate(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
|
||||||
|
{
|
||||||
|
Send(PrepareObjectUpdateMessage(msgType, sog));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Send/Receive messages to/from the remote Physics Engine
|
||||||
|
|
||||||
|
#region Load balancing functions
|
||||||
|
/*
|
||||||
|
public void SendLoadBalanceRejection(string response)
|
||||||
|
{
|
||||||
|
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceRejection, response);
|
||||||
|
Send(msg);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,749 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
//Information of a registered idle physics engine.
|
||||||
|
//Note, this is a temporary solution to inlcude idle physics engines here.
|
||||||
|
//In the future, there might be a independent load balaner that keeps track
|
||||||
|
//of available idle hardware.
|
||||||
|
public class IdlePhysEngineInfo
|
||||||
|
{
|
||||||
|
public TcpClient TClient;
|
||||||
|
//public IPAddress PhysEngineIPAddr;
|
||||||
|
//public int PhysEnginePort;
|
||||||
|
public string ID;
|
||||||
|
|
||||||
|
//Will be used to store the overloaded PE that has send LB request and paired with this idle PE
|
||||||
|
public SceneToPhysEngineConnector AwaitOverloadedSE=null;
|
||||||
|
|
||||||
|
public IdlePhysEngineInfo(TcpClient tclient)
|
||||||
|
{
|
||||||
|
if(tclient==null) return;
|
||||||
|
TClient = tclient;
|
||||||
|
IPAddress ipAddr = ((IPEndPoint)tclient.Client.RemoteEndPoint).Address;
|
||||||
|
int port = ((IPEndPoint)tclient.Client.RemoteEndPoint).Port;
|
||||||
|
ID = ipAddr.ToString()+":"+port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Here is the per actor type listening server for physics Engines.
|
||||||
|
public class SceneToPhysEngineSyncServer : ISceneToPhysEngineServer, ICommandableModule
|
||||||
|
{
|
||||||
|
#region SceneToPhysEngineSyncServer members
|
||||||
|
// Set the addr and port for TcpListener
|
||||||
|
private IPAddress m_addr;
|
||||||
|
private Int32 m_port;
|
||||||
|
|
||||||
|
//this field is only meaning for the QuarkInfo records on the Scene side
|
||||||
|
private SceneToPhysEngineConnector m_peConnector=null;
|
||||||
|
public SceneToPhysEngineConnector PEConnector
|
||||||
|
{
|
||||||
|
get { return m_peConnector; }
|
||||||
|
set { m_peConnector = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int peCounter;
|
||||||
|
|
||||||
|
// static counters that are used to compute global configuration state
|
||||||
|
private static int m_syncServerInitialized = 0;
|
||||||
|
private static int m_totalConnections = 0;
|
||||||
|
private static List<Scene> m_allScenes = new List<Scene>();
|
||||||
|
|
||||||
|
// The local scene.
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
private ILog m_log;
|
||||||
|
|
||||||
|
// The listener and the thread which listens for connections from client managers
|
||||||
|
private TcpListener m_listener;
|
||||||
|
private Thread m_listenerThread;
|
||||||
|
|
||||||
|
private object m_physEngineConnector_lock = new object();
|
||||||
|
//private Dictionary<string, SceneToPhysEngineConnector> m_physEngineConnectors = new Dictionary<string, SceneToPhysEngineConnector>();
|
||||||
|
private List<SceneToPhysEngineConnector> m_physEngineConnectors = new List<SceneToPhysEngineConnector>();
|
||||||
|
// the last connector created
|
||||||
|
private SceneToPhysEngineConnector m_sceneToPhysEngineConnector = null;
|
||||||
|
|
||||||
|
//list of idle physics engines that have registered.
|
||||||
|
private List<IdlePhysEngineInfo> m_idlePhysEngineList = new List<IdlePhysEngineInfo>();
|
||||||
|
|
||||||
|
|
||||||
|
private string LogHeader = "[SCENE TO PHYS ENGINE SYNC SERVER]";
|
||||||
|
|
||||||
|
#region ICommandableModule Members
|
||||||
|
private readonly Commander m_commander = new Commander("phys");
|
||||||
|
public ICommander CommandInterface
|
||||||
|
{
|
||||||
|
get { return m_commander; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InstallInterfaces()
|
||||||
|
{
|
||||||
|
// Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer.");
|
||||||
|
//cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
|
||||||
|
|
||||||
|
// Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer.");
|
||||||
|
//cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
|
||||||
|
//cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
|
||||||
|
|
||||||
|
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
|
||||||
|
|
||||||
|
|
||||||
|
// m_commander.RegisterCommand("start", cmdSyncStart);
|
||||||
|
// m_commander.RegisterCommand("stop", cmdSyncStop);
|
||||||
|
m_commander.RegisterCommand("status", cmdSyncStatus);
|
||||||
|
|
||||||
|
lock (m_scene)
|
||||||
|
{
|
||||||
|
// Add this to our scene so scripts can call these functions
|
||||||
|
m_scene.RegisterModuleCommander(m_commander);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes commandline input. Do not call directly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">Commandline arguments</param>
|
||||||
|
private void EventManager_OnPluginConsole(string[] args)
|
||||||
|
{
|
||||||
|
if (args[0] == "phys")
|
||||||
|
{
|
||||||
|
if (args.Length == 1)
|
||||||
|
{
|
||||||
|
m_commander.ProcessConsoleCommand("help", new string[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] tmpArgs = new string[args.Length - 2];
|
||||||
|
int i;
|
||||||
|
for (i = 2; i < args.Length; i++)
|
||||||
|
tmpArgs[i - 2] = args[i];
|
||||||
|
|
||||||
|
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStart(Object[] args)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
private void SyncStop(Object[] args)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
private void SyncStatus(Object[] args)
|
||||||
|
{
|
||||||
|
lock (m_physEngineConnector_lock)
|
||||||
|
{
|
||||||
|
if (m_physEngineConnectors.Count == 0)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " Not currently synchronized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_log.Warn(LogHeader + " Synchronized");
|
||||||
|
foreach (SceneToPhysEngineConnector pec in m_physEngineConnectors)
|
||||||
|
{
|
||||||
|
m_log.Warn(pec.StatisticLine(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// Check if any of the client views are in a connected state
|
||||||
|
public bool IsPhysEngineScene() { return SceneToPhysEngineSyncServer.IsPhysEngineScene2S(); }
|
||||||
|
public bool IsActivePhysEngineScene() { return SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S(); }
|
||||||
|
public bool IsPhysEngineActor() { return SceneToPhysEngineSyncServer.IsPhysEngineActorS; }
|
||||||
|
|
||||||
|
public bool Synced
|
||||||
|
{
|
||||||
|
get { return (m_physEngineConnectors.Count > 0); }
|
||||||
|
}
|
||||||
|
public static bool IsPhysEngineSceneS
|
||||||
|
{
|
||||||
|
get { return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0); }
|
||||||
|
}
|
||||||
|
public static bool IsPhysEngineScene2S()
|
||||||
|
{
|
||||||
|
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0);
|
||||||
|
}
|
||||||
|
public static bool IsActivePhysEngineSceneS
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
System.Console.WriteLine("IsActivePhysEngineScene: si={0} tc={1}",
|
||||||
|
SceneToPhysEngineSyncServer.m_syncServerInitialized,
|
||||||
|
SceneToPhysEngineSyncServer.m_totalConnections);
|
||||||
|
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0
|
||||||
|
&& SceneToPhysEngineSyncServer.m_totalConnections > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool IsActivePhysEngineScene2S()
|
||||||
|
{
|
||||||
|
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0
|
||||||
|
&& SceneToPhysEngineSyncServer.m_totalConnections > 0);
|
||||||
|
}
|
||||||
|
public static bool IsPhysEngineActorS
|
||||||
|
{
|
||||||
|
get { return PhysEngineToSceneConnectorModule.IsPhysEngineActorS; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scene is unknown by ODE so we have to look through the scenes to
|
||||||
|
/// find the one with this PhysicsActor so we can send the update.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pa"></param>
|
||||||
|
public static void RouteUpdate(PhysicsActor pa)
|
||||||
|
{
|
||||||
|
SceneObjectPart sop = null;
|
||||||
|
Scene s = null;
|
||||||
|
foreach (Scene ss in m_allScenes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sop = ss.GetSceneObjectPart(pa.UUID);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
sop = null;
|
||||||
|
}
|
||||||
|
if (sop != null)
|
||||||
|
{
|
||||||
|
s = ss;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScenePresence sp = ss.GetScenePresence(pa.UUID);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
s = ss;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s != null)
|
||||||
|
{
|
||||||
|
if (s.SceneToPhysEngineSyncServer != null)
|
||||||
|
{
|
||||||
|
s.SceneToPhysEngineSyncServer.SendUpdate(pa);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("RouteUpdate: SceneToPhysEngineSyncServer is not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("RouteUpdate: no SOP for update of {0}", pa.UUID);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendUpdate(PhysicsActor pa)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: SendUpdate for {1}", LogHeader, pa.LocalID);
|
||||||
|
if (m_sceneToPhysEngineConnector != null)
|
||||||
|
{
|
||||||
|
this.m_sceneToPhysEngineConnector.SendPhysUpdateAttributes(pa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public SceneToPhysEngineSyncServer(Scene scene, string addr, int port)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
//m_log.Warn(LogHeader + "Constructed");
|
||||||
|
m_scene = scene;
|
||||||
|
m_addr = IPAddress.Parse(addr);
|
||||||
|
m_port = port;
|
||||||
|
|
||||||
|
m_scene.RegisterModuleInterface<ISceneToPhysEngineServer>(this);
|
||||||
|
|
||||||
|
// remember all the scenes that are configured for connection to physics engine
|
||||||
|
if (!m_allScenes.Contains(m_scene))
|
||||||
|
{
|
||||||
|
m_allScenes.Add(m_scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscribeToEvents();
|
||||||
|
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
|
InstallInterfaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SubscribeToEvents()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UnSubscribeToEvents()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the server
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
SceneToPhysEngineSyncServer.m_syncServerInitialized++;
|
||||||
|
m_listenerThread = new Thread(new ThreadStart(Listen));
|
||||||
|
m_listenerThread.Name = "SceneToPhysEngineSyncServer Listener";
|
||||||
|
m_log.DebugFormat("{0}: Starting {1} thread", LogHeader, m_listenerThread.Name);
|
||||||
|
m_listenerThread.Start();
|
||||||
|
// m_log.DebugFormat("{0}: Started", LogHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Stop the server and disconnect all RegionSyncClients
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("{0}: Shutdown", LogHeader);
|
||||||
|
SceneToPhysEngineSyncServer.m_syncServerInitialized--;
|
||||||
|
// Stop the listener and listening thread so no new clients are accepted
|
||||||
|
m_listener.Stop();
|
||||||
|
m_listenerThread.Abort();
|
||||||
|
m_listenerThread = null;
|
||||||
|
|
||||||
|
// Stop all existing SceneTOSEConnectors
|
||||||
|
//TO FINISH
|
||||||
|
foreach (SceneToPhysEngineConnector peConnector in m_physEngineConnectors)
|
||||||
|
{
|
||||||
|
peConnector.Shutdown();
|
||||||
|
}
|
||||||
|
m_physEngineConnectors.Clear();
|
||||||
|
|
||||||
|
UnSubscribeToEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add a connector to a physics engine
|
||||||
|
public void AddSyncedPhysEngine(SceneToPhysEngineConnector peConnector)
|
||||||
|
{
|
||||||
|
lock (m_physEngineConnector_lock)
|
||||||
|
{
|
||||||
|
m_physEngineConnectors.Add(peConnector);
|
||||||
|
m_sceneToPhysEngineConnector = peConnector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the client view from the list and decrement synced client counter
|
||||||
|
public void RemoveSyncedPhysEngine(SceneToPhysEngineConnector peConnector)
|
||||||
|
{
|
||||||
|
lock (m_physEngineConnector_lock)
|
||||||
|
{
|
||||||
|
//Dictionary<string, SceneToPhysEngineConnector> currentlist = m_physEngineConnectors;
|
||||||
|
//Dictionary<string, SceneToPhysEngineConnector> newlist = new Dictionary<string, SceneToPhysEngineConnector>(currentlist);
|
||||||
|
m_physEngineConnectors.Remove(peConnector);
|
||||||
|
// Threads holding the previous version of the list can keep using it since
|
||||||
|
// they will not hold it for long and get a new copy next time they need to iterate
|
||||||
|
//m_physEngineConnectors = newlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for connections from a new RegionSyncClient
|
||||||
|
// When connected, start the ReceiveLoop for the new client
|
||||||
|
private void Listen()
|
||||||
|
{
|
||||||
|
m_listener = new TcpListener(m_addr, m_port);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Start listening for clients
|
||||||
|
m_listener.Start();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// *** Move/Add TRY/CATCH to here, but we don't want to spin loop on the same error
|
||||||
|
m_log.WarnFormat(LogHeader + ": Listening for new connections on port {0}...", m_port.ToString());
|
||||||
|
TcpClient tcpclient = m_listener.AcceptTcpClient();
|
||||||
|
IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address;
|
||||||
|
int port = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Port;
|
||||||
|
SceneToPhysEngineSyncServer.m_totalConnections++;
|
||||||
|
// m_log.DebugFormat("{0}: m_totalConnections = {1}", LogHeader, SceneToPhysEngineSyncServer.m_totalConnections);
|
||||||
|
|
||||||
|
ActorStatus actorStatus = GetActorStatus(tcpclient);
|
||||||
|
|
||||||
|
switch (actorStatus)
|
||||||
|
{
|
||||||
|
case ActorStatus.Sync:
|
||||||
|
// Add the SceneToPhysEngineConnector to the list
|
||||||
|
SceneToPhysEngineConnector sceneToPEConnector = new SceneToPhysEngineConnector(++peCounter, m_scene, tcpclient, this);
|
||||||
|
AddSyncedPhysEngine(sceneToPEConnector);
|
||||||
|
break;
|
||||||
|
case ActorStatus.Idle:
|
||||||
|
IdlePhysEngineInfo idleSE = new IdlePhysEngineInfo(tcpclient);
|
||||||
|
m_log.DebugFormat("{0}: adding an idle SE ({1}:{2})", LogHeader, addr, port);
|
||||||
|
m_idlePhysEngineList.Add(idleSE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_log.DebugFormat("{0}: Unknown actor status", LogHeader);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SocketException e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: [Listen] SocketException: {1}", LogHeader, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public void RegisterSyncedPhysEngine(SceneToPhysEngineConnector sceneToSEConnector)
|
||||||
|
{
|
||||||
|
//first, remove it from the idle list
|
||||||
|
m_idlePhysEngineList.Remove(sceneToSEConnector);
|
||||||
|
|
||||||
|
//now, added to the synced SE list
|
||||||
|
AddSyncedPhysEngine(sceneToSEConnector);
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
|
|
||||||
|
// Broadcast a message to all connected RegionSyncClients
|
||||||
|
public void SendToAllConnectedPE(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
if (m_physEngineConnectors.Count > 0)
|
||||||
|
{
|
||||||
|
m_log.Debug(LogHeader + ": region " + m_scene.RegionInfo.RegionName + " Broadcast to PhysEngine, msg " + msg.Type);
|
||||||
|
foreach (SceneToPhysEngineConnector peConnector in m_physEngineConnectors)
|
||||||
|
{
|
||||||
|
peConnector.Send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//TO FINISH: Find the right SceneToSEConnector to forward the message
|
||||||
|
public void SendToPE(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
|
||||||
|
{
|
||||||
|
SceneToPhysEngineConnector peConnector = GetSceneToPEConnector(sog);
|
||||||
|
if (peConnector != null)
|
||||||
|
{
|
||||||
|
peConnector.SendObjectUpdate(msgType, sog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//This is to send a message, rsm, to phys engine, and the message is about object SOG. E.g. RemovedObject
|
||||||
|
public void SendToPE(RegionSyncMessage rsm, SceneObjectGroup sog)
|
||||||
|
{
|
||||||
|
SceneToPhysEngineConnector peConnector = GetSceneToPEConnector(sog);
|
||||||
|
if (peConnector != null)
|
||||||
|
{
|
||||||
|
peConnector.Send(rsm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private SceneToPhysEngineConnector GetSceneToPEConnector(SceneObjectGroup sog)
|
||||||
|
{
|
||||||
|
if (m_physEngineConnectors.Count == 0)
|
||||||
|
return null;
|
||||||
|
if (sog == null)
|
||||||
|
{
|
||||||
|
return m_physEngineConnectors[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: connection of physics engine to quarks. Next line commented out
|
||||||
|
// SceneToPhysEngineConnector peConnector = m_quarksInScene[quarkID].PEConnector;
|
||||||
|
|
||||||
|
if (PEConnector == null)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + sog.AbsolutePosition.ToString() + " not covered by any physics engine");
|
||||||
|
}
|
||||||
|
|
||||||
|
return PEConnector;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActorStatus GetActorStatus(TcpClient tcpclient)
|
||||||
|
{
|
||||||
|
m_log.Debug(LogHeader+ ": Get Actor status");
|
||||||
|
|
||||||
|
RegionSyncMessage msg = new RegionSyncMessage(tcpclient.GetStream());
|
||||||
|
ActorStatus actorStatus;
|
||||||
|
switch (msg.Type)
|
||||||
|
{
|
||||||
|
case RegionSyncMessage.MsgType.ActorStatus:
|
||||||
|
{
|
||||||
|
string status = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
|
||||||
|
m_log.Debug(LogHeader + ": recv status: " + status);
|
||||||
|
actorStatus = (ActorStatus)Convert.ToInt32(status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
m_log.Error(LogHeader + ": Expect Message Type: ActorStatus");
|
||||||
|
RegionSyncMessage.HandleError("[REGION SYNC SERVER]", msg, String.Format("{0} Expect Message Type: ActorType", "[REGION SYNC SERVER]"));
|
||||||
|
return ActorStatus.Null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return actorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region Event Handlers
|
||||||
|
|
||||||
|
#endregion Event Handlers
|
||||||
|
|
||||||
|
#region Load balancing members and functions
|
||||||
|
/*
|
||||||
|
//keep track of idle physics engines that are in the process of load balancing (they are off the idle list, but not a working physics engine yet (not sync'ing with Scene yet)).
|
||||||
|
private Dictionary<string, IdlePhysEngineInfo> m_loadBalancingIdleSEs = new Dictionary<string,IdlePhysEngineInfo>();
|
||||||
|
public void HandleLoadBalanceRequest(SceneToPhysEngineConnector seConnctor)
|
||||||
|
{
|
||||||
|
//Let's start a thread to do the job, so that we can return quickly and don't block on ReceiveLoop()
|
||||||
|
|
||||||
|
Thread partitionThread = new Thread(new ParameterizedThreadStart(TriggerLoadBalanceProcess));
|
||||||
|
partitionThread.Name = "TriggerLoadBalanceProcess";
|
||||||
|
partitionThread.Start((object)seConnctor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerLoadBalanceProcess(object arg)
|
||||||
|
{
|
||||||
|
SceneToPhysEngineConnector seConnctor = (SceneToPhysEngineConnector)arg;
|
||||||
|
IdlePhysEngineInfo idlePhysEngineInfo = GetIdlePhysEngineConnector();
|
||||||
|
if (idlePhysEngineInfo != null)
|
||||||
|
{
|
||||||
|
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadMigrationNotice);
|
||||||
|
Send(idlePhysEngineInfo.TClient, msg.ToBytes());
|
||||||
|
m_log.Debug(LogHeader + ": HandleLoadBalanceRequest from " + seConnctor.Description + ", picked idle SE: " + idlePhysEngineInfo.ID);
|
||||||
|
|
||||||
|
//keep track of which overload physics engine is paired up with which idle physics engine
|
||||||
|
idlePhysEngineInfo.AwaitOverloadedSE = seConnctor;
|
||||||
|
m_loadBalancingIdleSEs.Add(idlePhysEngineInfo.ID, idlePhysEngineInfo);
|
||||||
|
|
||||||
|
m_log.Debug("ToSEConnector portal: local -" +
|
||||||
|
((IPEndPoint)idlePhysEngineInfo.TClient.Client.LocalEndPoint).Address.ToString() + ":" + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.LocalEndPoint).Port
|
||||||
|
+ "; remote - " + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.RemoteEndPoint).Address.ToString() + ":"
|
||||||
|
+ ((IPEndPoint)idlePhysEngineInfo.TClient.Client.RemoteEndPoint).Port);
|
||||||
|
|
||||||
|
//Now we expect the idle physics engine to reply back
|
||||||
|
msg = new RegionSyncMessage(idlePhysEngineInfo.TClient.GetStream());
|
||||||
|
if (msg.Type != RegionSyncMessage.MsgType.LoadMigrationListenerInitiated)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": should receive a message of type LoadMigrationListenerInitiated, but received " + msg.Type.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Before the load is migrated from overloaded physics engine to the idle engine, sync with the DB to update the state in DB
|
||||||
|
List<EntityBase> entities = m_scene.GetEntities();
|
||||||
|
foreach (EntityBase entity in entities)
|
||||||
|
{
|
||||||
|
if (!entity.IsDeleted && entity is SceneObjectGroup && ((SceneObjectGroup)entity).HasGroupChanged)
|
||||||
|
{
|
||||||
|
m_scene.ForceSceneObjectBackup((SceneObjectGroup)entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OSDMap data = DeserializeMessage(msg);
|
||||||
|
if (!data.ContainsKey("ip") || !data.ContainsKey("port") )
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": parameters missing in SceneLocation message from Scene, need to have ip, port");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//echo the information back to the overloaded physics engine
|
||||||
|
seConnctor.Send(new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceResponse, OSDParser.SerializeJsonString(data)));
|
||||||
|
|
||||||
|
m_log.Debug(LogHeader + " now remove physics engine " + idlePhysEngineInfo.ID + " from idle SE list, and create SceneToPhysEngineConnector to it");
|
||||||
|
//create a SceneToSEConnector for the idle physics engine, who will be sync'ing with this SyncServer soon
|
||||||
|
SceneToPhysEngineConnector sceneToSEConnector = new SceneToPhysEngineConnector(++peCounter, m_scene, idlePhysEngineInfo.TClient, this);
|
||||||
|
//Now remove the physics engine from the idle SE list
|
||||||
|
m_idlePhysEngineList.Remove(idlePhysEngineInfo);
|
||||||
|
//AddSyncedPhysEngine(sceneToSEConnector);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
seConnctor.SendLoadBalanceRejection("no idle physics engines");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
HashSet<string> exceptions = new HashSet<string>();
|
||||||
|
private OSDMap DeserializeMessage(RegionSyncMessage msg)
|
||||||
|
{
|
||||||
|
OSDMap data = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
lock (exceptions)
|
||||||
|
// If this is a new message, then print the underlying data that caused it
|
||||||
|
if (!exceptions.Contains(e.Message))
|
||||||
|
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Send(TcpClient tcpclient, byte[] data)
|
||||||
|
{
|
||||||
|
if (tcpclient.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar =>
|
||||||
|
{
|
||||||
|
if (tcpclient.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tcpclient.GetStream().EndWrite(ar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} physics Engine has disconnected.", LogHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IdlePhysEngineInfo GetIdlePhysEngineConnector()
|
||||||
|
{
|
||||||
|
if (m_idlePhysEngineList.Count == 0)
|
||||||
|
return null;
|
||||||
|
IdlePhysEngineInfo idleSEInfo = m_idlePhysEngineList[0];
|
||||||
|
m_idlePhysEngineList.Remove(idleSEInfo);
|
||||||
|
return idleSEInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Load balancing functions
|
||||||
|
|
||||||
|
#region Message Logging
|
||||||
|
public static bool logInput = false;
|
||||||
|
public static bool logOutput = true;
|
||||||
|
public static bool logEnabled = false;
|
||||||
|
private class PhysMsgLogger
|
||||||
|
{
|
||||||
|
public DateTime startTime;
|
||||||
|
public string path = null;
|
||||||
|
public System.IO.TextWriter Log = null;
|
||||||
|
}
|
||||||
|
private static PhysMsgLogger logWriter = null;
|
||||||
|
private static TimeSpan logMaxFileTime = new TimeSpan(0, 5, 0); // (h,m,s) => 5 minutes
|
||||||
|
public static string logDir = "/stats/stats";
|
||||||
|
private static object logLocker = new Object();
|
||||||
|
|
||||||
|
public static void PhysLogMessage(bool direction, RegionSyncMessage rsm)
|
||||||
|
{
|
||||||
|
if (!logEnabled) return; // save to work of the ToStringFull if not enabled
|
||||||
|
PhysLogMessage(direction, rsm.ToStringFull());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a physics bucket message
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="direction">True of message originated from the agent</param>
|
||||||
|
/// <param name="msg">the message to log</param>
|
||||||
|
public static void PhysLogMessage(bool direction, string msg)
|
||||||
|
{
|
||||||
|
if (!logEnabled) return;
|
||||||
|
|
||||||
|
lock (logLocker)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
if (logWriter == null || (now > logWriter.startTime + logMaxFileTime))
|
||||||
|
{
|
||||||
|
if (logWriter != null && logWriter.Log != null)
|
||||||
|
{
|
||||||
|
logWriter.Log.Close();
|
||||||
|
logWriter.Log.Dispose();
|
||||||
|
logWriter.Log = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First log file or time has expired, start writing to a new log file
|
||||||
|
logWriter = new PhysMsgLogger();
|
||||||
|
logWriter.startTime = now;
|
||||||
|
logWriter.path = (logDir.Length > 0 ? logDir + System.IO.Path.DirectorySeparatorChar.ToString() : "")
|
||||||
|
+ String.Format("physics-{0}.log", now.ToString("yyyyMMddHHmmss"));
|
||||||
|
logWriter.Log = new StreamWriter(File.Open(logWriter.path, FileMode.Append, FileAccess.Write));
|
||||||
|
}
|
||||||
|
if (logWriter != null && logWriter.Log != null)
|
||||||
|
{
|
||||||
|
StringBuilder buff = new StringBuilder();
|
||||||
|
buff.Append(now.ToString("yyyyMMddHHmmssfff"));
|
||||||
|
buff.Append(" ");
|
||||||
|
buff.Append(direction ? "A->S:" : "S->A:");
|
||||||
|
buff.Append(msg);
|
||||||
|
buff.Append("\r\n");
|
||||||
|
logWriter.Log.Write(buff.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
|
||||||
|
logEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PhysLogMessageClose()
|
||||||
|
{
|
||||||
|
if (logWriter != null && logWriter.Log != null)
|
||||||
|
{
|
||||||
|
logWriter.Log.Close();
|
||||||
|
logWriter.Log.Dispose();
|
||||||
|
logWriter.Log = null;
|
||||||
|
logWriter = null;
|
||||||
|
}
|
||||||
|
logEnabled = false;
|
||||||
|
}
|
||||||
|
#endregion Message Logging
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using log4net;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ClientManagerSyncModule")]
|
||||||
|
public class ClientManagerSyncModule : INonSharedRegionModule, IDSGActorSyncModule
|
||||||
|
{
|
||||||
|
#region INonSharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||||
|
m_active = false;
|
||||||
|
if (syncConfig == null)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
|
||||||
|
|
||||||
|
//Read in configuration, if the local actor is configured to be a client manager, load this module.
|
||||||
|
if (!actorType.Equals("client_manager"))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": not configured as Client Manager Actor. Shut down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_actorID = syncConfig.GetString("ActorID", "");
|
||||||
|
if (m_actorID.Equals(""))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
m_log.Warn(LogHeader + " Initialised");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called after Initialise()
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//connect with scene
|
||||||
|
m_scene = scene;
|
||||||
|
|
||||||
|
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
|
||||||
|
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
|
||||||
|
|
||||||
|
// Setup the command line interface
|
||||||
|
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
|
//InstallInterfaces();
|
||||||
|
|
||||||
|
//Register for the OnPostSceneCreation event
|
||||||
|
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
|
||||||
|
|
||||||
|
//Register for Scene/SceneGraph events
|
||||||
|
m_scene.EventManager.OnSymmetricSyncStop += ClientManager_OnSymmetricSyncStop;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called after AddRegion() has been called for all region modules of the scene.
|
||||||
|
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "ClientManagerSyncModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //INonSharedRegionModule
|
||||||
|
|
||||||
|
|
||||||
|
#region IDSGActorSyncModule members and functions
|
||||||
|
|
||||||
|
private DSGActorTypes m_actorType = DSGActorTypes.ClientManager;
|
||||||
|
public DSGActorTypes ActorType
|
||||||
|
{
|
||||||
|
get { return m_actorType; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_actorID;
|
||||||
|
public string ActorID
|
||||||
|
{
|
||||||
|
get { return m_actorID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //IDSGActorSyncModule
|
||||||
|
|
||||||
|
#region ClientManagerSyncModule memebers and functions
|
||||||
|
private ILog m_log;
|
||||||
|
private bool m_active = false;
|
||||||
|
public bool Active
|
||||||
|
{
|
||||||
|
get { return m_active; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
private string LogHeader = "[ClientManagerSyncModule]";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Client Manager's action upon an object is added to the local scene
|
||||||
|
/// </summary>
|
||||||
|
private void ClientManager_OnObjectCreateBySync(EntityBase entity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientManager_OnSymmetricSyncStop()
|
||||||
|
{
|
||||||
|
//remove all objects
|
||||||
|
//m_scene.DeleteAllSceneObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //ScriptEngineSyncModule
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,384 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using Nwc.XmlRpc;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||||
|
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
//DSG added to support llDialog with distributed script engine and client manager,
|
||||||
|
//following the same communication pattern as grid_instant_message
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridDialogModule")]
|
||||||
|
public class GridDialogModule : ISharedRegionModule, IGridDialogModule
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
//private bool m_Enabled = false;
|
||||||
|
protected List<Scene> m_Scenes = new List<Scene>();
|
||||||
|
|
||||||
|
private IPresenceService m_PresenceService;
|
||||||
|
protected IPresenceService PresenceService
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_PresenceService == null)
|
||||||
|
m_PresenceService = m_Scenes[0].RequestModuleInterface<IPresenceService>();
|
||||||
|
return m_PresenceService;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
public virtual void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
//m_log.Debug("[GRID DIALOG MODULE]: Initialise");
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
lock (m_Scenes)
|
||||||
|
{
|
||||||
|
m_log.Debug("[GRID DIALOG MODULE]: Grid Dialog Module active");
|
||||||
|
scene.RegisterModuleInterface<IGridDialogModule>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void PostInitialise()
|
||||||
|
{
|
||||||
|
//if (!m_Enabled)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
MainServer.Instance.AddXmlRPCHandler(
|
||||||
|
"grid_dialog", processXMLRPCGridDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
//if (!m_Enabled)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
lock (m_Scenes)
|
||||||
|
{
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string Name
|
||||||
|
{
|
||||||
|
get { return "GridDialogModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //ISharedRegionModule
|
||||||
|
|
||||||
|
|
||||||
|
#region GridCommunication
|
||||||
|
|
||||||
|
public delegate void GridDialogDelegate(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName,
|
||||||
|
string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID);
|
||||||
|
|
||||||
|
protected virtual void GridDialogCompleted(IAsyncResult iar)
|
||||||
|
{
|
||||||
|
GridDialogDelegate icon =
|
||||||
|
(GridDialogDelegate)iar.AsyncState;
|
||||||
|
icon.EndInvoke(iar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendGridDialogViaXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName,
|
||||||
|
string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID)
|
||||||
|
{
|
||||||
|
GridDialogDelegate d = SendGridDialogViaXMLRPCAsync;
|
||||||
|
|
||||||
|
d.BeginInvoke(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID,
|
||||||
|
GridDialogCompleted, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SendGridDialogViaXMLRPCAsync(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName,
|
||||||
|
string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID)
|
||||||
|
{
|
||||||
|
PresenceInfo upd = null;
|
||||||
|
// Non-cached user agent lookup.
|
||||||
|
PresenceInfo[] presences = PresenceService.GetAgents(new string[] { avatarID.ToString() });
|
||||||
|
|
||||||
|
if (presences != null && presences.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (PresenceInfo p in presences)
|
||||||
|
{
|
||||||
|
if (p.RegionID != UUID.Zero)
|
||||||
|
{
|
||||||
|
upd = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upd != null)
|
||||||
|
{
|
||||||
|
// check if we've tried this before..
|
||||||
|
// This is one way to end the recursive loop
|
||||||
|
//
|
||||||
|
if (upd.RegionID == prevRegionID)
|
||||||
|
{
|
||||||
|
//Dialog content undelivered
|
||||||
|
m_log.WarnFormat("Couldn't deliver dialog to {0}" + avatarID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Dialog content undelivered
|
||||||
|
m_log.WarnFormat("Couldn't deliver dialog to {0}" + avatarID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upd != null)
|
||||||
|
{
|
||||||
|
GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID,
|
||||||
|
upd.RegionID);
|
||||||
|
if (reginfo != null)
|
||||||
|
{
|
||||||
|
Hashtable msgdata = ConvertGridDialogToXMLRPC(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels);
|
||||||
|
//= ConvertGridInstantMessageToXMLRPC(im);
|
||||||
|
// Not actually used anymore, left in for compatibility
|
||||||
|
// Remove at next interface change
|
||||||
|
//
|
||||||
|
msgdata["region_handle"] = 0;
|
||||||
|
|
||||||
|
bool imresult = doDialogSending(reginfo, msgdata);
|
||||||
|
if (!imresult)
|
||||||
|
{
|
||||||
|
SendGridDialogViaXMLRPCAsync(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID);
|
||||||
|
m_log.WarnFormat("Couldn't deliver dialog to {0}" + avatarID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Hashtable ConvertGridDialogToXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName,
|
||||||
|
string message, UUID textureID, int ch, string[] buttonlabels)
|
||||||
|
{
|
||||||
|
Hashtable msgdata = new Hashtable();
|
||||||
|
msgdata["avatarID"] = avatarID.ToString();
|
||||||
|
msgdata["objectName"] = objectName;
|
||||||
|
msgdata["objectID"] = objectID.ToString();
|
||||||
|
msgdata["ownerID"] = ownerID.ToString();
|
||||||
|
msgdata["ownerFirstName"] = ownerFirstName;
|
||||||
|
msgdata["ownerLastName"] = ownerLastName;
|
||||||
|
msgdata["message"] = message;
|
||||||
|
msgdata["textureID"] = textureID.ToString();
|
||||||
|
msgdata["ch"] = ch.ToString();
|
||||||
|
msgdata["buttonlabelsNum"] = buttonlabels.Length.ToString();
|
||||||
|
|
||||||
|
for (int i = 0; i < buttonlabels.Length; i++)
|
||||||
|
{
|
||||||
|
string key = "buttonlabel_" + i;
|
||||||
|
msgdata[key] = buttonlabels[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This actually does the XMLRPC Request
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reginfo">RegionInfo we pull the data out of to send the request to</param>
|
||||||
|
/// <param name="xmlrpcdata">The Instant Message data Hashtable</param>
|
||||||
|
/// <returns>Bool if the message was successfully delivered at the other side.</returns>
|
||||||
|
protected virtual bool doDialogSending(GridRegion reginfo, Hashtable xmlrpcdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
ArrayList SendParams = new ArrayList();
|
||||||
|
SendParams.Add(xmlrpcdata);
|
||||||
|
XmlRpcRequest GridReq = new XmlRpcRequest("grid_dialog", SendParams);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, 3000);
|
||||||
|
|
||||||
|
Hashtable responseData = (Hashtable)GridResp.Value;
|
||||||
|
|
||||||
|
if (responseData.ContainsKey("success"))
|
||||||
|
{
|
||||||
|
if ((string)responseData["success"] == "TRUE")
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (WebException e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending grid_dialog to {0} the host didn't respond " + e.ToString(), reginfo.ServerURI.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process a XMLRPC Grid Instant Message
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">XMLRPC parameters
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Nothing much</returns>
|
||||||
|
protected virtual XmlRpcResponse processXMLRPCGridDialog(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||||
|
{
|
||||||
|
bool decodingSuccessful = true;
|
||||||
|
bool deliverSuccessful = false;
|
||||||
|
UUID avatarID = UUID.Zero;
|
||||||
|
UUID objectID = UUID.Zero;
|
||||||
|
UUID textureID = UUID.Zero;
|
||||||
|
UUID ownerID = UUID.Zero;
|
||||||
|
string objectName="", ownerFirstName="", ownerLastName="";
|
||||||
|
string message="";
|
||||||
|
int ch=0;
|
||||||
|
string[] buttonlabels = null;
|
||||||
|
|
||||||
|
Hashtable requestData = (Hashtable)request.Params[0];
|
||||||
|
|
||||||
|
// Check if it's got all the data
|
||||||
|
if (requestData.ContainsKey("avatarID")
|
||||||
|
&& requestData.ContainsKey("objectName") && requestData.ContainsKey("objectID")
|
||||||
|
&& requestData.ContainsKey("ownerID")
|
||||||
|
&& requestData.ContainsKey("ownerFirstName") && requestData.ContainsKey("ownerLastName")
|
||||||
|
&& requestData.ContainsKey("message") && requestData.ContainsKey("textureID")
|
||||||
|
&& requestData.ContainsKey("ch")
|
||||||
|
&& requestData.ContainsKey("buttonlabelsNum"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Do the easy way of validating the UUIDs
|
||||||
|
UUID.TryParse((string)requestData["avatarID"], out avatarID);
|
||||||
|
UUID.TryParse((string)requestData["objectID"], out objectID);
|
||||||
|
UUID.TryParse((string)requestData["textureID"], out textureID);
|
||||||
|
UUID.TryParse((string)requestData["ownerID"], out ownerID);
|
||||||
|
|
||||||
|
objectName = (string)requestData["objectName"];
|
||||||
|
ownerFirstName = (string)requestData["ownerFirstName"];
|
||||||
|
ownerLastName = (string)requestData["ownerLastName"];
|
||||||
|
ch = Convert.ToInt32((string)requestData["ch"]);
|
||||||
|
|
||||||
|
int buttonlabelsNum = Convert.ToInt32((string)requestData["buttonlabelsNum"]);
|
||||||
|
buttonlabels = new string[buttonlabelsNum];
|
||||||
|
|
||||||
|
for (int i = 0; i < buttonlabelsNum; i++)
|
||||||
|
{
|
||||||
|
string key = "buttonlabel_" + i;
|
||||||
|
if (requestData.ContainsKey(key))
|
||||||
|
{
|
||||||
|
buttonlabels[i] = (string)requestData[key];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decodingSuccessful = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("Error in processXMLRPCGridDialog: {0}", e.Message);
|
||||||
|
deliverSuccessful = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decodingSuccessful)
|
||||||
|
{
|
||||||
|
//Deliver the dialog to the client
|
||||||
|
foreach (Scene scene in m_Scenes)
|
||||||
|
{
|
||||||
|
if (scene.Entities.ContainsKey(avatarID) &&
|
||||||
|
scene.Entities[avatarID] is ScenePresence)
|
||||||
|
{
|
||||||
|
ScenePresence user =
|
||||||
|
(ScenePresence)scene.Entities[avatarID];
|
||||||
|
|
||||||
|
if (!user.IsChildAgent)
|
||||||
|
{
|
||||||
|
user.ControllingClient.SendDialog(objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels);
|
||||||
|
deliverSuccessful = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send response back to region calling if it was successful
|
||||||
|
// calling region uses this to know when to look up a user's location again.
|
||||||
|
XmlRpcResponse resp = new XmlRpcResponse();
|
||||||
|
Hashtable respdata = new Hashtable();
|
||||||
|
if (deliverSuccessful)
|
||||||
|
respdata["success"] = "TRUE";
|
||||||
|
else
|
||||||
|
respdata["success"] = "FALSE";
|
||||||
|
resp.Value = respdata;
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //GridCommunication
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using log4net;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsEngineSyncModule")]
|
||||||
|
public class PhysicsEngineSyncModule : INonSharedRegionModule, IDSGActorSyncModule
|
||||||
|
{
|
||||||
|
#region INonSharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||||
|
m_active = false;
|
||||||
|
if (syncConfig == null)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
|
||||||
|
|
||||||
|
//Read in configuration, if the local actor is configured to be a client manager, load this module.
|
||||||
|
if (!actorType.Equals("physics_engine"))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": not configured as Physics Engine Actor. Shut down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_actorID = syncConfig.GetString("ActorID", "");
|
||||||
|
if (m_actorID.Equals(""))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
m_log.Warn(LogHeader + " Initialised");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called after Initialise()
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//connect with scene
|
||||||
|
m_scene = scene;
|
||||||
|
|
||||||
|
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
|
||||||
|
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
|
||||||
|
|
||||||
|
// register actor
|
||||||
|
if (!scene.GridService.RegisterActor(scene.RegionInfo.RegionID.ToString(),
|
||||||
|
"physics_engine", scene.RegionInfo.RegionID.ToString()))
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0}: Failure registering actor", LogHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the command line interface
|
||||||
|
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
|
//InstallInterfaces();
|
||||||
|
|
||||||
|
//Register for the OnPostSceneCreation event
|
||||||
|
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
|
||||||
|
|
||||||
|
//Register for Scene/SceneGraph events
|
||||||
|
m_scene.EventManager.OnSymmetricSyncStop += PhysicsEngine_OnSymmetricSyncStop;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called after AddRegion() has been called for all region modules of the scene.
|
||||||
|
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "PhysicsEngineSyncModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //INonSharedRegionModule
|
||||||
|
|
||||||
|
|
||||||
|
#region IDSGActorSyncModule members and functions
|
||||||
|
|
||||||
|
private DSGActorTypes m_actorType = DSGActorTypes.PhysicsEngine;
|
||||||
|
public DSGActorTypes ActorType
|
||||||
|
{
|
||||||
|
get { return m_actorType; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_actorID;
|
||||||
|
public string ActorID
|
||||||
|
{
|
||||||
|
get { return m_actorID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //IDSGActorSyncModule
|
||||||
|
|
||||||
|
#region PhysicsEngineSyncModule members and functions
|
||||||
|
private ILog m_log;
|
||||||
|
private bool m_active = false;
|
||||||
|
public bool Active
|
||||||
|
{
|
||||||
|
get { return m_active; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
private string LogHeader = "[PhysicsEngineSyncModule]";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Physics Engine's action upon an object is added to the local scene
|
||||||
|
/// </summary>
|
||||||
|
private void PhysicsEngine_OnObjectCreateBySync(EntityBase entity)
|
||||||
|
{
|
||||||
|
if (entity is SceneObjectGroup)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PhysicsEngine_OnSymmetricSyncStop()
|
||||||
|
{
|
||||||
|
//remove all objects
|
||||||
|
m_scene.DeleteAllSceneObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion PhysicsEngineSyncModule members and functions
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,226 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using log4net;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScenePersistenceSyncModule")]
|
||||||
|
public class ScenePersistenceSyncModule : INonSharedRegionModule, IDSGActorSyncModule
|
||||||
|
{
|
||||||
|
#region INonSharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||||
|
m_active = false;
|
||||||
|
if (syncConfig == null)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
|
||||||
|
if (!actorType.Equals("scene_persistence"))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": not configured as Scene Persistence Actor. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_actorID = syncConfig.GetString("ActorID", "");
|
||||||
|
if (m_actorID.Equals(""))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
m_log.Warn(LogHeader+" Initialised");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called after Initialise()
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
m_log.Warn(LogHeader + " AddRegion() called");
|
||||||
|
//connect with scene
|
||||||
|
m_scene = scene;
|
||||||
|
|
||||||
|
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
|
||||||
|
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
|
||||||
|
|
||||||
|
// register actor
|
||||||
|
if (!scene.GridService.RegisterActor(scene.RegionInfo.RegionID.ToString(),
|
||||||
|
"scene_persistence", scene.RegionInfo.RegionID.ToString()))
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0}: Failure registering actor", LogHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the command line interface
|
||||||
|
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
|
//InstallInterfaces();
|
||||||
|
|
||||||
|
//Register for the OnPostSceneCreation event
|
||||||
|
m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
|
||||||
|
|
||||||
|
//Register for Scene/SceneGraph events
|
||||||
|
m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScenePersistence_OnObjectCreate);
|
||||||
|
//m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(ScenePersistence_OnObjectCreateBySync);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called after AddRegion() has been called for all region modules of the scene.
|
||||||
|
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
|
||||||
|
// So to try to access other region modules in RegionLoaded, e.g. RegionSyncModule, is not a good idea.
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
m_log.Warn(LogHeader + " RegionLoaded() called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "ScenePersistenceSyncModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //INonSharedRegionModule
|
||||||
|
|
||||||
|
#region IDSGActorSyncModule members and functions
|
||||||
|
|
||||||
|
private DSGActorTypes m_actorType = DSGActorTypes.ScenePersistence;
|
||||||
|
public DSGActorTypes ActorType
|
||||||
|
{
|
||||||
|
get { return m_actorType; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_actorID;
|
||||||
|
public string ActorID
|
||||||
|
{
|
||||||
|
get { return m_actorID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //IDSGActorSyncModule
|
||||||
|
|
||||||
|
#region ScenePersistenceSyncModule memebers and functions
|
||||||
|
private ILog m_log;
|
||||||
|
private bool m_active = false;
|
||||||
|
public bool Active
|
||||||
|
{
|
||||||
|
get { return m_active; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
private string LogHeader = "[ScenePersistenceSyncModule]";
|
||||||
|
|
||||||
|
public void OnPostSceneCreation(Scene createdScene)
|
||||||
|
{
|
||||||
|
//If this is the local scene the actor is working on, do something
|
||||||
|
if (createdScene == m_scene)
|
||||||
|
{
|
||||||
|
m_scene.RequestModuleInterface<ITerrainModule>().SetSyncInfo(DateTime.Now.Ticks, m_scene.GetSyncActorID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ScenePersistence's actions upon an object is added to the local scene.
|
||||||
|
/// </summary>
|
||||||
|
private void ScenePersistence_OnObjectCreate(EntityBase entity)
|
||||||
|
{
|
||||||
|
if (entity is SceneObjectGroup)
|
||||||
|
{
|
||||||
|
//m_log.Warn(LogHeader + ":OnObjectCreate -- link to backup for " + entity.UUID);
|
||||||
|
SceneObjectGroup sog = (SceneObjectGroup)entity;
|
||||||
|
|
||||||
|
//probably what we should do here is to set some variable sog.SyncToBackup to true, and sog.ProcessBackup will only run if that value is true,
|
||||||
|
//then we do not need to worry about where an object is attach-to-backup and modify all those lines.
|
||||||
|
sog.ToPersistObjectState = true;
|
||||||
|
sog.AttachToBackup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ScenePersistence's actions upon an object is added to the local scene.
|
||||||
|
/// </summary>
|
||||||
|
private void ScenePersistence_OnObjectCreateBySync(EntityBase entity)
|
||||||
|
{
|
||||||
|
if (entity is SceneObjectGroup)
|
||||||
|
{
|
||||||
|
//m_log.Warn(LogHeader + ":OnObjectCreateBySync -- link to backup for " + entity.UUID);
|
||||||
|
SceneObjectGroup sog = (SceneObjectGroup)entity;
|
||||||
|
|
||||||
|
//probably what we should do here is to set some variable sog.SyncToBackup to true, and sog.ProcessBackup will only run if that value is true,
|
||||||
|
//then we do not need to worry about where an object is attach-to-backup and modify all those lines.
|
||||||
|
sog.ToPersistObjectState = true;
|
||||||
|
sog.AttachToBackup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //ScenePersistenceSyncModule
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,263 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using log4net;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")]
|
||||||
|
public class ScriptEngineSyncModule : INonSharedRegionModule, IDSGActorSyncModule
|
||||||
|
{
|
||||||
|
#region INonSharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||||
|
m_active = false;
|
||||||
|
if (syncConfig == null)
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
|
||||||
|
if (!actorType.Equals("script_engine"))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": not configured as Scene Persistence Actor. Shut down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_actorID = syncConfig.GetString("ActorID", "");
|
||||||
|
if (m_actorID.Equals(""))
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
LogHeader += "-" + m_actorID;
|
||||||
|
m_log.Warn(LogHeader + " Initialised");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called after Initialise()
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
m_log.Warn(LogHeader + " AddRegion() called");
|
||||||
|
//connect with scene
|
||||||
|
m_scene = scene;
|
||||||
|
|
||||||
|
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
|
||||||
|
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
|
||||||
|
|
||||||
|
// Setup the command line interface
|
||||||
|
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
|
//InstallInterfaces();
|
||||||
|
|
||||||
|
//Register for the OnPostSceneCreation event
|
||||||
|
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
|
||||||
|
|
||||||
|
//Register for Scene/SceneGraph events
|
||||||
|
//m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScriptEngine_OnObjectCreate);
|
||||||
|
|
||||||
|
//Don't subscribe to OnObjectCreate, only subscribe OnObjectCreateBySync.
|
||||||
|
m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(ScriptEngine_OnObjectCreateBySync);
|
||||||
|
m_scene.EventManager.OnSymmetricSyncStop += ScriptEngine_OnSymmetricSyncStop;
|
||||||
|
|
||||||
|
//for local OnUpdateScript, we'll handle it the same way as a remove OnUpdateScript.
|
||||||
|
//RegionSyncModule will capture a locally initiated OnUpdateScript event and publish it to other actors.
|
||||||
|
m_scene.EventManager.OnNewScript += ScriptEngine_OnNewScript;
|
||||||
|
m_scene.EventManager.OnUpdateScript += ScriptEngine_OnUpdateScript;
|
||||||
|
|
||||||
|
m_scene.EventManager.OnAggregateScriptEvents += ScriptEngine_OnAggregateScriptEvents;
|
||||||
|
|
||||||
|
LogHeader += "-" + m_actorID + "-" + m_scene.RegionInfo.RegionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called after AddRegion() has been called for all region modules of the scene.
|
||||||
|
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "ScriptEngineSyncModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //INonSharedRegionModule
|
||||||
|
|
||||||
|
#region IDSGActorSyncModule members and functions
|
||||||
|
|
||||||
|
public static string ActorTypeString = DSGActorTypes.ScriptEngine.ToString();
|
||||||
|
|
||||||
|
private DSGActorTypes m_actorType = DSGActorTypes.ScriptEngine;
|
||||||
|
public DSGActorTypes ActorType
|
||||||
|
{
|
||||||
|
get { return m_actorType; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_actorID;
|
||||||
|
public string ActorID
|
||||||
|
{
|
||||||
|
get { return m_actorID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //IDSGActorSyncModule
|
||||||
|
|
||||||
|
|
||||||
|
#region ScriptEngineSyncModule memebers and functions
|
||||||
|
private ILog m_log;
|
||||||
|
private bool m_active = false;
|
||||||
|
public bool Active
|
||||||
|
{
|
||||||
|
get { return m_active; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
private string LogHeader = "[ScriptEngineSyncModule]";
|
||||||
|
|
||||||
|
public void OnPostSceneCreation(Scene createdScene)
|
||||||
|
{
|
||||||
|
//If this is the local scene the actor is working on, do something
|
||||||
|
if (createdScene == m_scene)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Script Engine's action upon an object is added to the local scene
|
||||||
|
/// </summary>
|
||||||
|
private void ScriptEngine_OnObjectCreateBySync(EntityBase entity)
|
||||||
|
{
|
||||||
|
if (entity is SceneObjectGroup)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("{0}: start script for obj {1}", LogHeader, entity.UUID);
|
||||||
|
SceneObjectGroup sog = (SceneObjectGroup)entity;
|
||||||
|
sog.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0);
|
||||||
|
sog.ResumeScripts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScriptEngine_OnSymmetricSyncStop()
|
||||||
|
{
|
||||||
|
//Inform script engine to save script states and stop scripts
|
||||||
|
m_scene.EventManager.TriggerScriptEngineSyncStop();
|
||||||
|
//remove all objects
|
||||||
|
m_scene.DeleteAllSceneObjectsBySync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScriptEngine_OnNewScript(UUID agentID, SceneObjectPart part, UUID itemID)
|
||||||
|
{
|
||||||
|
m_log.Debug(LogHeader + " ScriptEngine_OnUpdateScript");
|
||||||
|
|
||||||
|
ArrayList errors = m_scene.SymSync_OnNewScript(agentID, itemID, part);
|
||||||
|
//The errors should be sent back to the client's viewer who submitted
|
||||||
|
//the new script. But for now, let just display it in concole and
|
||||||
|
//log it.
|
||||||
|
LogScriptErrors(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Assumption, when this function is triggered, the new script asset has already been saved.
|
||||||
|
public void ScriptEngine_OnUpdateScript(UUID agentID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
|
||||||
|
{
|
||||||
|
m_log.Debug(LogHeader + " ScriptEngine_OnUpdateScript");
|
||||||
|
ArrayList errors = m_scene.SymSync_OnUpdateScript(agentID, itemID, primID, isScriptRunning, newAssetID);
|
||||||
|
|
||||||
|
//The errors should be sent back to the client's viewer who submitted
|
||||||
|
//the script update. But for now, let just display it in concole and
|
||||||
|
//log it.
|
||||||
|
LogScriptErrors(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogScriptErrors(ArrayList errors)
|
||||||
|
{
|
||||||
|
string errorString = "";
|
||||||
|
foreach (Object err in errors)
|
||||||
|
{
|
||||||
|
errorString += err + "\n";
|
||||||
|
}
|
||||||
|
if (errorString != String.Empty)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("Error in script: {0}", errorString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScriptEngine_OnAggregateScriptEvents(SceneObjectPart part)
|
||||||
|
{
|
||||||
|
part.aggregateScriptEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //ScriptEngineSyncModule
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
//Initial code in SymmetricSyncMessage copied from RegionSyncMessage.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Types of symmetric sync messages among actors.
|
||||||
|
/// NOTE:: To enable message subscription, we may need to move the definition of MsgType to, say IRegionSyncModule, so that it can be exposed to other region modules.
|
||||||
|
/// </summary>
|
||||||
|
public class SymmetricSyncMessage
|
||||||
|
{
|
||||||
|
#region MsgType Enum
|
||||||
|
public enum MsgType
|
||||||
|
{
|
||||||
|
Null,
|
||||||
|
// Actor -> SIM(Scene)
|
||||||
|
GetTerrain,
|
||||||
|
GetObjects,
|
||||||
|
|
||||||
|
// SIM <-> CM
|
||||||
|
Terrain,
|
||||||
|
NewObject, // objects
|
||||||
|
UpdatedPrimProperties, //per property sync
|
||||||
|
//UpdatedObject, // objects
|
||||||
|
UpdatedBucketProperties, //object properties in one bucket
|
||||||
|
RemovedObject, // objects
|
||||||
|
LinkObject,
|
||||||
|
DelinkObject,
|
||||||
|
RegionName,
|
||||||
|
//RegionStatus,
|
||||||
|
ActorID,
|
||||||
|
ActorType,
|
||||||
|
//events
|
||||||
|
NewScript,
|
||||||
|
UpdateScript,
|
||||||
|
ScriptReset,
|
||||||
|
ChatFromClient,
|
||||||
|
ChatFromWorld,
|
||||||
|
ChatBroadcast,
|
||||||
|
ObjectGrab,
|
||||||
|
ObjectGrabbing,
|
||||||
|
ObjectDeGrab,
|
||||||
|
Attach,
|
||||||
|
PhysicsCollision,
|
||||||
|
ScriptCollidingStart,
|
||||||
|
ScriptColliding,
|
||||||
|
ScriptCollidingEnd,
|
||||||
|
ScriptLandCollidingStart,
|
||||||
|
ScriptLandColliding,
|
||||||
|
ScriptLandCollidingEnd,
|
||||||
|
//contorl command
|
||||||
|
SyncStateReport,
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Member Data
|
||||||
|
private MsgType m_type;
|
||||||
|
private byte[] m_data;
|
||||||
|
static ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public SymmetricSyncMessage(MsgType type, byte[] data)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SymmetricSyncMessage(MsgType type, string msg)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_data = System.Text.Encoding.ASCII.GetBytes(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SymmetricSyncMessage(MsgType type)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_data = new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public SymmetricSyncMessage(Stream stream)
|
||||||
|
{
|
||||||
|
//ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
//try
|
||||||
|
{
|
||||||
|
m_type = (MsgType)Utils.BytesToInt(GetBytesFromStream(stream, 4));
|
||||||
|
int length = Utils.BytesToInt(GetBytesFromStream(stream, 4));
|
||||||
|
m_data = GetBytesFromStream(stream, length);
|
||||||
|
//log.WarnFormat("RegionSyncMessage Constructed {0} ({1} bytes)", m_type.ToString(), length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] GetBytesFromStream(Stream stream, int count)
|
||||||
|
{
|
||||||
|
// Loop to receive the message length
|
||||||
|
byte[] ret = new byte[count];
|
||||||
|
int i = 0;
|
||||||
|
while (i < count)
|
||||||
|
{
|
||||||
|
i += stream.Read(ret, i, count - i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Accessors
|
||||||
|
public MsgType Type
|
||||||
|
{
|
||||||
|
get { return m_type; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Length
|
||||||
|
{
|
||||||
|
get { return m_data.Length; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Data
|
||||||
|
{
|
||||||
|
get { return m_data; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Conversions
|
||||||
|
public byte[] ToBytes()
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[m_data.Length + 8];
|
||||||
|
Utils.IntToBytes((int)m_type, buf, 0);
|
||||||
|
Utils.IntToBytes(m_data.Length, buf, 4);
|
||||||
|
Array.Copy(m_data, 0, buf, 8, m_data.Length);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return String.Format("{0} ({1} bytes)", m_type.ToString(), m_data.Length.ToString());
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
public static void HandleSuccess(string header, SymmetricSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Handled {1}: {2}", header, msg.ToString(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleTrivial(string header, SymmetricSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Issue handling {1}: {2}", header, msg.ToString(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleWarning(string header, SymmetricSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Warning handling {1}: {2}", header, msg.ToString(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleError(string header, SymmetricSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Error handling {1}: {2}", header, msg.ToString(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HandlerDebug(string header, SymmetricSyncMessage msg, string message)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} DBG ({1}): {2}", header, msg.ToString(), message);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,383 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Text;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
public enum SyncConnectorState
|
||||||
|
{
|
||||||
|
Idle, //not connected
|
||||||
|
Initialization, //initializing local copy of Scene
|
||||||
|
Syncing, //done initialization, in normal process of syncing terrain, objects, etc
|
||||||
|
}
|
||||||
|
// For implementations, a lot was copied from RegionSyncClientView, especially the SendLoop/ReceiveLoop.
|
||||||
|
public class SyncConnector : ISyncStatistics
|
||||||
|
{
|
||||||
|
private TcpClient m_tcpConnection = null;
|
||||||
|
private RegionSyncListenerInfo m_remoteListenerInfo = null;
|
||||||
|
private Thread m_rcvLoop;
|
||||||
|
private Thread m_send_loop;
|
||||||
|
|
||||||
|
private string LogHeader = "[SYNC CONNECTOR]";
|
||||||
|
// The logfile
|
||||||
|
private ILog m_log;
|
||||||
|
|
||||||
|
//members for in/out messages queueing
|
||||||
|
object stats = new object();
|
||||||
|
private long queuedUpdates=0;
|
||||||
|
private long dequeuedUpdates=0;
|
||||||
|
private long msgsIn=0;
|
||||||
|
private long msgsOut=0;
|
||||||
|
private long bytesIn=0;
|
||||||
|
private long bytesOut=0;
|
||||||
|
private DateTime lastStatTime;
|
||||||
|
|
||||||
|
// A queue for outgoing traffic.
|
||||||
|
private BlockingUpdateQueue m_outQ = new BlockingUpdateQueue();
|
||||||
|
|
||||||
|
private RegionSyncModule m_regionSyncModule = null;
|
||||||
|
|
||||||
|
//members for keeping track of state of this connector
|
||||||
|
private SyncConnectorState m_syncState = SyncConnectorState.Idle;
|
||||||
|
|
||||||
|
// unique connector number across all regions
|
||||||
|
private static int m_connectorNum = 0;
|
||||||
|
public int ConnectorNum
|
||||||
|
{
|
||||||
|
get { return m_connectorNum; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//the actorID of the other end of the connection
|
||||||
|
private string m_syncOtherSideActorID;
|
||||||
|
public string OtherSideActorID
|
||||||
|
{
|
||||||
|
get { return m_syncOtherSideActorID; }
|
||||||
|
//set { m_syncOtherSideActorID = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//The region name of the other side of the connection
|
||||||
|
private string m_syncOtherSideRegionName="";
|
||||||
|
public string OtherSideRegionName
|
||||||
|
{
|
||||||
|
get { return m_syncOtherSideRegionName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_syncOtherSideActorType;
|
||||||
|
public string OtherSideActorType
|
||||||
|
{
|
||||||
|
get { return m_syncOtherSideActorType; }
|
||||||
|
//set { m_syncOtherSideActorID = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the client is connected
|
||||||
|
public bool Connected
|
||||||
|
{ get { return (m_tcpConnection !=null && m_tcpConnection.Connected); } }
|
||||||
|
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_syncOtherSideRegionName == null)
|
||||||
|
return String.Format("SyncConnector{0}", m_connectorNum);
|
||||||
|
return String.Format("SyncConnector{0}({2}/{1:10})",
|
||||||
|
m_connectorNum, m_syncOtherSideRegionName, m_syncOtherSideActorID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The constructor that will be called when a SyncConnector is created passively: a remote SyncConnector has initiated the connection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectorNum"></param>
|
||||||
|
/// <param name="tcpclient"></param>
|
||||||
|
public SyncConnector(int connectorNum, TcpClient tcpclient, RegionSyncModule syncModule)
|
||||||
|
{
|
||||||
|
m_tcpConnection = tcpclient;
|
||||||
|
m_connectorNum = connectorNum;
|
||||||
|
m_regionSyncModule = syncModule;
|
||||||
|
lastStatTime = DateTime.Now;
|
||||||
|
SyncStatisticCollector.Register(this);
|
||||||
|
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The constructor that will be called when a SyncConnector is created actively: it is created to send connection request to a remote listener
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectorNum"></param>
|
||||||
|
/// <param name="listenerInfo"></param>
|
||||||
|
public SyncConnector(int connectorNum, RegionSyncListenerInfo listenerInfo, RegionSyncModule syncModule)
|
||||||
|
{
|
||||||
|
m_remoteListenerInfo = listenerInfo;
|
||||||
|
m_connectorNum = connectorNum;
|
||||||
|
m_regionSyncModule = syncModule;
|
||||||
|
lastStatTime = DateTime.Now;
|
||||||
|
SyncStatisticCollector.Register(this);
|
||||||
|
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Connect to the remote listener
|
||||||
|
public bool Connect()
|
||||||
|
{
|
||||||
|
m_tcpConnection = new TcpClient();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_tcpConnection.Connect(m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} [Start] Could not connect to RegionSyncModule at {1}:{2}", LogHeader, m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port);
|
||||||
|
m_log.Warn(e.Message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start both the send and receive threads
|
||||||
|
/// </summary>
|
||||||
|
public void StartCommThreads()
|
||||||
|
{
|
||||||
|
// Create a thread for the receive loop
|
||||||
|
m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop));
|
||||||
|
m_rcvLoop.Name = Description + " (ReceiveLoop)";
|
||||||
|
m_log.WarnFormat("{0} Starting {1} thread", Description, m_rcvLoop.Name);
|
||||||
|
m_rcvLoop.Start();
|
||||||
|
|
||||||
|
// Create a thread for the send loop
|
||||||
|
m_send_loop = new Thread(new ThreadStart(delegate() { SendLoop(); }));
|
||||||
|
m_send_loop.Name = Description + " (SendLoop)";
|
||||||
|
m_log.WarnFormat("{0} Starting {1} thread", Description, m_send_loop.Name);
|
||||||
|
m_send_loop.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
m_log.Warn(LogHeader + " shutdown connection");
|
||||||
|
// Abort receive and send loop
|
||||||
|
m_rcvLoop.Abort();
|
||||||
|
m_send_loop.Abort();
|
||||||
|
|
||||||
|
// Close the connection
|
||||||
|
m_tcpConnection.Client.Close();
|
||||||
|
m_tcpConnection.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// Sending messages out to the other side of the connection
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// Send messages from the update Q as fast as we can DeQueue them
|
||||||
|
// *** This is the main send loop thread for each connected client
|
||||||
|
private void SendLoop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Dequeue is thread safe
|
||||||
|
byte[] update = m_outQ.Dequeue();
|
||||||
|
lock (stats)
|
||||||
|
dequeuedUpdates++;
|
||||||
|
Send(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0} has disconnected: {1} (SendLoop)", Description, e.Message);
|
||||||
|
}
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enqueue update of an object/avatar into the outgoing queue, and return right away
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">UUID of the object/avatar</param>
|
||||||
|
/// <param name="update">the update infomation in byte format</param>
|
||||||
|
public void EnqueueOutgoingUpdate(UUID id, byte[] update)
|
||||||
|
{
|
||||||
|
lock (stats)
|
||||||
|
queuedUpdates++;
|
||||||
|
// Enqueue is thread safe
|
||||||
|
m_outQ.Enqueue(id, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send out a messge directly. This should only by called for short messages that are not sent frequently.
|
||||||
|
//Don't call this function for sending out updates. Call EnqueueOutgoingUpdate instead
|
||||||
|
public void Send(SymmetricSyncMessage msg)
|
||||||
|
{
|
||||||
|
Send(msg.ToBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Send(byte[] data)
|
||||||
|
{
|
||||||
|
if (m_tcpConnection.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
msgsOut++;
|
||||||
|
bytesOut += data.Length;
|
||||||
|
}
|
||||||
|
m_tcpConnection.GetStream().BeginWrite(data, 0, data.Length, ar =>
|
||||||
|
{
|
||||||
|
if (m_tcpConnection.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_tcpConnection.GetStream().EndWrite(ar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}:Error in Send() {1} has disconnected -- error message: {2}.", Description, m_connectorNum, e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// Receiving messages from the other side ofthe connection
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
private void ReceiveLoop()
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name);
|
||||||
|
while (true && m_tcpConnection.Connected)
|
||||||
|
{
|
||||||
|
SymmetricSyncMessage msg;
|
||||||
|
// Try to get the message from the network stream
|
||||||
|
try
|
||||||
|
{
|
||||||
|
msg = new SymmetricSyncMessage(m_tcpConnection.GetStream());
|
||||||
|
//m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString());
|
||||||
|
}
|
||||||
|
// If there is a problem reading from the client, shut 'er down.
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//ShutdownClient();
|
||||||
|
m_log.WarnFormat("{0}: ReceiveLoop error {1} has disconnected -- error message {2}.", Description, m_connectorNum, e.Message);
|
||||||
|
Shutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Try handling the message
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HandleMessage(msg);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Encountered an exception: {1} (MSGTYPE = {2})", Description, e.Message, msg.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleMessage(SymmetricSyncMessage msg)
|
||||||
|
{
|
||||||
|
|
||||||
|
msgsIn++;
|
||||||
|
bytesIn += msg.Data.Length;
|
||||||
|
switch (msg.Type)
|
||||||
|
{
|
||||||
|
case SymmetricSyncMessage.MsgType.RegionName:
|
||||||
|
{
|
||||||
|
m_syncOtherSideRegionName = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
|
||||||
|
if (m_regionSyncModule.IsSyncRelay)
|
||||||
|
{
|
||||||
|
SymmetricSyncMessage outMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.RegionName, m_regionSyncModule.LocalScene.RegionInfo.RegionName);
|
||||||
|
Send(outMsg);
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("Syncing to region \"{0}\"", m_syncOtherSideRegionName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case SymmetricSyncMessage.MsgType.ActorID:
|
||||||
|
{
|
||||||
|
m_syncOtherSideActorID = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
|
||||||
|
if (m_regionSyncModule.IsSyncRelay)
|
||||||
|
{
|
||||||
|
SymmetricSyncMessage outMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.ActorID, m_regionSyncModule.ActorID);
|
||||||
|
Send(outMsg);
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("Syncing to actor \"{0}\"", m_syncOtherSideActorID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case SymmetricSyncMessage.MsgType.ActorType:
|
||||||
|
{
|
||||||
|
m_syncOtherSideActorType = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
|
||||||
|
if (m_regionSyncModule.IsSyncRelay)
|
||||||
|
{
|
||||||
|
SymmetricSyncMessage outMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.ActorType, m_regionSyncModule.LocalScene.RegionSyncActorType );
|
||||||
|
Send(outMsg);
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("Syncing to actor type \"{0}\"", m_syncOtherSideActorType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//For any other messages, we simply deliver the message to RegionSyncModule for now.
|
||||||
|
//Later on, we may deliver messages to different modules, say sync message to RegionSyncModule and event message to ActorSyncModule.
|
||||||
|
m_regionSyncModule.HandleIncomingMessage(msg, m_syncOtherSideActorID, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StatisticIdentifier()
|
||||||
|
{
|
||||||
|
return this.Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StatisticLine(bool clearFlag)
|
||||||
|
{
|
||||||
|
string statLine = "";
|
||||||
|
lock (stats)
|
||||||
|
{
|
||||||
|
double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds;
|
||||||
|
lastStatTime = DateTime.Now;
|
||||||
|
statLine = String.Format("{0},{1},{2},{3},{4},{5},{6}",
|
||||||
|
msgsIn, msgsOut, bytesIn, bytesOut, m_outQ.Count,
|
||||||
|
8 * (bytesIn / secondsSinceLastStats / 1000000),
|
||||||
|
8 * (bytesOut / secondsSinceLastStats / 1000000) );
|
||||||
|
if (clearFlag)
|
||||||
|
msgsIn = msgsOut = bytesIn = bytesOut = 0;
|
||||||
|
}
|
||||||
|
return statLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StatisticTitle()
|
||||||
|
{
|
||||||
|
return "msgsIn,msgsOut,bytesIn,bytesOut,queueSize,Mbps In,Mbps Out";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Timers;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
{
|
||||||
|
public interface ISyncStatistics
|
||||||
|
{
|
||||||
|
// return an identifier for this statistics source
|
||||||
|
string StatisticIdentifier();
|
||||||
|
// a line of comma separated values
|
||||||
|
string StatisticLine(bool clearFlag);
|
||||||
|
// a line of comma separated field descriptions (describes what StatisticLine returns)
|
||||||
|
string StatisticTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SyncStatisticCollector
|
||||||
|
{
|
||||||
|
public static bool LogEnabled = false;
|
||||||
|
public static string LogDirectory = ".";
|
||||||
|
public static int LogInterval = 5000;
|
||||||
|
public static int LogMaxFileTimeMin = 5; // 5 minutes
|
||||||
|
public static string LogFileHeader = "stats-";
|
||||||
|
|
||||||
|
private static List<ISyncStatistics> s_staters = new List<ISyncStatistics>();
|
||||||
|
private static object s_statersLock = new object();
|
||||||
|
private static Timer s_timer = null;
|
||||||
|
|
||||||
|
static SyncStatisticCollector()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SyncStatisticCollector()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Any implementor of ISyncStatistics will call Register to put themselves in
|
||||||
|
/// the list of routines to collect statistics from. This will run periodically
|
||||||
|
/// and suck statistics from the registered routines.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stat"></param>
|
||||||
|
public static void Register(ISyncStatistics stat)
|
||||||
|
{
|
||||||
|
if (!LogEnabled) return;
|
||||||
|
lock (SyncStatisticCollector.s_statersLock)
|
||||||
|
{
|
||||||
|
// set up logging timer
|
||||||
|
if (SyncStatisticCollector.s_timer == null)
|
||||||
|
{
|
||||||
|
SyncStatisticCollector.s_timer = new Timer();
|
||||||
|
SyncStatisticCollector.s_timer.Interval = LogInterval;
|
||||||
|
SyncStatisticCollector.s_timer.Enabled = true;
|
||||||
|
SyncStatisticCollector.s_timer.Elapsed += Tick;
|
||||||
|
|
||||||
|
}
|
||||||
|
SyncStatisticCollector.s_staters.Add(stat);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Close()
|
||||||
|
{
|
||||||
|
lock (SyncStatisticCollector.s_statersLock)
|
||||||
|
{
|
||||||
|
SyncStatisticCollector.LogEnabled = false;
|
||||||
|
if (SyncStatisticCollector.s_timer != null)
|
||||||
|
{
|
||||||
|
SyncStatisticCollector.s_timer.Enabled = false;
|
||||||
|
SyncStatisticCollector.s_timer.Dispose();
|
||||||
|
SyncStatisticCollector.s_timer = null;
|
||||||
|
}
|
||||||
|
if (SyncStatisticCollector.LogFile != null)
|
||||||
|
{
|
||||||
|
SyncStatisticCollector.LogFile.Close();
|
||||||
|
SyncStatisticCollector.LogFile.Dispose();
|
||||||
|
SyncStatisticCollector.LogFile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!LogEnabled) return;
|
||||||
|
lock (SyncStatisticCollector.s_statersLock)
|
||||||
|
{
|
||||||
|
foreach (ISyncStatistics iss in s_staters)
|
||||||
|
{
|
||||||
|
LogWriter(iss.StatisticIdentifier() + "," + iss.StatisticLine(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DateTime LogStartTime;
|
||||||
|
private static System.IO.TextWriter LogFile = null;
|
||||||
|
private static void LogWriter(string line)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
if (LogFile == null || (now > (LogStartTime + new TimeSpan(0, LogMaxFileTimeMin, 0))))
|
||||||
|
{
|
||||||
|
if (LogFile != null)
|
||||||
|
{
|
||||||
|
LogFile.Close();
|
||||||
|
LogFile.Dispose();
|
||||||
|
LogFile = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First log file or time has expired, start writing to a new log file
|
||||||
|
LogStartTime = now;
|
||||||
|
string path = (LogDirectory.Length > 0 ? LogDirectory
|
||||||
|
+ System.IO.Path.DirectorySeparatorChar.ToString() : "")
|
||||||
|
+ String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
|
||||||
|
LogFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
|
||||||
|
}
|
||||||
|
if (LogFile != null)
|
||||||
|
{
|
||||||
|
StringBuilder buff = new StringBuilder();
|
||||||
|
// buff.Append(now.ToString("yyyyMMddHHmmssfff"));
|
||||||
|
buff.Append(now.ToString("yyyyMMddHHmmss"));
|
||||||
|
buff.Append(",");
|
||||||
|
buff.Append(line);
|
||||||
|
buff.Append("\r\n");
|
||||||
|
LogFile.Write(buff.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
|
||||||
|
LogEnabled = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,8 +34,8 @@ using OpenSim.Framework;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
// using log4net;
|
//using log4net;
|
||||||
// using System.Reflection;
|
//using System.Reflection;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************
|
/*****************************************************
|
||||||
|
@ -98,6 +98,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
||||||
private int m_saydistance = 30;
|
private int m_saydistance = 30;
|
||||||
private int m_shoutdistance = 100;
|
private int m_shoutdistance = 100;
|
||||||
|
|
||||||
|
//private ILog m_log;
|
||||||
|
|
||||||
#region IRegionModule Members
|
#region IRegionModule Members
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
|
@ -125,6 +127,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
||||||
m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
|
m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
|
||||||
m_scene.EventManager.OnChatFromClient += DeliverClientMessage;
|
m_scene.EventManager.OnChatFromClient += DeliverClientMessage;
|
||||||
m_scene.EventManager.OnChatBroadcast += DeliverClientMessage;
|
m_scene.EventManager.OnChatBroadcast += DeliverClientMessage;
|
||||||
|
//DSG SYNC
|
||||||
|
//m_scene.EventManager.OnChatFromWorld += DeliverClientMessage;
|
||||||
|
//Kitty: temp debug
|
||||||
|
//m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
//end DSG SYNC
|
||||||
m_pendingQ = new Queue();
|
m_pendingQ = new Queue();
|
||||||
m_pending = Queue.Synchronized(m_pendingQ);
|
m_pending = Queue.Synchronized(m_pendingQ);
|
||||||
}
|
}
|
||||||
|
@ -241,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
||||||
/// <param name="msg">msg to sent</param>
|
/// <param name="msg">msg to sent</param>
|
||||||
public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position)
|
public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
|
//m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
|
||||||
// type, channel, name, id, msg);
|
// type, channel, name, id, msg);
|
||||||
|
|
||||||
// Determine which listen event filters match the given set of arguments, this results
|
// Determine which listen event filters match the given set of arguments, this results
|
||||||
|
|
|
@ -260,5 +260,33 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
MainConsole.Instance.Output(caps.ToString());
|
MainConsole.Instance.Output(caps.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region SYNC SERVER
|
||||||
|
// Stubs for actor and quark management. Only implementation is in SimianGridService
|
||||||
|
public bool RegisterEndpoint(GridEndpointInfo gei)
|
||||||
|
{
|
||||||
|
return m_GridService.RegisterEndpoint(gei);
|
||||||
|
}
|
||||||
|
public bool RegisterActor(string actorID, string actorType, string syncServerID)
|
||||||
|
{
|
||||||
|
return m_GridService.RegisterActor(actorID, actorType, syncServerID);
|
||||||
|
}
|
||||||
|
public bool RegisterQuark(string syncServerID, uint locX, uint locY)
|
||||||
|
{
|
||||||
|
return m_GridService.RegisterQuark(syncServerID, locX, locY);
|
||||||
|
}
|
||||||
|
public List<GridEndpointInfo> LookupQuark(uint locX, uint locY)
|
||||||
|
{
|
||||||
|
return m_GridService.LookupQuark(locX, locY);
|
||||||
|
}
|
||||||
|
public List<GridEndpointInfo> LookupQuark(uint locX, uint locY, string actorType)
|
||||||
|
{
|
||||||
|
return m_GridService.LookupQuark(locX, locY, actorType);
|
||||||
|
}
|
||||||
|
public bool CleanUpEndpoint(string syncServerID)
|
||||||
|
{
|
||||||
|
return m_GridService.CleanUpEndpoint(syncServerID);
|
||||||
|
}
|
||||||
|
#endregion SYNC SERVER
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,5 +318,33 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region SYNC SERVER
|
||||||
|
// Stubs for actor and quark management. Only implementation is in SimianGridService
|
||||||
|
public bool RegisterEndpoint(GridEndpointInfo gei)
|
||||||
|
{
|
||||||
|
return m_RemoteGridService.RegisterEndpoint(gei);
|
||||||
|
}
|
||||||
|
public bool RegisterActor(string actorID, string actorType, string syncServerID)
|
||||||
|
{
|
||||||
|
return m_RemoteGridService.RegisterActor(actorID, actorType, syncServerID);
|
||||||
|
}
|
||||||
|
public bool RegisterQuark(string syncServerID, uint locX, uint locY)
|
||||||
|
{
|
||||||
|
return m_RemoteGridService.RegisterQuark(syncServerID, locX, locY);
|
||||||
|
}
|
||||||
|
public List<GridEndpointInfo> LookupQuark(uint locX, uint locY)
|
||||||
|
{
|
||||||
|
return m_RemoteGridService.LookupQuark(locX, locY);
|
||||||
|
}
|
||||||
|
public List<GridEndpointInfo> LookupQuark(uint locX, uint locY, string actorType)
|
||||||
|
{
|
||||||
|
return m_RemoteGridService.LookupQuark(locX, locY, actorType);
|
||||||
|
}
|
||||||
|
public bool CleanUpEndpoint(string syncServerID)
|
||||||
|
{
|
||||||
|
return m_RemoteGridService.CleanUpEndpoint(syncServerID);
|
||||||
|
}
|
||||||
|
#endregion SYNC SERVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,6 +200,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
|
|
||||||
public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
|
public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
if (destination == null)
|
if (destination == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -249,10 +249,11 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
part.Shape.Media[face] = me;
|
part.Shape.Media[face] = me;
|
||||||
|
|
||||||
UpdateMediaUrl(part, UUID.Zero);
|
UpdateMediaUrl(part, UUID.Zero);
|
||||||
|
|
||||||
SetPartMediaFlags(part, face, me != null);
|
SetPartMediaFlags(part, face, me != null);
|
||||||
|
//part.ScheduleFullUpdate();
|
||||||
part.ScheduleFullUpdate();
|
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.MediaUrl, SceneObjectPartSyncProperties.Shape});
|
||||||
|
|
||||||
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +458,8 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
UpdateMediaUrl(part, agentId);
|
UpdateMediaUrl(part, agentId);
|
||||||
|
|
||||||
// Arguably, we could avoid sending a full update to the avatar that just changed the texture.
|
// Arguably, we could avoid sending a full update to the avatar that just changed the texture.
|
||||||
part.ScheduleFullUpdate();
|
//part.ScheduleFullUpdate();
|
||||||
|
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Shape, SceneObjectPartSyncProperties.MediaUrl});
|
||||||
|
|
||||||
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
||||||
|
|
||||||
|
@ -535,7 +537,8 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
|
|
||||||
UpdateMediaUrl(part, agentId);
|
UpdateMediaUrl(part, agentId);
|
||||||
|
|
||||||
part.ScheduleFullUpdate();
|
//part.ScheduleFullUpdate();
|
||||||
|
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.MediaUrl});
|
||||||
|
|
||||||
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
||||||
|
|
||||||
|
@ -629,4 +632,4 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
|
||||||
part.GetProperties(remoteClient);
|
part.GetProperties(remoteClient);
|
||||||
part.TriggerScriptChangedEvent(Changed.OWNER);
|
part.TriggerScriptChangedEvent(Changed.OWNER);
|
||||||
group.ResumeScripts();
|
group.ResumeScripts();
|
||||||
part.ScheduleFullUpdate();
|
//part.ScheduleFullUpdate();
|
||||||
|
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.FullUpdate }); //quite some properties changed, let's just force all to be synchronized
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -584,6 +584,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
|
m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
|
||||||
m_scene.SaveTerrain();
|
m_scene.SaveTerrain();
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
//Terrain has been modified, send out sync message if needed
|
||||||
|
//if (m_scene.RegionSyncModule != null)
|
||||||
|
//{
|
||||||
|
//m_log.DebugFormat("EventManager_OnTerrainTick: To call SendTerrainUpdates with TS {0} and actorID {1}", m_lastUpdateTimeStamp, m_lastUpdateActorID);
|
||||||
|
//m_scene.RegionSyncModule.SendTerrainUpdates(m_lastUpdateTimeStamp, m_lastUpdateActorID);
|
||||||
|
//}
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
// Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
|
// Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
|
||||||
//m_scene.CreateTerrainTexture(true);
|
//m_scene.CreateTerrainTexture(true);
|
||||||
}
|
}
|
||||||
|
@ -624,6 +633,83 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
client.OnUnackedTerrain += client_OnUnackedTerrain;
|
client.OnUnackedTerrain += client_OnUnackedTerrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
private long m_lastUpdateTimeStamp = DateTime.Now.Ticks;
|
||||||
|
public long LastUpdateTimeStamp
|
||||||
|
{
|
||||||
|
get { return m_lastUpdateTimeStamp; }
|
||||||
|
set { m_lastUpdateTimeStamp = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_lastUpdateActorID;
|
||||||
|
public string LastUpdateActorID
|
||||||
|
{
|
||||||
|
get { return m_lastUpdateActorID; }
|
||||||
|
set { m_lastUpdateActorID = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncInfoUpdate(long timeStamp, string actorID)
|
||||||
|
{
|
||||||
|
m_lastUpdateTimeStamp = timeStamp;
|
||||||
|
m_lastUpdateActorID = actorID;
|
||||||
|
|
||||||
|
// m_log.DebugFormat("TerrainModule: updated syncinfo -- TS {0}, actorID {1}", m_lastUpdateTimeStamp, m_lastUpdateActorID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked by receiving a terrain sync message. First, check if the
|
||||||
|
/// timestamp is more advance than the local copy. If so, update the
|
||||||
|
/// local terrain copy, update the sync info (timestamp and actorID).
|
||||||
|
/// <param name="timeStamp"></param>
|
||||||
|
/// <param name="actorID"></param>
|
||||||
|
/// <param name="terrainData"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool UpdateTerrianBySync(long timeStamp, string actorID, string terrainData)
|
||||||
|
{
|
||||||
|
if (timeStamp > m_lastUpdateTimeStamp)
|
||||||
|
{
|
||||||
|
if (actorID.Equals(m_lastUpdateActorID) && actorID.Equals(m_scene.GetSyncActorID()))
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("TerrainModule: Received a Terrain sync message with a more recent timestamp, HOWEVER, actorID on the update is the same with local acotrID ({0})",
|
||||||
|
actorID);
|
||||||
|
}
|
||||||
|
//SyncInfoUpdate(timeStamp, actorID);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("TerrainModule: to copy new terrain data with TS {0}, actorID {1}", timeStamp, actorID);
|
||||||
|
|
||||||
|
m_scene.Heightmap.LoadFromXmlString(terrainData);
|
||||||
|
CheckForTerrainUpdates(false, timeStamp, actorID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ((timeStamp == m_lastUpdateTimeStamp) && !actorID.Equals(m_lastUpdateActorID))
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("TerrainModule: actors {0} and {1} have edited terrain with the same timestamp, TO DE DONE: need to pick a winner.",
|
||||||
|
actorID, m_lastUpdateActorID);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TerrianModifiedLocally(string localActorID)
|
||||||
|
{
|
||||||
|
if (localActorID == m_lastUpdateActorID)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetSyncInfo(out long lastUpdateTimeStamp, out string lastUpdateActorID)
|
||||||
|
{
|
||||||
|
lastUpdateTimeStamp = m_lastUpdateTimeStamp;
|
||||||
|
lastUpdateActorID = m_lastUpdateActorID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSyncInfo(long lastUpdateTimeStamp, string lastUpdateActorID)
|
||||||
|
{
|
||||||
|
m_lastUpdateTimeStamp = lastUpdateTimeStamp;
|
||||||
|
m_lastUpdateActorID = lastUpdateActorID;
|
||||||
|
}
|
||||||
|
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks to see if the terrain has been modified since last check
|
/// Checks to see if the terrain has been modified since last check
|
||||||
/// but won't attempt to limit those changes to the limits specified in the estate settings
|
/// but won't attempt to limit those changes to the limits specified in the estate settings
|
||||||
|
@ -631,7 +717,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void CheckForTerrainUpdates()
|
private void CheckForTerrainUpdates()
|
||||||
{
|
{
|
||||||
CheckForTerrainUpdates(false);
|
//DSG SYNC
|
||||||
|
m_log.DebugFormat("CheckForTerrainUpdates() called");
|
||||||
|
//Assumption: Thus function is only called when the terrain is updated by the local actor.
|
||||||
|
// Updating terrain during receiving sync messages from another actor will call CheckForTerrainUpdates.
|
||||||
|
|
||||||
|
//Update the timestamp to the current time tick, and set the LastUpdateActorID to be self
|
||||||
|
long currentTimeTick = DateTime.Now.Ticks;
|
||||||
|
string localActorID = m_scene.GetSyncActorID();
|
||||||
|
//SyncInfoUpdate(currentTimeTick, localActorID);
|
||||||
|
//Check if the terrain has been modified and send out sync message if modified.
|
||||||
|
CheckForTerrainUpdates(false, currentTimeTick, localActorID);
|
||||||
|
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
|
//CheckForTerrainUpdates(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -642,7 +742,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
/// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
|
/// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
|
||||||
/// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
|
/// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void CheckForTerrainUpdates(bool respectEstateSettings)
|
//private void CheckForTerrainUpdates(bool respectEstateSettings)
|
||||||
|
//DSG SYNC: Change the interface, to input the right sync information for the most recent update
|
||||||
|
private void CheckForTerrainUpdates(bool respectEstateSettings, long lastUpdateTimeStamp, string lastUpdateActorID)
|
||||||
|
//end of DSG SYNC
|
||||||
{
|
{
|
||||||
bool shouldTaint = false;
|
bool shouldTaint = false;
|
||||||
float[] serialised = m_channel.GetFloatsSerialised();
|
float[] serialised = m_channel.GetFloatsSerialised();
|
||||||
|
@ -671,6 +774,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
if (shouldTaint)
|
if (shouldTaint)
|
||||||
{
|
{
|
||||||
m_tainted = true;
|
m_tainted = true;
|
||||||
|
//DSG SYNC
|
||||||
|
//Terrain has been modified, updated the sync info
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
SyncInfoUpdate(lastUpdateTimeStamp, lastUpdateActorID);
|
||||||
|
m_scene.RegionSyncModule.SendTerrainUpdates(lastUpdateTimeStamp, lastUpdateActorID);
|
||||||
|
}
|
||||||
|
//end of DSG SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,7 +894,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
m_painteffects[(StandardTerrainEffects) action].PaintEffect(
|
m_painteffects[(StandardTerrainEffects) action].PaintEffect(
|
||||||
m_channel, allowMask, west, south, height, size, seconds);
|
m_channel, allowMask, west, south, height, size, seconds);
|
||||||
|
|
||||||
CheckForTerrainUpdates(!god); //revert changes outside estate limits
|
//CheckForTerrainUpdates(!god); //revert changes outside estate limits
|
||||||
|
//DSG SYNC
|
||||||
|
CheckForTerrainUpdates(!god, DateTime.Now.Ticks, m_scene.GetSyncActorID());
|
||||||
|
//end of DSG SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -824,7 +938,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
m_floodeffects[(StandardTerrainEffects) action].FloodEffect(
|
m_floodeffects[(StandardTerrainEffects) action].FloodEffect(
|
||||||
m_channel, fillArea, size);
|
m_channel, fillArea, size);
|
||||||
|
|
||||||
CheckForTerrainUpdates(!god); //revert changes outside estate limits
|
//CheckForTerrainUpdates(!god); //revert changes outside estate limits
|
||||||
|
//DSG SYNC
|
||||||
|
CheckForTerrainUpdates(!god, DateTime.Now.Ticks, m_scene.GetSyncActorID());
|
||||||
|
//end of DSG SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -56,6 +56,7 @@ namespace OpenSim.Region.Examples.SimpleModule
|
||||||
|
|
||||||
public event ImprovedInstantMessage OnInstantMessage;
|
public event ImprovedInstantMessage OnInstantMessage;
|
||||||
public event ChatMessage OnChatFromClient;
|
public event ChatMessage OnChatFromClient;
|
||||||
|
public event ChatMessageRaw OnChatFromClientRaw;
|
||||||
public event TextureRequest OnRequestTexture;
|
public event TextureRequest OnRequestTexture;
|
||||||
public event RezObject OnRezObject;
|
public event RezObject OnRezObject;
|
||||||
public event ModifyTerrain OnModifyTerrain;
|
public event ModifyTerrain OnModifyTerrain;
|
||||||
|
@ -75,6 +76,9 @@ namespace OpenSim.Region.Examples.SimpleModule
|
||||||
public event RequestMapBlocks OnRequestMapBlocks;
|
public event RequestMapBlocks OnRequestMapBlocks;
|
||||||
public event RequestMapName OnMapNameRequest;
|
public event RequestMapName OnMapNameRequest;
|
||||||
public event TeleportLocationRequest OnTeleportLocationRequest;
|
public event TeleportLocationRequest OnTeleportLocationRequest;
|
||||||
|
//DSG:
|
||||||
|
public event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
|
||||||
|
//end of DSG
|
||||||
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
|
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
|
||||||
public event DisconnectUser OnDisconnectUser;
|
public event DisconnectUser OnDisconnectUser;
|
||||||
public event RequestAvatarProperties OnRequestAvatarProperties;
|
public event RequestAvatarProperties OnRequestAvatarProperties;
|
||||||
|
@ -86,6 +90,7 @@ namespace OpenSim.Region.Examples.SimpleModule
|
||||||
public event GenericCall1 OnCompleteMovementToRegion;
|
public event GenericCall1 OnCompleteMovementToRegion;
|
||||||
public event UpdateAgent OnPreAgentUpdate;
|
public event UpdateAgent OnPreAgentUpdate;
|
||||||
public event UpdateAgent OnAgentUpdate;
|
public event UpdateAgent OnAgentUpdate;
|
||||||
|
public event UpdateAgentRaw OnAgentUpdateRaw;
|
||||||
public event AgentRequestSit OnAgentRequestSit;
|
public event AgentRequestSit OnAgentRequestSit;
|
||||||
public event AgentSit OnAgentSit;
|
public event AgentSit OnAgentSit;
|
||||||
public event AvatarPickerRequest OnAvatarPickerRequest;
|
public event AvatarPickerRequest OnAvatarPickerRequest;
|
||||||
|
@ -400,6 +405,11 @@ namespace OpenSim.Region.Examples.SimpleModule
|
||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint MaxCoarseLocations
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void ActivateGesture(UUID assetId, UUID gestureId)
|
public virtual void ActivateGesture(UUID assetId, UUID gestureId)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,5 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
bool ValidateBakedTextureCache(IClientAPI client);
|
bool ValidateBakedTextureCache(IClientAPI client);
|
||||||
void QueueAppearanceSend(UUID agentid);
|
void QueueAppearanceSend(UUID agentid);
|
||||||
void QueueAppearanceSave(UUID agentid);
|
void QueueAppearanceSave(UUID agentid);
|
||||||
|
void RefreshAppearance(UUID agentid);
|
||||||
|
void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,10 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
ArrayList GetScriptErrors(UUID itemID);
|
ArrayList GetScriptErrors(UUID itemID);
|
||||||
void ResumeScripts();
|
void ResumeScripts();
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
void SuspendScripts();
|
||||||
|
#endregion REGION SYNC
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop all the scripts in this entity.
|
/// Stop all the scripts in this entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -229,5 +233,8 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// A <see cref="Dictionary`2"/>
|
/// A <see cref="Dictionary`2"/>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
Dictionary<UUID, string> GetScriptStates();
|
Dictionary<UUID, string> GetScriptStates();
|
||||||
|
|
||||||
|
//DSG
|
||||||
|
bool UpdateInventoryItemBySync(TaskInventoryItem item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
public interface IGridDialogModule
|
||||||
|
{
|
||||||
|
void SendGridDialogViaXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName,
|
||||||
|
string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,5 +37,8 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
event UndeliveredMessage OnUndeliveredMessage;
|
event UndeliveredMessage OnUndeliveredMessage;
|
||||||
|
|
||||||
void SendInstantMessage(GridInstantMessage im, MessageResultNotification result);
|
void SendInstantMessage(GridInstantMessage im, MessageResultNotification result);
|
||||||
|
|
||||||
|
//DSG: add this to the interface to enable outsiders to call it
|
||||||
|
void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//KittyL: Added to support running script engine actor
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
//the interface for Scene to sync with Script Engine
|
||||||
|
public interface IPhysEngineToSceneConnector
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//KittyL: Added to support running script engine actor
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
//the interface for Scene to sync with Script Engine
|
||||||
|
public interface IPhysEngineToSceneConnectorModule
|
||||||
|
{
|
||||||
|
bool IsPhysEngineScene();
|
||||||
|
bool IsActivePhysEngineScene();
|
||||||
|
bool IsPhysEngineActor();
|
||||||
|
bool DebugWithViewer { get; }
|
||||||
|
void SendUpdate(PhysicsActor pa);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
public interface IRegionSyncClientModule
|
||||||
|
{
|
||||||
|
bool Active { get; }
|
||||||
|
bool Synced { get; }
|
||||||
|
void SendCoarseLocations();
|
||||||
|
void SendAppearanceToScene(UUID agentID);
|
||||||
|
void IncomingLoadBalanceConnection(ScenePresence presence);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//KittyL: Added to support running script engine actor
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
public enum DSGActorTypes
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
ScenePersistence, //the Scene (data store), which is now considered as a persistence actor
|
||||||
|
ClientManager,
|
||||||
|
ScriptEngine,
|
||||||
|
PhysicsEngine
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//Interface for SceneGraph to call into RegionSyncModule
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
public interface IRegionSyncModule
|
||||||
|
{
|
||||||
|
bool Active { get; } //if true, this RegionSyncModule is connected into the synchronization overlay
|
||||||
|
string ActorID { get; } //might be phased out soon
|
||||||
|
string SyncID { get; }
|
||||||
|
//DSGActorTypes DSGActorType { get; set; }
|
||||||
|
bool IsSyncRelay { get; }
|
||||||
|
|
||||||
|
void ProcessAndEnqueuePrimUpdatesByLocal(SceneObjectPart part, List<SceneObjectPartSyncProperties> updatedProperties);
|
||||||
|
void SyncOutPrimUpdates();
|
||||||
|
|
||||||
|
//New functions for per property sync'ing
|
||||||
|
void SyncNewObject(SceneObjectGroup sog);
|
||||||
|
void SyncDeleteObject(SceneObjectGroup sog, bool softDelete);
|
||||||
|
void SyncLinkObject(SceneObjectGroup linkedGroup, SceneObjectPart root, List<SceneObjectPart> children);
|
||||||
|
void SyncDeLinkObject(List<SceneObjectPart> prims, List<SceneObjectGroup> beforeDelinkGroups, List<SceneObjectGroup> afterDelinkGroups);
|
||||||
|
|
||||||
|
void SendTerrainUpdates(long updateTimeStamp, string lastUpdateActorID);
|
||||||
|
//For propogating scene events to other actors
|
||||||
|
void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs);
|
||||||
|
|
||||||
|
//TODO LIST:
|
||||||
|
//Special API for handling avatars
|
||||||
|
//void QueuePresenceForTerseUpdate(ScenePresence presence)
|
||||||
|
//void SendAvatarUpdates();
|
||||||
|
|
||||||
|
//Debug purpose, mainly for debugging properties updated by LSL scripts
|
||||||
|
void Debug(String debugMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for invoking DSGActor specific functions or accessing members whose values depend on the actor's type.
|
||||||
|
/// </summary>
|
||||||
|
public interface IDSGActorSyncModule
|
||||||
|
{
|
||||||
|
DSGActorTypes ActorType { get; }
|
||||||
|
string ActorID { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
public interface IRegionSyncServerModule
|
||||||
|
{
|
||||||
|
|
||||||
|
//void Scene_AddNewPrim(SceneObjectGroup sog);
|
||||||
|
|
||||||
|
bool Active { get; }
|
||||||
|
bool Synced { get; }
|
||||||
|
|
||||||
|
void QueuePresenceForTerseUpdate(ScenePresence presence);
|
||||||
|
void SendUpdates();
|
||||||
|
void SendAppearance(UUID agentID);
|
||||||
|
void SendAnimations(UUID agentID, UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
|
||||||
|
|
||||||
|
void SendTeleportUpdate(ScenePresence presence);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//KittyL: Added to support running script engine actor
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
//the interface for Scene to sync with Script Engine
|
||||||
|
public interface ISceneToPhysEngineConnector
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//KittyL: Added to support running script engine actor
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
//the interface for Scene to sync with Script Engine
|
||||||
|
public interface ISceneToPhysEngineServer
|
||||||
|
{
|
||||||
|
bool IsPhysEngineScene();
|
||||||
|
bool IsActivePhysEngineScene();
|
||||||
|
bool IsPhysEngineActor();
|
||||||
|
void SendUpdate(PhysicsActor pa);
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,7 +34,8 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
{
|
{
|
||||||
void Reset();
|
void Reset();
|
||||||
void Close();
|
void Close();
|
||||||
void QueuePartForUpdate(SceneObjectPart part);
|
//void QueuePartForUpdate(SceneObjectPart part);
|
||||||
|
void QueuePartForUpdate(SceneObjectPartBase part);
|
||||||
void SendPrimUpdates();
|
void SendPrimUpdates();
|
||||||
int GetPendingObjectsCount();
|
int GetPendingObjectsCount();
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,9 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// <param name="regionUUID">the Region UUID</param>
|
/// <param name="regionUUID">the Region UUID</param>
|
||||||
/// <returns>List of loaded groups</returns>
|
/// <returns>List of loaded groups</returns>
|
||||||
List<SceneObjectGroup> LoadObjects(UUID regionUUID);
|
List<SceneObjectGroup> LoadObjects(UUID regionUUID);
|
||||||
|
#region REGION SYNC
|
||||||
|
List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY);
|
||||||
|
#endregion REGION SYNC
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Store a terrain revision in region storage
|
/// Store a terrain revision in region storage
|
||||||
|
|
|
@ -73,6 +73,9 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// <param name="regionUUID">the Region UUID</param>
|
/// <param name="regionUUID">the Region UUID</param>
|
||||||
/// <returns>List of loaded groups</returns>
|
/// <returns>List of loaded groups</returns>
|
||||||
List<SceneObjectGroup> LoadObjects(UUID regionUUID);
|
List<SceneObjectGroup> LoadObjects(UUID regionUUID);
|
||||||
|
#region REGION SYNC
|
||||||
|
List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY);
|
||||||
|
#endregion REGION SYNC
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Store a terrain revision in region storage
|
/// Store a terrain revision in region storage
|
||||||
|
|
|
@ -64,5 +64,38 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
void InstallPlugin(string name, ITerrainEffect plug);
|
void InstallPlugin(string name, ITerrainEffect plug);
|
||||||
|
|
||||||
void UndoTerrain(ITerrainChannel channel);
|
void UndoTerrain(ITerrainChannel channel);
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked by receiving a terrain sync message. First, check if the
|
||||||
|
/// timestamp is more advance than the local copy. If so, update the
|
||||||
|
/// local terrain copy.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timeStamp">The time that the updated terrain was
|
||||||
|
/// created</param>
|
||||||
|
/// <param name="actorID">The actor who created the update.</param>
|
||||||
|
/// <param name="terrainData">The updated terrain</param>
|
||||||
|
bool UpdateTerrianBySync(long timeStamp, string actorID, string terrainData);
|
||||||
|
/// <summary>
|
||||||
|
/// Return true if the most recent update on terrain is done locally (i.e. not by receiving a terrain-sync message).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localActorID"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool TerrianModifiedLocally(string localActorID);
|
||||||
|
/// <summary>
|
||||||
|
/// Obtain the timestemp and actorID information for the most recent update on terrain.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lastUpdateTimeStamp"></param>
|
||||||
|
/// <param name="lastUpdateActorID"></param>
|
||||||
|
void GetSyncInfo(out long lastUpdateTimeStamp, out string lastUpdateActorID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is only supposed to be called by Persistence actor, which will
|
||||||
|
/// set the timestamp and actorID values for terrain upon initialization time.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lastUpdateTimeStamp"></param>
|
||||||
|
/// <param name="lastUpdateActorID"></param>
|
||||||
|
void SetSyncInfo(long lastUpdateTimeStamp, string lastUpdateActorID);
|
||||||
|
//end of DSG SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
||||||
public string CurrentMovementAnimation
|
public string CurrentMovementAnimation
|
||||||
{
|
{
|
||||||
get { return m_movementAnimation; }
|
get { return m_movementAnimation; }
|
||||||
|
set { m_movementAnimation = value; }
|
||||||
}
|
}
|
||||||
protected string m_movementAnimation = "DEFAULT";
|
protected string m_movementAnimation = "DEFAULT";
|
||||||
|
|
||||||
|
@ -404,6 +405,13 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
||||||
{
|
{
|
||||||
if (m_scenePresence.IsChildAgent)
|
if (m_scenePresence.IsChildAgent)
|
||||||
return;
|
return;
|
||||||
|
if (m_scenePresence.Scene.IsSyncedServer())
|
||||||
|
{
|
||||||
|
m_scenePresence.Scene.RegionSyncServerModule.SendAnimations(
|
||||||
|
m_scenePresence.ControllingClient.AgentId, animations, seqs,
|
||||||
|
m_scenePresence.ControllingClient.AgentId, objectIDs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_scenePresence.Scene.ForEachClient(
|
m_scenePresence.Scene.ForEachClient(
|
||||||
delegate(IClientAPI client)
|
delegate(IClientAPI client)
|
||||||
|
|
|
@ -38,10 +38,361 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Scenes
|
namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
|
//DSG SYNC: Rename the original EventManager as EventManagerBase, and implement a new EventManager that inherits from EventManagerBase
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A class for triggering remote scene events.
|
/// A wrapper class to implement handle event differently depending on if they are initiated locally or remotelly (i.e. by another actor)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EventManager
|
public class EventManager: EventManagerBase
|
||||||
|
{
|
||||||
|
private Scene m_scene;
|
||||||
|
|
||||||
|
//the events that we'll handle specially in sym-sync
|
||||||
|
public enum EventNames
|
||||||
|
{
|
||||||
|
NewScript,
|
||||||
|
UpdateScript,
|
||||||
|
ScriptReset,
|
||||||
|
ChatFromClient, //chats from avatars
|
||||||
|
ChatFromWorld, //chats from objects
|
||||||
|
ChatBroadcast, //broadcast
|
||||||
|
ObjectGrab,
|
||||||
|
ObjectGrabbing,
|
||||||
|
ObjectDeGrab,
|
||||||
|
Attach, //attaching object to avatar
|
||||||
|
PhysicsCollision,
|
||||||
|
ScriptCollidingStart,
|
||||||
|
ScriptColliding,
|
||||||
|
ScriptCollidingEnd,
|
||||||
|
ScriptLandCollidingStart,
|
||||||
|
ScriptLandColliding,
|
||||||
|
ScriptLandCollidingEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventManager(Scene scene)
|
||||||
|
{
|
||||||
|
m_scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region NewScript
|
||||||
|
//triggered by client.OnRezScript
|
||||||
|
public override void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID)
|
||||||
|
{
|
||||||
|
//publish the event to other actors who are intersted in it
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[3];
|
||||||
|
eventArgs[0] = (Object)clientID;
|
||||||
|
eventArgs[1] = (Object)part;
|
||||||
|
eventArgs[2] = (Object)itemID;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.NewScript, eventArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
//trigger event locally,
|
||||||
|
TriggerNewScriptLocally(clientID, part, itemID);
|
||||||
|
}
|
||||||
|
//public void TriggerNewScriptLocally(UUID clientID, UUID itemId, UUID primId, UUID newAssetID)
|
||||||
|
public void TriggerNewScriptLocally(UUID clientID, SceneObjectPart part, UUID itemID)
|
||||||
|
{
|
||||||
|
base.TriggerNewScript(clientID, part, itemID);
|
||||||
|
}
|
||||||
|
#endregion //UpdateScript
|
||||||
|
|
||||||
|
#region UpdateScript
|
||||||
|
public override void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
|
||||||
|
{
|
||||||
|
//publish the event to other actors who are intersted in it
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[5];
|
||||||
|
eventArgs[0] = (Object) clientId;
|
||||||
|
eventArgs[1] = (Object)itemId;
|
||||||
|
eventArgs[2] = (Object)primId;
|
||||||
|
eventArgs[3] = (Object)isScriptRunning;
|
||||||
|
eventArgs[4] = (Object)newAssetID;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.UpdateScript, eventArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
//trigger event locally,
|
||||||
|
TriggerUpdateScriptLocally(clientId, itemId, primId, isScriptRunning, newAssetID);
|
||||||
|
}
|
||||||
|
public void TriggerUpdateScriptLocally(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
|
||||||
|
{
|
||||||
|
base.TriggerUpdateScript(clientId, itemId, primId, isScriptRunning, newAssetID);
|
||||||
|
}
|
||||||
|
#endregion //UpdateScript
|
||||||
|
|
||||||
|
#region ScriptReset
|
||||||
|
public override void TriggerScriptReset(uint localID, UUID itemID)
|
||||||
|
{
|
||||||
|
//publish the event to other actors who are intersted in it
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[2];
|
||||||
|
eventArgs[0] = (Object)localID;
|
||||||
|
eventArgs[1] = (Object)itemID;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptReset, eventArgs);
|
||||||
|
}
|
||||||
|
//trigger event locally, as the legacy code does
|
||||||
|
TriggerScriptResetLocally(localID, itemID);
|
||||||
|
}
|
||||||
|
public void TriggerScriptResetLocally(uint localID, UUID itemID)
|
||||||
|
{
|
||||||
|
base.TriggerScriptReset(localID, itemID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //UpdateScript
|
||||||
|
|
||||||
|
#region ChatFromClient
|
||||||
|
public override void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[2];
|
||||||
|
eventArgs[0] = sender;
|
||||||
|
eventArgs[1] = (Object)chat;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ChatFromClient, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerOnChatFromClientLocally(sender, chat);
|
||||||
|
}
|
||||||
|
public void TriggerOnChatFromClientLocally(Object sender, OSChatMessage chat)
|
||||||
|
{
|
||||||
|
base.TriggerOnChatFromClient(sender, chat);
|
||||||
|
}
|
||||||
|
#endregion //ChatFromClient
|
||||||
|
|
||||||
|
#region ChatBroadcast
|
||||||
|
|
||||||
|
public override void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[2];
|
||||||
|
eventArgs[0] = sender;
|
||||||
|
eventArgs[1] = (Object)chat;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ChatBroadcast, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerOnChatBroadcastLocally(sender, chat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerOnChatBroadcastLocally(Object sender, OSChatMessage chat)
|
||||||
|
{
|
||||||
|
base.TriggerOnChatBroadcast(sender, chat);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region ChatFromWorld
|
||||||
|
|
||||||
|
public override void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[2];
|
||||||
|
eventArgs[0] = sender;
|
||||||
|
eventArgs[1] = (Object)chat;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ChatFromWorld, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerOnChatFromWorldLocally(sender, chat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerOnChatFromWorldLocally(Object sender, OSChatMessage chat)
|
||||||
|
{
|
||||||
|
base.TriggerOnChatFromWorld(sender, chat);
|
||||||
|
}
|
||||||
|
#endregion //ChatFromWorld
|
||||||
|
|
||||||
|
#region ObjectGrab, ObjectGrabbing, ObjectDeGrab
|
||||||
|
public override void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[5];
|
||||||
|
eventArgs[0] = (Object)localID;
|
||||||
|
eventArgs[1] = (Object)originalID;
|
||||||
|
eventArgs[2] = (Object)offsetPos;
|
||||||
|
eventArgs[3] = (Object)remoteClient;
|
||||||
|
eventArgs[4] = (Object)surfaceArgs;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ObjectGrab, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerObjectGrabLocally(localID, originalID, offsetPos, remoteClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
public void TriggerObjectGrabLocally(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
{
|
||||||
|
base.TriggerObjectGrab(localID, originalID, offsetPos, remoteClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void TriggerObjectGrabbing(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[5];
|
||||||
|
eventArgs[0] = (Object)localID;
|
||||||
|
eventArgs[1] = (Object)originalID;
|
||||||
|
eventArgs[2] = (Object)offsetPos;
|
||||||
|
eventArgs[3] = (Object)remoteClient;
|
||||||
|
eventArgs[4] = (Object)surfaceArgs;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ObjectGrabbing, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerObjectGrabbingLocally(localID, originalID, offsetPos, remoteClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerObjectGrabbingLocally(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
{
|
||||||
|
base.TriggerObjectGrabbing(localID, originalID, offsetPos, remoteClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[4];
|
||||||
|
eventArgs[0] = (Object)localID;
|
||||||
|
eventArgs[1] = (Object)originalID;
|
||||||
|
eventArgs[2] = (Object)remoteClient;
|
||||||
|
eventArgs[3] = (Object)surfaceArgs;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ObjectDeGrab, eventArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerObjectDeGrabLocally(localID, originalID, remoteClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerObjectDeGrabLocally(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
{
|
||||||
|
base.TriggerObjectDeGrab(localID, originalID, remoteClient, surfaceArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[4];
|
||||||
|
eventArgs[0] = (Object)localID;
|
||||||
|
eventArgs[1] = (Object)itemID;
|
||||||
|
eventArgs[2] = (Object)avatarID;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.Attach, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerOnAttachLocally(localID, itemID, avatarID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerOnAttachLocally(uint localID, UUID itemID, UUID avatarID)
|
||||||
|
{
|
||||||
|
base.TriggerOnAttach(localID, itemID, avatarID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //GrabObject
|
||||||
|
|
||||||
|
#region collisions
|
||||||
|
public override void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[4];
|
||||||
|
eventArgs[0] = (Object)localId;
|
||||||
|
eventArgs[1] = (Object)colliders;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptCollidingStart, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerScriptCollidingStartLocally(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerScriptCollidingStartLocally(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
base.TriggerScriptCollidingStart(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void TriggerScriptColliding(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[4];
|
||||||
|
eventArgs[0] = (Object)localId;
|
||||||
|
eventArgs[1] = (Object)colliders;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptColliding, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerScriptCollidingLocally(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerScriptCollidingLocally(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
base.TriggerScriptColliding(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[4];
|
||||||
|
eventArgs[0] = (Object)localId;
|
||||||
|
eventArgs[1] = (Object)colliders;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptCollidingEnd, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerScriptCollidingEndLocally(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerScriptCollidingEndLocally(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
base.TriggerScriptCollidingEnd(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void TriggerScriptLandCollidingStart(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[4];
|
||||||
|
eventArgs[0] = (Object)localId;
|
||||||
|
eventArgs[1] = (Object)colliders;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptLandCollidingStart, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerScriptLandCollidingStartLocally(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerScriptLandCollidingStartLocally(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
base.TriggerScriptLandCollidingStart(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void TriggerScriptLandColliding(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[4];
|
||||||
|
eventArgs[0] = (Object)localId;
|
||||||
|
eventArgs[1] = (Object)colliders;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptLandColliding, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerScriptLandCollidingLocally(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerScriptLandCollidingLocally(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
base.TriggerScriptLandColliding(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void TriggerScriptLandCollidingEnd(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
if (m_scene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
Object[] eventArgs = new Object[4];
|
||||||
|
eventArgs[0] = (Object)localId;
|
||||||
|
eventArgs[1] = (Object)colliders;
|
||||||
|
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptLandCollidingEnd, eventArgs);
|
||||||
|
}
|
||||||
|
TriggerScriptLandCollidingEndLocally(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerScriptLandCollidingEndLocally(uint localId, ColliderArgs colliders)
|
||||||
|
{
|
||||||
|
base.TriggerScriptLandCollidingEnd(localId, colliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A class for triggering scene events.
|
||||||
|
/// </summary>
|
||||||
|
public class EventManagerBase
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
@ -461,7 +812,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public event LandBuy OnLandBuy;
|
public event LandBuy OnLandBuy;
|
||||||
public event LandBuy OnValidateLandBuy;
|
public event LandBuy OnValidateLandBuy;
|
||||||
|
|
||||||
public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
|
//public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
|
||||||
|
public virtual void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
|
||||||
{
|
{
|
||||||
Attach handlerOnAttach = OnAttach;
|
Attach handlerOnAttach = OnAttach;
|
||||||
if (handlerOnAttach != null)
|
if (handlerOnAttach != null)
|
||||||
|
@ -882,7 +1234,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
//DSG SYNC: overridden at new EventManager class
|
||||||
|
//public void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
public virtual void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
{
|
{
|
||||||
ObjectGrabDelegate handlerObjectGrab = OnObjectGrab;
|
ObjectGrabDelegate handlerObjectGrab = OnObjectGrab;
|
||||||
if (handlerObjectGrab != null)
|
if (handlerObjectGrab != null)
|
||||||
|
@ -903,7 +1257,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerObjectGrabbing(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
//DSG SYNC: overridden at new EventManager class
|
||||||
|
//public void TriggerObjectGrabbing(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
public virtual void TriggerObjectGrabbing(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
{
|
{
|
||||||
ObjectGrabDelegate handlerObjectGrabbing = OnObjectGrabbing;
|
ObjectGrabDelegate handlerObjectGrabbing = OnObjectGrabbing;
|
||||||
if (handlerObjectGrabbing != null)
|
if (handlerObjectGrabbing != null)
|
||||||
|
@ -924,7 +1280,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
//DSG SYNC: overridden at new EventManager class
|
||||||
|
//public void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
|
public virtual void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
|
||||||
{
|
{
|
||||||
ObjectDeGrabDelegate handlerObjectDeGrab = OnObjectDeGrab;
|
ObjectDeGrabDelegate handlerObjectDeGrab = OnObjectDeGrab;
|
||||||
if (handlerObjectDeGrab != null)
|
if (handlerObjectDeGrab != null)
|
||||||
|
@ -945,7 +1303,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerScriptReset(uint localID, UUID itemID)
|
//public void TriggerScriptReset(uint localID, UUID itemID)
|
||||||
|
public virtual void TriggerScriptReset(uint localID, UUID itemID)
|
||||||
{
|
{
|
||||||
ScriptResetDelegate handlerScriptReset = OnScriptReset;
|
ScriptResetDelegate handlerScriptReset = OnScriptReset;
|
||||||
if (handlerScriptReset != null)
|
if (handlerScriptReset != null)
|
||||||
|
@ -1613,7 +1972,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
|
//DSG SYNC: the function is overridden in new EventManager
|
||||||
|
//public void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
|
||||||
|
public virtual void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
|
||||||
{
|
{
|
||||||
ChatFromWorldEvent handlerChatFromWorld = OnChatFromWorld;
|
ChatFromWorldEvent handlerChatFromWorld = OnChatFromWorld;
|
||||||
if (handlerChatFromWorld != null)
|
if (handlerChatFromWorld != null)
|
||||||
|
@ -1634,7 +1995,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
|
//DSG SYNC: overiding this in the inherited class
|
||||||
|
//public void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
|
||||||
|
public virtual void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
|
||||||
{
|
{
|
||||||
ChatFromClientEvent handlerChatFromClient = OnChatFromClient;
|
ChatFromClientEvent handlerChatFromClient = OnChatFromClient;
|
||||||
if (handlerChatFromClient != null)
|
if (handlerChatFromClient != null)
|
||||||
|
@ -1679,7 +2042,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
|
//public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
|
||||||
|
public virtual void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
|
||||||
{
|
{
|
||||||
ChatBroadcastEvent handlerChatBroadcast = OnChatBroadcast;
|
ChatBroadcastEvent handlerChatBroadcast = OnChatBroadcast;
|
||||||
if (handlerChatBroadcast != null)
|
if (handlerChatBroadcast != null)
|
||||||
|
@ -1951,7 +2315,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
|
//public void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
|
||||||
|
public virtual void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
|
||||||
{
|
{
|
||||||
ScriptColliding handlerCollidingStart = OnScriptColliderStart;
|
ScriptColliding handlerCollidingStart = OnScriptColliderStart;
|
||||||
if (handlerCollidingStart != null)
|
if (handlerCollidingStart != null)
|
||||||
|
@ -1972,7 +2337,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerScriptColliding(uint localId, ColliderArgs colliders)
|
//public void TriggerScriptColliding(uint localId, ColliderArgs colliders)
|
||||||
|
public virtual void TriggerScriptColliding(uint localId, ColliderArgs colliders)
|
||||||
{
|
{
|
||||||
ScriptColliding handlerColliding = OnScriptColliding;
|
ScriptColliding handlerColliding = OnScriptColliding;
|
||||||
if (handlerColliding != null)
|
if (handlerColliding != null)
|
||||||
|
@ -1993,7 +2359,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
|
//public void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
|
||||||
|
public virtual void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
|
||||||
{
|
{
|
||||||
ScriptColliding handlerCollidingEnd = OnScriptCollidingEnd;
|
ScriptColliding handlerCollidingEnd = OnScriptCollidingEnd;
|
||||||
if (handlerCollidingEnd != null)
|
if (handlerCollidingEnd != null)
|
||||||
|
@ -2014,7 +2381,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerScriptLandCollidingStart(uint localId, ColliderArgs colliders)
|
//public void TriggerScriptLandCollidingStart(uint localId, ColliderArgs colliders)
|
||||||
|
public virtual void TriggerScriptLandCollidingStart(uint localId, ColliderArgs colliders)
|
||||||
{
|
{
|
||||||
ScriptColliding handlerLandCollidingStart = OnScriptLandColliderStart;
|
ScriptColliding handlerLandCollidingStart = OnScriptLandColliderStart;
|
||||||
if (handlerLandCollidingStart != null)
|
if (handlerLandCollidingStart != null)
|
||||||
|
@ -2035,7 +2403,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerScriptLandColliding(uint localId, ColliderArgs colliders)
|
//public void TriggerScriptLandColliding(uint localId, ColliderArgs colliders)
|
||||||
|
public virtual void TriggerScriptLandColliding(uint localId, ColliderArgs colliders)
|
||||||
{
|
{
|
||||||
ScriptColliding handlerLandColliding = OnScriptLandColliding;
|
ScriptColliding handlerLandColliding = OnScriptLandColliding;
|
||||||
if (handlerLandColliding != null)
|
if (handlerLandColliding != null)
|
||||||
|
@ -2056,7 +2425,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerScriptLandCollidingEnd(uint localId, ColliderArgs colliders)
|
//public void TriggerScriptLandCollidingEnd(uint localId, ColliderArgs colliders)
|
||||||
|
public virtual void TriggerScriptLandCollidingEnd(uint localId, ColliderArgs colliders)
|
||||||
{
|
{
|
||||||
ScriptColliding handlerLandCollidingEnd = OnScriptLandColliderEnd;
|
ScriptColliding handlerLandCollidingEnd = OnScriptLandColliderEnd;
|
||||||
if (handlerLandCollidingEnd != null)
|
if (handlerLandCollidingEnd != null)
|
||||||
|
@ -2118,7 +2488,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerOnSceneObjectLoaded(SceneObjectGroup so)
|
public void TriggerOnSceneObjectLoaded(SceneObjectGroup so)
|
||||||
{
|
{
|
||||||
SceneObjectDelegate handler = OnSceneObjectLoaded;
|
SceneObjectDelegate handler = OnSceneObjectLoaded;
|
||||||
|
@ -2139,7 +2509,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerOnSceneObjectPreSave(SceneObjectGroup persistingSo, SceneObjectGroup originalSo)
|
public void TriggerOnSceneObjectPreSave(SceneObjectGroup persistingSo, SceneObjectGroup originalSo)
|
||||||
{
|
{
|
||||||
SceneObjectPreSaveDelegate handler = OnSceneObjectPreSave;
|
SceneObjectPreSaveDelegate handler = OnSceneObjectPreSave;
|
||||||
|
@ -2266,5 +2636,179 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//REGION SYNC
|
||||||
|
#region REGION SYNC RELATED EVENTS
|
||||||
|
//OnScriptEngineSyncStop: triggered when user types "sync stop" on the script engine's console
|
||||||
|
public delegate void ScriptEngineSyncStop();
|
||||||
|
public event ScriptEngineSyncStop OnScriptEngineSyncStop;
|
||||||
|
public void TriggerScriptEngineSyncStop()
|
||||||
|
{
|
||||||
|
ScriptEngineSyncStop handlerScriptEngineSyncStop = OnScriptEngineSyncStop;
|
||||||
|
if (handlerScriptEngineSyncStop != null)
|
||||||
|
{
|
||||||
|
foreach (ScriptEngineSyncStop d in handlerScriptEngineSyncStop.GetInvocationList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[EVENT MANAGER]: Delegate for TriggerScriptEngineSyncStop failed - continuing. {0} {1}",
|
||||||
|
e.Message, e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void NewScript(UUID clientID, SceneObjectPart part, UUID itemID);
|
||||||
|
public event NewScript OnNewScript;
|
||||||
|
public virtual void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID)
|
||||||
|
{
|
||||||
|
NewScript handlerNewScript = OnNewScript;
|
||||||
|
if (handlerNewScript != null)
|
||||||
|
{
|
||||||
|
foreach (NewScript d in handlerNewScript.GetInvocationList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d(clientID, part, itemID);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[EVENT MANAGER]: Delegate for TriggerNewScript failed - continuing. {0} {1}",
|
||||||
|
e.Message, e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TriggerUpdateScript: triggered after Scene receives client's upload of updated script and stores it as asset
|
||||||
|
public delegate void UpdateScript(UUID clientID, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID);
|
||||||
|
public event UpdateScript OnUpdateScript;
|
||||||
|
public virtual void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
|
||||||
|
{
|
||||||
|
UpdateScript handlerUpdateScript = OnUpdateScript;
|
||||||
|
if (handlerUpdateScript != null)
|
||||||
|
{
|
||||||
|
foreach (UpdateScript d in handlerUpdateScript.GetInvocationList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d(clientId, itemId, primId, isScriptRunning, newAssetID);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[EVENT MANAGER]: Delegate for TriggerUpdateScript failed - continuing. {0} {1}",
|
||||||
|
e.Message, e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//OnPopulateLocalSceneList: Triggered by OpenSim to the valid local scene, should only happen in script engine
|
||||||
|
public delegate void PopulateLocalSceneList(List<Scene> localScenes);
|
||||||
|
public event PopulateLocalSceneList OnPopulateLocalSceneList;
|
||||||
|
public void TriggerPopulateLocalSceneList(List<Scene> localScenes)
|
||||||
|
//public delegate void PopulateLocalSceneList(List<Scene> localScenes, string[] cmdparams);
|
||||||
|
//public event PopulateLocalSceneList OnPopulateLocalSceneList;
|
||||||
|
//public void TriggerPopulateLocalSceneList(List<Scene> localScenes, string[] cmdparams)
|
||||||
|
{
|
||||||
|
PopulateLocalSceneList handlerPopulateLocalSceneList = OnPopulateLocalSceneList;
|
||||||
|
if (handlerPopulateLocalSceneList != null)
|
||||||
|
{
|
||||||
|
foreach (PopulateLocalSceneList d in handlerPopulateLocalSceneList.GetInvocationList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d(localScenes);
|
||||||
|
//d(localScenes, cmdparams);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[EVENT MANAGER]: Delegate for TriggerPopulateLocalSceneList failed - continuing. {0} {1}",
|
||||||
|
e.Message, e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
public event PostSceneCreation OnPostSceneCreation;
|
||||||
|
public delegate void PostSceneCreation(Scene createdScene);
|
||||||
|
public void TriggerOnPostSceneCreation(Scene createdScene)
|
||||||
|
{
|
||||||
|
PostSceneCreation handler = OnPostSceneCreation;
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
foreach (PostSceneCreation d in handler.GetInvocationList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d(createdScene);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[EVENT MANAGER]: Delegate for TriggerOnPostSceneCreation failed - continuing. {0} {1}",
|
||||||
|
e.Message, e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void SymmetricSyncStop();
|
||||||
|
public event SymmetricSyncStop OnSymmetricSyncStop;
|
||||||
|
public void TriggerOnSymmetricSyncStop()
|
||||||
|
{
|
||||||
|
SymmetricSyncStop handlerSymmetricSyncStop = OnSymmetricSyncStop;
|
||||||
|
if (handlerSymmetricSyncStop != null)
|
||||||
|
{
|
||||||
|
foreach (SymmetricSyncStop d in handlerSymmetricSyncStop.GetInvocationList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[EVENT MANAGER]: Delegate for TriggerOnSymmetricSyncStop failed - continuing. {0} {1}",
|
||||||
|
e.Message, e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void AggregateScriptEvents(SceneObjectPart part);
|
||||||
|
public event AggregateScriptEvents OnAggregateScriptEvents;
|
||||||
|
public void TriggerAggregateScriptEvents(SceneObjectPart part)
|
||||||
|
{
|
||||||
|
AggregateScriptEvents handlerAggregateScriptEvents = OnAggregateScriptEvents;
|
||||||
|
if (handlerAggregateScriptEvents != null)
|
||||||
|
{
|
||||||
|
foreach (AggregateScriptEvents d in handlerAggregateScriptEvents.GetInvocationList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d(part);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[EVENT MANAGER]: Delegate for TriggerAggregateScriptEvents failed - continuing. {0} {1}",
|
||||||
|
e.Message, e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end of DSG SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,6 +204,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return UUID.Zero;
|
return UUID.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//REGION SYNC
|
||||||
|
//Scene does permission checking, asset creation and storing, then informs Script Engine to
|
||||||
|
//update the script.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Capability originating call to update the asset of a script in a prim's (task's) inventory
|
/// Capability originating call to update the asset of a script in a prim's (task's) inventory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -250,10 +255,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data, remoteClient.AgentId);
|
AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data, remoteClient.AgentId);
|
||||||
AssetService.Store(asset);
|
AssetService.Store(asset);
|
||||||
|
|
||||||
if (isScriptRunning)
|
//REGION SYNC: if RegionSyncEnabled, move script related operations to be after update inventory item
|
||||||
|
//DSG SYNC: commenting out old REGION SYNC code, the RemoveScriptInstance would be handled by ScriptEngineSyncModule
|
||||||
|
/*
|
||||||
|
if (!RegionSyncEnabled)
|
||||||
{
|
{
|
||||||
part.Inventory.RemoveScriptInstance(item.ItemID, false);
|
if (isScriptRunning)
|
||||||
|
{
|
||||||
|
part.Inventory.RemoveScriptInstance(item.ItemID, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
// Update item with new asset
|
// Update item with new asset
|
||||||
item.AssetID = asset.FullID;
|
item.AssetID = asset.FullID;
|
||||||
|
@ -262,25 +274,182 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
part.GetProperties(remoteClient);
|
part.GetProperties(remoteClient);
|
||||||
|
|
||||||
// Trigger rerunning of script (use TriggerRezScript event, see RezScript)
|
////REGION SYNC
|
||||||
|
//DSG SYNC: commenting out old REGION SYNC code, the RemoveScriptInstance would be handled by ScriptEngineSyncModule
|
||||||
|
/*
|
||||||
|
if (!RegionSyncEnabled)
|
||||||
|
{
|
||||||
|
//Original OpenSim code below
|
||||||
|
|
||||||
|
// Trigger rerunning of script (use TriggerRezScript event, see RezScript)
|
||||||
|
ArrayList errors = new ArrayList();
|
||||||
|
|
||||||
|
if (isScriptRunning)
|
||||||
|
{
|
||||||
|
// Needs to determine which engine was running it and use that
|
||||||
|
//
|
||||||
|
part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0);
|
||||||
|
errors = part.Inventory.GetScriptErrors(item.ItemID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remoteClient.SendAgentAlertMessage("Script saved", false);
|
||||||
|
}
|
||||||
|
part.ParentGroup.ResumeScripts();
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Distributed Scene Graph is in place, trigger event OnUpdateScript to
|
||||||
|
//let SceneToSEConnector to contact remote script engine for script update
|
||||||
|
m_log.Debug("Scene.Inventory: to call EventManager.TriggerUpdateTaskInventoryScriptAsset, agentID: " + remoteClient.AgentId);
|
||||||
|
EventManager.TriggerUpdateScript(remoteClient.AgentId, itemId, primId, isScriptRunning, item.AssetID);
|
||||||
|
|
||||||
|
//For now, we simple tell client that script saved while waiting for remote script engine to re-rez the script.
|
||||||
|
//Later will change the BaseHttpServer's code to return error list to client.
|
||||||
|
remoteClient.SendAgentAlertMessage("Script saved", false);
|
||||||
|
ArrayList errors = new ArrayList();
|
||||||
|
return errors;
|
||||||
|
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
|
//DSG SYNC: Distributed Scene Graph implementation
|
||||||
|
m_log.Debug("Scene.Inventory: to call EventManager.TriggerUpdateScript, agentID: " + remoteClient.AgentId);
|
||||||
|
//Trigger OnUpdateScript event.
|
||||||
|
EventManager.TriggerUpdateScript(remoteClient.AgentId, itemId, primId, isScriptRunning, item.AssetID);
|
||||||
|
|
||||||
|
//For now, we simple tell client that script saved while waiting for remote script engine to re-rez the script.
|
||||||
|
//Later will change the BaseHttpServer's code to return error list to client.
|
||||||
|
//remoteClient.SendAgentAlertMessage("Script saved", false);
|
||||||
ArrayList errors = new ArrayList();
|
ArrayList errors = new ArrayList();
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//REGION SYNC
|
||||||
|
//Scene does permission checking, asset creation and storing, then informs Script Engine to
|
||||||
|
//update the script.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//Only should be called when this is the local Scene of script engine
|
||||||
|
public ArrayList OnUpdateScript(UUID avatarID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
|
||||||
|
{
|
||||||
|
ArrayList errors = new ArrayList();
|
||||||
|
|
||||||
|
//In the old async model, this function is supposed to be executed only on a remote script engine, not an authorative Scene
|
||||||
|
/*
|
||||||
|
if (RegionSyncModule==null && !IsSyncedScriptEngine())
|
||||||
|
{
|
||||||
|
m_log.Warn("This is not the script engine. Should not have received OnUpdateScript event.");
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
SceneObjectPart part = GetSceneObjectPart(primID);
|
||||||
|
SceneObjectGroup group = part.ParentGroup;
|
||||||
|
if (isScriptRunning)
|
||||||
|
{
|
||||||
|
m_log.Debug("To RemoveScriptInstance");
|
||||||
|
part.Inventory.RemoveScriptInstance(itemID, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve item
|
||||||
|
TaskInventoryItem item = group.GetInventoryItem(part.LocalId, itemID);
|
||||||
|
|
||||||
|
// Update item with new asset
|
||||||
|
item.AssetID = newAssetID;
|
||||||
|
group.UpdateInventoryItemBySync(item);
|
||||||
|
m_log.Debug("UpdateInventoryItem on object "+group.UUID);
|
||||||
|
|
||||||
if (isScriptRunning)
|
if (isScriptRunning)
|
||||||
{
|
{
|
||||||
// Needs to determine which engine was running it and use that
|
// Needs to determine which engine was running it and use that
|
||||||
//
|
m_log.Debug("To CreateScriptInstance");
|
||||||
part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0);
|
part.Inventory.CreateScriptInstance(itemID, 0, false, DefaultScriptEngine, 0);
|
||||||
errors = part.Inventory.GetScriptErrors(item.ItemID);
|
errors = part.Inventory.GetScriptErrors(itemID);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
remoteClient.SendAgentAlertMessage("Script saved", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
part.ParentGroup.ResumeScripts();
|
part.ParentGroup.ResumeScripts();
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region DSG SYNC
|
||||||
|
public ArrayList SymSync_OnNewScript(UUID avatarID, UUID itemID, SceneObjectPart part)
|
||||||
|
{
|
||||||
|
TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID);
|
||||||
|
|
||||||
|
part.Inventory.CreateScriptInstance(item, 0, false, DefaultScriptEngine, 0);
|
||||||
|
part.ParentGroup.ResumeScripts();
|
||||||
|
|
||||||
|
ArrayList errors = part.Inventory.GetScriptErrors(itemID);
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
//only a script engine actor is supposed to call this function
|
||||||
|
public ArrayList SymSync_OnUpdateScript(UUID avatarID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
|
||||||
|
{
|
||||||
|
ArrayList errors = new ArrayList();
|
||||||
|
|
||||||
|
SceneObjectPart part = GetSceneObjectPart(primID);
|
||||||
|
SceneObjectGroup group = part.ParentGroup;
|
||||||
|
|
||||||
|
if (null == group)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[PRIM INVENTORY]: " +
|
||||||
|
"Prim inventory update requested for item ID {0} in prim ID {1} but this prim does not exist",
|
||||||
|
itemID, primID);
|
||||||
|
|
||||||
|
return new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isScriptRunning)
|
||||||
|
{
|
||||||
|
m_log.Debug("To RemoveScriptInstance");
|
||||||
|
part.Inventory.RemoveScriptInstance(itemID, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve item
|
||||||
|
TaskInventoryItem item = group.GetInventoryItem(part.LocalId, itemID);
|
||||||
|
|
||||||
|
if (null == item)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for caps script update "
|
||||||
|
+ " but the item does not exist in this inventory",
|
||||||
|
itemID, part.Name, part.UUID);
|
||||||
|
|
||||||
|
return new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update item with new asset.
|
||||||
|
// The actor that initiate the UpdateScript event should also send out
|
||||||
|
// a sync message for the updated task inventory. In case that sync message is
|
||||||
|
// not here year, we retrieve and update the task item -- w/o marking that
|
||||||
|
// the taskinventory is modified here, so that when the sync message is here,
|
||||||
|
// the actor and timestamp info will be copied.
|
||||||
|
item.AssetID = newAssetID;
|
||||||
|
group.UpdateInventoryItemBySync(item);
|
||||||
|
m_log.Debug("UpdateInventoryItem on object "+group.UUID);
|
||||||
|
|
||||||
|
if (isScriptRunning)
|
||||||
|
{
|
||||||
|
// Needs to determine which engine was running it and use that
|
||||||
|
m_log.Debug("To CreateScriptInstance");
|
||||||
|
part.Inventory.CreateScriptInstance(itemID, 0, false, DefaultScriptEngine, 0);
|
||||||
|
errors = part.Inventory.GetScriptErrors(itemID);
|
||||||
|
}
|
||||||
|
|
||||||
|
part.ParentGroup.ResumeScripts();
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
#endregion //DSG SYNC
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see>
|
/// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ArrayList CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,
|
public ArrayList CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,
|
||||||
|
@ -290,6 +459,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (TryGetScenePresence(avatarId, out avatar))
|
if (TryGetScenePresence(avatarId, out avatar))
|
||||||
{
|
{
|
||||||
|
//REGION SYNC LOG
|
||||||
|
m_log.Debug("Scene.Inventory: Avatar " + avatarId + ", triggers UpdateTaskInventoryScriptAsset");
|
||||||
return CapsUpdateTaskInventoryScriptAsset(
|
return CapsUpdateTaskInventoryScriptAsset(
|
||||||
avatar.ControllingClient, itemId, primId, isScriptRunning, data);
|
avatar.ControllingClient, itemId, primId, isScriptRunning, data);
|
||||||
}
|
}
|
||||||
|
@ -1561,6 +1732,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return;
|
return;
|
||||||
|
|
||||||
part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID);
|
part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID);
|
||||||
|
part.GetProperties(remoteClient);
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
/* Original OpenSim code, commented out
|
||||||
// TODO: switch to posting on_rez here when scripts
|
// TODO: switch to posting on_rez here when scripts
|
||||||
// have state in inventory
|
// have state in inventory
|
||||||
part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0);
|
part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0);
|
||||||
|
@ -1568,8 +1743,26 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// m_log.InfoFormat("[PRIMINVENTORY]: " +
|
// m_log.InfoFormat("[PRIMINVENTORY]: " +
|
||||||
// "Rezzed script {0} into prim local ID {1} for user {2}",
|
// "Rezzed script {0} into prim local ID {1} for user {2}",
|
||||||
// item.inventoryName, localID, remoteClient.Name);
|
// item.inventoryName, localID, remoteClient.Name);
|
||||||
part.GetProperties(remoteClient);
|
//part.GetProperties(remoteClient);
|
||||||
part.ParentGroup.ResumeScripts();
|
part.ParentGroup.ResumeScripts();
|
||||||
|
* */
|
||||||
|
if (RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
//part.SyncInfoUpdate();
|
||||||
|
EventManager.TriggerNewScript(remoteClient.AgentId, part, copyID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0);
|
||||||
|
|
||||||
|
// m_log.InfoFormat("[PRIMINVENTORY]: " +
|
||||||
|
// "Rezzed script {0} into prim local ID {1} for user {2}",
|
||||||
|
// item.inventoryName, localID, remoteClient.Name);
|
||||||
|
//part.GetProperties(remoteClient);
|
||||||
|
part.ParentGroup.ResumeScripts();
|
||||||
|
}
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1628,8 +1821,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
part.Inventory.AddInventoryItem(taskItem, false);
|
part.Inventory.AddInventoryItem(taskItem, false);
|
||||||
part.GetProperties(remoteClient);
|
part.GetProperties(remoteClient);
|
||||||
|
|
||||||
part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
|
//DSG SYNC
|
||||||
part.ParentGroup.ResumeScripts();
|
//part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
|
||||||
|
//part.ParentGroup.ResumeScripts();
|
||||||
|
if (RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
//part.SyncInfoUpdate();
|
||||||
|
EventManager.TriggerNewScript(remoteClient.AgentId, part, taskItem.ItemID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
|
||||||
|
|
||||||
|
// m_log.InfoFormat("[PRIMINVENTORY]: " +
|
||||||
|
// "Rezzed script {0} into prim local ID {1} for user {2}",
|
||||||
|
// item.inventoryName, localID, remoteClient.Name);
|
||||||
|
//part.GetProperties(remoteClient);
|
||||||
|
part.ParentGroup.ResumeScripts();
|
||||||
|
}
|
||||||
|
//end of DSG SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2047,14 +2257,36 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
|
sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddNewSceneObject(group, true, pos, rot, vel);
|
//AddNewSceneObject(group, true, pos, rot, vel);
|
||||||
|
//DSG SYNC
|
||||||
|
bool triggerSyncNewObject = false;
|
||||||
|
AddNewSceneObjectByRez(group, true, true, triggerSyncNewObject);
|
||||||
|
|
||||||
|
group.AbsolutePosition = pos;
|
||||||
|
group.Velocity = vel;
|
||||||
|
|
||||||
|
if (rot != null)
|
||||||
|
group.UpdateGroupRotationR((Quaternion)rot);
|
||||||
|
|
||||||
|
// TODO: This needs to be refactored with the similar code in
|
||||||
|
// SceneGraph.AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
|
||||||
|
// possibly by allowing this method to take a null rotation.
|
||||||
|
if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero)
|
||||||
|
group.RootPart.ApplyImpulse((vel * group.GetMass()), false);
|
||||||
|
|
||||||
// We can only call this after adding the scene object, since the scene object references the scene
|
// We can only call this after adding the scene object, since the scene object references the scene
|
||||||
// to find out if scripts should be activated at all.
|
// to find out if scripts should be activated at all.
|
||||||
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
|
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
|
||||||
|
|
||||||
group.ScheduleGroupForFullUpdate();
|
//group.ScheduleGroupForFullUpdate();
|
||||||
|
group.ScheduleGroupForFullUpdate(null); //new object, all properties have new value
|
||||||
|
|
||||||
|
//DSG SYNC: now all properties have been set, sending NewObject message,
|
||||||
|
if (RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
RegionSyncModule.SyncNewObject(group);
|
||||||
|
}
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2118,7 +2350,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
sog.SetOwnerId(ownerID);
|
sog.SetOwnerId(ownerID);
|
||||||
sog.SetGroup(groupID, remoteClient);
|
sog.SetGroup(groupID, remoteClient);
|
||||||
sog.ScheduleGroupForFullUpdate();
|
//sog.ScheduleGroupForFullUpdate();
|
||||||
|
sog.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.OwnerID, SceneObjectPartSyncProperties.GroupID});
|
||||||
|
|
||||||
SceneObjectPart[] partList = sog.Parts;
|
SceneObjectPart[] partList = sog.Parts;
|
||||||
|
|
||||||
|
@ -2182,6 +2415,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
List<SceneObjectPart> children = new List<SceneObjectPart>();
|
List<SceneObjectPart> children = new List<SceneObjectPart>();
|
||||||
SceneObjectPart root = GetSceneObjectPart(parentPrimId);
|
SceneObjectPart root = GetSceneObjectPart(parentPrimId);
|
||||||
|
|
||||||
|
//DSG DEBUG
|
||||||
|
m_log.Debug("Scene.LinkObjects -- ROOT: " + root.DebugObjectPartProperties());
|
||||||
|
|
||||||
if (root == null)
|
if (root == null)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[LINK]: Can't find linkset root prim {0}", parentPrimId);
|
m_log.DebugFormat("[LINK]: Can't find linkset root prim {0}", parentPrimId);
|
||||||
|
@ -2201,6 +2437,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (part == null)
|
if (part == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
//DSG DEBUG
|
||||||
|
m_log.Debug("Scene.LinkObjects -- child to link: " + part.DebugObjectPartProperties());
|
||||||
|
|
||||||
if (!owners.Contains(part.OwnerID))
|
if (!owners.Contains(part.OwnerID))
|
||||||
owners.Add(part.OwnerID);
|
owners.Add(part.OwnerID);
|
||||||
|
|
||||||
|
|
|
@ -208,11 +208,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// TODO: Make selection flagging per prim!
|
// TODO: Make selection flagging per prim!
|
||||||
//
|
//
|
||||||
part.ParentGroup.IsSelected = false;
|
part.ParentGroup.IsSelected = false;
|
||||||
|
|
||||||
if (part.ParentGroup.IsAttachment)
|
if (part.ParentGroup.IsAttachment)
|
||||||
isAttachment = true;
|
isAttachment = true;
|
||||||
else
|
else
|
||||||
part.ParentGroup.ScheduleGroupForFullUpdate();
|
//part.ParentGroup.ScheduleGroupForFullUpdate();
|
||||||
|
part.ParentGroup.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate});
|
||||||
|
|
||||||
// If it's not an attachment, and we are allowed to move it,
|
// If it's not an attachment, and we are allowed to move it,
|
||||||
// then we might have done so. If we moved across a parcel
|
// then we might have done so. If we moved across a parcel
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -469,6 +469,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// Shows various details about the sim based on the parameters supplied by the console command in openSimMain.
|
/// Shows various details about the sim based on the parameters supplied by the console command in openSimMain.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="showParams">What to show</param>
|
/// <param name="showParams">What to show</param>
|
||||||
|
///
|
||||||
|
/*
|
||||||
public virtual void Show(string[] showParams)
|
public virtual void Show(string[] showParams)
|
||||||
{
|
{
|
||||||
switch (showParams[0])
|
switch (showParams[0])
|
||||||
|
@ -484,7 +486,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call this from a region module to add a command to the OpenSim console.
|
/// Call this from a region module to add a command to the OpenSim console.
|
||||||
|
|
|
@ -47,6 +47,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public delegate void ObjectDeleteDelegate(EntityBase obj);
|
public delegate void ObjectDeleteDelegate(EntityBase obj);
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
public delegate void ObjectCreateBySyncDelegate(EntityBase obj);
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
|
/// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
|
||||||
/// should be migrated out over time.
|
/// should be migrated out over time.
|
||||||
|
@ -64,6 +69,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public event ObjectCreateDelegate OnObjectCreate;
|
public event ObjectCreateDelegate OnObjectCreate;
|
||||||
public event ObjectDeleteDelegate OnObjectRemove;
|
public event ObjectDeleteDelegate OnObjectRemove;
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
public event ObjectCreateBySyncDelegate OnObjectCreateBySync;
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
|
@ -279,7 +288,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
sceneObject.HasGroupChanged = true;
|
sceneObject.HasGroupChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
|
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -301,7 +310,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (attachToBackup)
|
if (attachToBackup)
|
||||||
sceneObject.HasGroupChanged = true;
|
sceneObject.HasGroupChanged = true;
|
||||||
|
|
||||||
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
|
//DSG SYNC: passing true to trigger SyncNewObject
|
||||||
|
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -337,7 +347,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
|
sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
|
||||||
sceneObject.Velocity = vel;
|
sceneObject.Velocity = vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
//Moving AddNewSceneObject to the end of this function, so that
|
||||||
|
//all object properties are set when AddNewSceneObject is called.
|
||||||
|
AddNewSceneObject(sceneObject, true, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,17 +375,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// true if the object was added, false if an object with the same uuid was already in the scene
|
/// true if the object was added, false if an object with the same uuid was already in the scene
|
||||||
/// </returns>
|
/// </returns>
|
||||||
protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
|
protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates, bool triggerSyncNewObject)
|
||||||
{
|
{
|
||||||
if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero)
|
if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Entities.ContainsKey(sceneObject.UUID))
|
if (Entities.ContainsKey(sceneObject.UUID))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
|
// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
|
||||||
// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
|
// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
|
||||||
|
|
||||||
SceneObjectPart[] children = sceneObject.Parts;
|
SceneObjectPart[] children = sceneObject.Parts;
|
||||||
|
|
||||||
|
@ -388,16 +403,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (scale.Z > m_parentScene.m_maxNonphys)
|
if (scale.Z > m_parentScene.m_maxNonphys)
|
||||||
scale.Z = m_parentScene.m_maxNonphys;
|
scale.Z = m_parentScene.m_maxNonphys;
|
||||||
|
|
||||||
part.Shape.Scale = scale;
|
//part.Shape.Scale = scale;
|
||||||
|
part.Scale = scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_numPrim += children.Length;
|
m_numPrim += children.Length;
|
||||||
|
|
||||||
sceneObject.AttachToScene(m_parentScene);
|
sceneObject.AttachToScene(m_parentScene);
|
||||||
|
|
||||||
if (sendClientUpdates)
|
|
||||||
sceneObject.ScheduleGroupForFullUpdate();
|
|
||||||
|
|
||||||
Entities.Add(sceneObject);
|
Entities.Add(sceneObject);
|
||||||
|
|
||||||
if (attachToBackup)
|
if (attachToBackup)
|
||||||
|
@ -408,7 +421,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
lock (SceneObjectGroupsByFullID)
|
lock (SceneObjectGroupsByFullID)
|
||||||
SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
|
SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
|
||||||
|
|
||||||
lock (SceneObjectGroupsByFullPartID)
|
lock (SceneObjectGroupsByFullPartID)
|
||||||
{
|
{
|
||||||
SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject;
|
SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject;
|
||||||
|
@ -423,6 +436,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
|
SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sendClientUpdates)
|
||||||
|
//sceneObject.ScheduleGroupForFullUpdate();
|
||||||
|
sceneObject.ScheduleGroupForFullUpdate(null);
|
||||||
|
|
||||||
|
//DSG SYNC: sending NewObject event,
|
||||||
|
if (m_parentScene.RegionSyncModule != null && triggerSyncNewObject)
|
||||||
|
{
|
||||||
|
m_parentScene.RegionSyncModule.SyncNewObject(sceneObject);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +506,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
protected internal void AddToUpdateList(SceneObjectGroup obj)
|
protected internal void AddToUpdateList(SceneObjectGroup obj)
|
||||||
{
|
{
|
||||||
lock (m_updateList)
|
lock (m_updateList)
|
||||||
|
{
|
||||||
m_updateList[obj.UUID] = obj;
|
m_updateList[obj.UUID] = obj;
|
||||||
|
//m_log.Debug("added " + obj.Name+","+ obj.UUID + " to m_updateList");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -502,6 +528,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
lock (m_updateList)
|
lock (m_updateList)
|
||||||
{
|
{
|
||||||
updates = new List<SceneObjectGroup>(m_updateList.Values);
|
updates = new List<SceneObjectGroup>(m_updateList.Values);
|
||||||
|
|
||||||
|
|
||||||
|
if (updates.Count > 0)
|
||||||
|
{
|
||||||
|
//m_log.Debug("SceneGraph.UpdateObjectGroups: " + updates.Count + " objects to send updates for");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
m_updateList.Clear();
|
m_updateList.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +700,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
|
Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
|
||||||
List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
|
List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
|
||||||
|
|
||||||
// Remove the presence reference from the dictionary
|
// Remove the presence reference from the dictionary
|
||||||
if (newmap.ContainsKey(agentID))
|
if (newmap.ContainsKey(agentID))
|
||||||
{
|
{
|
||||||
|
@ -923,7 +958,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fullID"></param>
|
/// <param name="fullID"></param>
|
||||||
/// <returns>null if no scene object group containing that prim is found</returns>
|
/// <returns>null if no scene object group containing that prim is found</returns>
|
||||||
private SceneObjectGroup GetGroupByPrim(UUID fullID)
|
public SceneObjectGroup GetGroupByPrim(UUID fullID)
|
||||||
{
|
{
|
||||||
SceneObjectGroup sog;
|
SceneObjectGroup sog;
|
||||||
lock (SceneObjectGroupsByFullPartID)
|
lock (SceneObjectGroupsByFullPartID)
|
||||||
|
@ -1653,8 +1688,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return; // parent is null so not in this region
|
return; // parent is null so not in this region
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach (SceneObjectGroup child in childGroups)
|
foreach (SceneObjectGroup child in childGroups)
|
||||||
{
|
{
|
||||||
|
m_log.Debug("linking child " + child.UUID + " to parentGroup " + parentGroup.UUID);
|
||||||
|
|
||||||
parentGroup.LinkToGroup(child);
|
parentGroup.LinkToGroup(child);
|
||||||
|
|
||||||
// this is here so physics gets updated!
|
// this is here so physics gets updated!
|
||||||
|
@ -1662,12 +1701,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
child.AbsolutePosition = child.AbsolutePosition;
|
child.AbsolutePosition = child.AbsolutePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to explicitly resend the newly link prim's object properties since no other actions
|
|
||||||
// occur on link to invoke this elsewhere (such as object selection)
|
|
||||||
parentGroup.RootPart.CreateSelected = true;
|
parentGroup.RootPart.CreateSelected = true;
|
||||||
parentGroup.TriggerScriptChangedEvent(Changed.LINK);
|
parentGroup.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
parentGroup.HasGroupChanged = true;
|
parentGroup.HasGroupChanged = true;
|
||||||
parentGroup.ScheduleGroupForFullUpdate();
|
|
||||||
|
//DSG SYNC
|
||||||
|
//Send out LinkObject sync messages.
|
||||||
|
if (m_parentScene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
//Tell other actors to link the SceneObjectParts together as a new group.
|
||||||
|
//m_parentScene.RegionSyncModule.SendLinkObject(parentGroup, root, children);
|
||||||
|
m_parentScene.RegionSyncModule.SyncLinkObject(parentGroup, root, children);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Schedule updates as in legacy OpenSim code, to send updates to viewers connected to this actor (at least needed for client managers).
|
||||||
|
//But timestamp won't be changed, so that when other actors get the update, they's simple ignore the updates since they already get them
|
||||||
|
//via the LinkObject message sent above.
|
||||||
|
parentGroup.ScheduleGroupForFullUpdate(null);
|
||||||
|
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -1688,6 +1740,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
List<SceneObjectPart> childParts = new List<SceneObjectPart>();
|
List<SceneObjectPart> childParts = new List<SceneObjectPart>();
|
||||||
List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
|
List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
|
||||||
List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
|
List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
|
||||||
|
|
||||||
|
//DSG SYNC, record the new object groups after the delink operation
|
||||||
|
List<SceneObjectGroup> beforeDelinkGroups = new List<SceneObjectGroup>();
|
||||||
|
List<SceneObjectGroup> afterDelinkGroups = new List<SceneObjectGroup>();
|
||||||
|
|
||||||
// Look them all up in one go, since that is comparatively expensive
|
// Look them all up in one go, since that is comparatively expensive
|
||||||
//
|
//
|
||||||
foreach (SceneObjectPart part in prims)
|
foreach (SceneObjectPart part in prims)
|
||||||
|
@ -1703,7 +1760,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
SceneObjectGroup group = part.ParentGroup;
|
SceneObjectGroup group = part.ParentGroup;
|
||||||
if (!affectedGroups.Contains(group))
|
if (!affectedGroups.Contains(group))
|
||||||
|
{
|
||||||
affectedGroups.Add(group);
|
affectedGroups.Add(group);
|
||||||
|
//DSG SYNC
|
||||||
|
beforeDelinkGroups.Add(group);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1717,7 +1778,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// These are not in affected groups and will not be
|
// These are not in affected groups and will not be
|
||||||
// handled further. Do the honors here.
|
// handled further. Do the honors here.
|
||||||
child.ParentGroup.HasGroupChanged = true;
|
child.ParentGroup.HasGroupChanged = true;
|
||||||
child.ParentGroup.ScheduleGroupForFullUpdate();
|
|
||||||
|
//DSG SYNC, delay ScheduleGroupForFullUpdate till the end of the delink operations.
|
||||||
|
//child.ParentGroup.ScheduleGroupForFullUpdate();
|
||||||
|
afterDelinkGroups.Add(child.ParentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (SceneObjectPart root in rootParts)
|
foreach (SceneObjectPart root in rootParts)
|
||||||
|
@ -1786,8 +1850,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
g.TriggerScriptChangedEvent(Changed.LINK);
|
g.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
g.HasGroupChanged = true; // Persist
|
g.HasGroupChanged = true; // Persist
|
||||||
g.ScheduleGroupForFullUpdate();
|
|
||||||
|
//DSG SYNC, delay ScheduleGroupForFullUpdate till the end of the delink operations.
|
||||||
|
//g.ScheduleGroupForFullUpdate();
|
||||||
|
afterDelinkGroups.Add(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
//Send out DelinkObject message to other actors to sychronize their object list
|
||||||
|
if (m_parentScene.RegionSyncModule != null)
|
||||||
|
{
|
||||||
|
m_parentScene.RegionSyncModule.SyncDeLinkObject(prims, beforeDelinkGroups, afterDelinkGroups);
|
||||||
|
}
|
||||||
|
//Schedule updates as in legacy OpenSim code, to send updates
|
||||||
|
//to viewers connected to this actor (at least needed for client managers).
|
||||||
|
foreach (SceneObjectGroup sog in afterDelinkGroups)
|
||||||
|
{
|
||||||
|
sog.ScheduleGroupForFullUpdate(null);
|
||||||
|
}
|
||||||
|
//end of DSG SYNC
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -1947,7 +2028,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
|
copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
|
||||||
copy.HasGroupChanged = true;
|
copy.HasGroupChanged = true;
|
||||||
copy.ScheduleGroupForFullUpdate();
|
//copy.ScheduleGroupForFullUpdate();
|
||||||
|
copy.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate}); //new object, all property values are new
|
||||||
copy.ResumeScripts();
|
copy.ResumeScripts();
|
||||||
|
|
||||||
// required for physics to update it's position
|
// required for physics to update it's position
|
||||||
|
@ -1985,6 +2067,514 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region DSG SYNC
|
||||||
|
|
||||||
|
/*
|
||||||
|
public Scene.ObjectUpdateResult UpdateObjectBySynchronization(SceneObjectGroup updatedSog)
|
||||||
|
{
|
||||||
|
UUID sogID = updatedSog.UUID;
|
||||||
|
Scene.ObjectUpdateResult updateResult = Scene.ObjectUpdateResult.Unchanged;
|
||||||
|
|
||||||
|
if (Entities.ContainsKey(sogID))
|
||||||
|
{
|
||||||
|
//update the object
|
||||||
|
EntityBase entity = Entities[sogID];
|
||||||
|
if (entity is SceneObjectGroup)
|
||||||
|
{
|
||||||
|
SceneObjectGroup localSog = (SceneObjectGroup)entity;
|
||||||
|
updateResult = localSog.UpdateObjectGroupBySync(updatedSog);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: Entity with {1} is not of type SceneObjectGroup: {2}",
|
||||||
|
"[SCENE GRAPH]", sogID, entity.GetType().ToString());
|
||||||
|
//return false;
|
||||||
|
updateResult = Scene.ObjectUpdateResult.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//An object no longer in Entity list, probably linked to other objects, or handed over to another quark.
|
||||||
|
m_log.WarnFormat("[SCENE GRAPH] UpdateObjectBySynchronization: received update for an object {0}, {1} no longer in local Entity list. Ignore update.", updatedSog.Name, updatedSog.UUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateResult;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//This is called when an object is added due to receiving a state synchronization message from Scene or an actor. Do similar things as the original AddSceneObject(),
|
||||||
|
//but call ScheduleGroupForFullUpdate_TimeStampUnchanged() instead, so as not to modify the timestamp or actorID, since the object was not created locally.
|
||||||
|
/*
|
||||||
|
public Scene.ObjectUpdateResult AddNewSceneObjectBySync(SceneObjectGroup sceneObject)
|
||||||
|
{
|
||||||
|
Scene.ObjectUpdateResult updateResult = Scene.ObjectUpdateResult.New;
|
||||||
|
|
||||||
|
if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero)
|
||||||
|
return Scene.ObjectUpdateResult.Error;
|
||||||
|
|
||||||
|
if (Entities.ContainsKey(sceneObject.UUID))
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[SCENE GRAPH] AddNewSceneObjectBySync: Already has object {0}, {1} in local Entity list.", sceneObject.Name, sceneObject.UUID);
|
||||||
|
return Scene.ObjectUpdateResult.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneObjectPart[] children = sceneObject.Parts;
|
||||||
|
|
||||||
|
// Clamp child prim sizes and add child prims to the m_numPrim count
|
||||||
|
if (m_parentScene.m_clampPrimSize)
|
||||||
|
{
|
||||||
|
foreach (SceneObjectPart part in children)
|
||||||
|
{
|
||||||
|
SceneObjectPartBase partBase = (SceneObjectPartBase)part;
|
||||||
|
Vector3 scale = partBase.Scale;
|
||||||
|
|
||||||
|
if (scale.X > m_parentScene.m_maxNonphys)
|
||||||
|
scale.X = m_parentScene.m_maxNonphys;
|
||||||
|
if (scale.Y > m_parentScene.m_maxNonphys)
|
||||||
|
scale.Y = m_parentScene.m_maxNonphys;
|
||||||
|
if (scale.Z > m_parentScene.m_maxNonphys)
|
||||||
|
scale.Z = m_parentScene.m_maxNonphys;
|
||||||
|
|
||||||
|
part.Scale = scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_numPrim += children.Length;
|
||||||
|
|
||||||
|
sceneObject.AttachToScene(m_parentScene);
|
||||||
|
|
||||||
|
//Take some special care of the case of this object being an attachment,
|
||||||
|
//since localID of attachedAvatar is different in different sync node's
|
||||||
|
//Scene copies.
|
||||||
|
sceneObject.RootPart.SetAttachmentPoint(sceneObject.RootPart.AttachmentPoint);
|
||||||
|
if (sceneObject.IsAttachment)
|
||||||
|
{
|
||||||
|
ScenePresence avatar = m_parentScene.GetScenePresence(sceneObject.RootPart.AttachedAvatar);
|
||||||
|
//It is possible that the avatar has not been fully
|
||||||
|
//created locally when attachment objects are sync'ed.
|
||||||
|
//So we need to check if the avatar already exists.
|
||||||
|
//If not, handling of NewAvatar will evetually trigger
|
||||||
|
//calling of SetParentLocalId.
|
||||||
|
if(avatar!=null)
|
||||||
|
sceneObject.RootPart.SetParentLocalId(avatar.LocalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneObject.HasGroupChanged = true;
|
||||||
|
//NewObject is sent via a specific sync message, not through updates;
|
||||||
|
//hence not passing any property list here
|
||||||
|
sceneObject.ScheduleGroupForFullUpdate(null);
|
||||||
|
|
||||||
|
Entities.Add(sceneObject);
|
||||||
|
|
||||||
|
//ScenePersistenceSyncModule will attach the object to backup when it catches the OnObjectCreate event.
|
||||||
|
//if (attachToBackup)
|
||||||
|
// sceneObject.AttachToBackup();
|
||||||
|
|
||||||
|
//if (OnObjectCreate != null)
|
||||||
|
// OnObjectCreate(sceneObject);
|
||||||
|
|
||||||
|
if (OnObjectCreateBySync != null)
|
||||||
|
OnObjectCreateBySync(sceneObject);
|
||||||
|
|
||||||
|
lock (SceneObjectGroupsByFullID)
|
||||||
|
SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
|
||||||
|
|
||||||
|
lock (SceneObjectGroupsByFullPartID)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject;
|
||||||
|
foreach (SceneObjectPart part in children)
|
||||||
|
SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (SceneObjectGroupsByLocalPartID)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject;
|
||||||
|
foreach (SceneObjectPart part in children)
|
||||||
|
SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateResult;
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
|
public void AddNewSceneObjectPart(SceneObjectPart newPart, SceneObjectGroup parentGroup)
|
||||||
|
{
|
||||||
|
SceneObjectPart[] children = parentGroup.Parts;
|
||||||
|
|
||||||
|
lock (SceneObjectGroupsByFullID)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByFullID[parentGroup.UUID] = parentGroup;
|
||||||
|
foreach (SceneObjectPart part in children)
|
||||||
|
SceneObjectGroupsByFullID[newPart.UUID] = parentGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (SceneObjectGroupsByLocalPartID)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByLocalPartID[parentGroup.LocalId] = parentGroup;
|
||||||
|
foreach (SceneObjectPart part in children)
|
||||||
|
SceneObjectGroupsByLocalPartID[newPart.LocalId] = parentGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LinkObjectsBySync(SceneObjectPart root, List<SceneObjectPart> children)
|
||||||
|
{
|
||||||
|
Monitor.Enter(m_updateLock);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SceneObjectGroup parentGroup = root.ParentGroup;
|
||||||
|
|
||||||
|
List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
|
||||||
|
if (parentGroup != null)
|
||||||
|
{
|
||||||
|
// We do this in reverse to get the link order of the prims correct
|
||||||
|
for (int i = children.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
SceneObjectGroup child = children[i].ParentGroup;
|
||||||
|
|
||||||
|
if (child != null)
|
||||||
|
{
|
||||||
|
// Make sure no child prim is set for sale
|
||||||
|
// So that, on delink, no prims are unwittingly
|
||||||
|
// left for sale and sold off
|
||||||
|
child.RootPart.ObjectSaleType = 0;
|
||||||
|
child.RootPart.SalePrice = 10;
|
||||||
|
childGroups.Add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return; // parent is null so not in this region
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectGroup child in childGroups)
|
||||||
|
{
|
||||||
|
parentGroup.LinkToGroupBySync(child);
|
||||||
|
|
||||||
|
// this is here so physics gets updated!
|
||||||
|
// Don't remove! Bad juju! Stay away! or fix physics!
|
||||||
|
child.AbsolutePosition = child.AbsolutePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// We need to explicitly resend the newly link prim's object properties since no other actions
|
||||||
|
// occur on link to invoke this elsewhere (such as object selection)
|
||||||
|
parentGroup.RootPart.CreateSelected = true;
|
||||||
|
parentGroup.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
|
parentGroup.HasGroupChanged = true;
|
||||||
|
//Do not change the timestamp and actorID values
|
||||||
|
parentGroup.ScheduleGroupForFullUpdate(null);
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Monitor.Exit(m_updateLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delink the prims as indicated in localPrimIDs, and regroup them as the object-groups indicated in incomingAfterDelinkGroups.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localPrims"></param>
|
||||||
|
/// <param name="beforeDelinkGroupIDs"></param>
|
||||||
|
/// <param name="incomingAfterDelinkGroups"></param>
|
||||||
|
public void DelinkObjectsBySync(List<UUID> delinkPrimIDs, List<UUID> beforeDelinkGroupIDs, List<SceneObjectGroup> incomingAfterDelinkGroups)
|
||||||
|
{
|
||||||
|
Dictionary<UUID, SceneObjectGroup> localBeforeDelinkGroups = new Dictionary<UUID, SceneObjectGroup>();
|
||||||
|
List<SceneObjectGroup> localAfterDelinkGroups = new List<SceneObjectGroup>();
|
||||||
|
Dictionary<UUID, SceneObjectPart> delinkPrims = new Dictionary<UUID, SceneObjectPart>();
|
||||||
|
bool beforeStateConsistent = true;
|
||||||
|
bool afterStateConsistent = true;
|
||||||
|
|
||||||
|
Monitor.Enter(m_updateLock);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//get the before-delink-groups, and all the prims to delink
|
||||||
|
foreach (UUID primID in delinkPrimIDs)
|
||||||
|
{
|
||||||
|
SceneObjectPart localPart = GetSceneObjectPart(primID);
|
||||||
|
if (!delinkPrims.ContainsKey(primID))
|
||||||
|
{
|
||||||
|
delinkPrims.Add(primID, localPart);
|
||||||
|
}
|
||||||
|
SceneObjectGroup localGroup = localPart.ParentGroup;
|
||||||
|
if (!localBeforeDelinkGroups.ContainsKey(localGroup.UUID))
|
||||||
|
{
|
||||||
|
localBeforeDelinkGroups.Add(localGroup.UUID, localGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Next, do some sanity check to see if the local copy agrees with remote copy on the before-link state.
|
||||||
|
//TODO:: Actions to be taken after detecting conflicts. For now, we just assume the chance that conflict will happen is almost 0.
|
||||||
|
|
||||||
|
//First, check if the groups match
|
||||||
|
if (beforeDelinkGroupIDs.Count != localBeforeDelinkGroups.Count)
|
||||||
|
{
|
||||||
|
//detected conflict on editing object groups
|
||||||
|
m_log.Warn("DelinkObjectsBySync: the # of groups in before-delink-groups is different from the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
|
||||||
|
beforeStateConsistent = false;
|
||||||
|
//TODO: further actions
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (UUID beforeGroupID in beforeDelinkGroupIDs)
|
||||||
|
{
|
||||||
|
if (!localBeforeDelinkGroups.ContainsKey(beforeGroupID))
|
||||||
|
{
|
||||||
|
m_log.Warn("DelinkObjectsBySync: the local state of before-delink-groups is different from the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
|
||||||
|
beforeStateConsistent = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO: further actions
|
||||||
|
}
|
||||||
|
|
||||||
|
if(beforeStateConsistent){
|
||||||
|
//Second, check if the prims match
|
||||||
|
List<SceneObjectPart> allPrimsInLocalGroups = new List<SceneObjectPart>();
|
||||||
|
foreach (KeyValuePair<UUID, SceneObjectGroup> pair in localBeforeDelinkGroups)
|
||||||
|
{
|
||||||
|
foreach (SceneObjectPart part in pair.Value.Parts)
|
||||||
|
{
|
||||||
|
allPrimsInLocalGroups.Add(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allPrimsInLocalGroups.Count != delinkPrims.Count)
|
||||||
|
{
|
||||||
|
m_log.Warn("DelinkObjectsBySync: the # of prims of before-delink-groups is different from the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
|
||||||
|
beforeStateConsistent = false;
|
||||||
|
//TODO: further action
|
||||||
|
}else{
|
||||||
|
foreach (SceneObjectPart part in allPrimsInLocalGroups)
|
||||||
|
{
|
||||||
|
if (!delinkPrims.ContainsKey(part.UUID))
|
||||||
|
{
|
||||||
|
m_log.Warn("DelinkObjectsBySync: some local prims in before-delink-groups not exist in the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
|
||||||
|
beforeStateConsistent = false;
|
||||||
|
break;
|
||||||
|
//TODO: further action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end of sanity checking
|
||||||
|
|
||||||
|
if(!beforeStateConsistent){
|
||||||
|
m_log.Warn("DelinkObjectsBySync: before-delink state not consistent in local copy and the incoming copy. Return without further operations.");
|
||||||
|
}else{
|
||||||
|
//Next, apply the delink operation locally.
|
||||||
|
localAfterDelinkGroups = DelinkObjectsBySync(new List<SceneObjectPart>(delinkPrims.Values));
|
||||||
|
|
||||||
|
//Check if local after-state agrees with that in the remote copy, and update the groups' properties
|
||||||
|
if (localAfterDelinkGroups.Count != incomingAfterDelinkGroups.Count)
|
||||||
|
{
|
||||||
|
m_log.Warn("DelinkObjectsBySync: local state after delink does not agree with the incoming delink message (# of groups are different). NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
|
||||||
|
afterStateConsistent = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<UUID, SceneObjectGroup> incomingAfterDelinkGroupsDictionary = new Dictionary<UUID,SceneObjectGroup>();
|
||||||
|
foreach (SceneObjectGroup incomingGroup in incomingAfterDelinkGroups){
|
||||||
|
incomingAfterDelinkGroupsDictionary.Add(incomingGroup.UUID, incomingGroup);
|
||||||
|
}
|
||||||
|
foreach (SceneObjectGroup localAfterGroup in localAfterDelinkGroups)
|
||||||
|
{
|
||||||
|
if (!incomingAfterDelinkGroupsDictionary.ContainsKey(localAfterGroup.UUID))
|
||||||
|
{
|
||||||
|
m_log.Warn("DelinkObjectsBySync: local state after delink does not agree with the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
|
||||||
|
afterStateConsistent = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//No longer calling update prim's properties here, caller will do that
|
||||||
|
//localAfterGroup.UpdateObjectGroupBySync(incomingAfterDelinkGroupsDictionary[localAfterGroup.UUID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectGroup sog in localAfterDelinkGroups)
|
||||||
|
{
|
||||||
|
sog.ScheduleGroupForFullUpdate(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Monitor.Exit(m_updateLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(beforeStateConsistent && afterStateConsistent){
|
||||||
|
m_log.Debug("DelinkObjectsBySync successful");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Similar to DelinkObjects(), but calling DelinkFromGroupBySync instead
|
||||||
|
private List<SceneObjectGroup> DelinkObjectsBySync(List<SceneObjectPart> prims)
|
||||||
|
{
|
||||||
|
//!!!Caller of this function should already lock on m_updateLock, so no locking here !!!
|
||||||
|
|
||||||
|
List<SceneObjectGroup> afterDelinkGroups = new List<SceneObjectGroup>();
|
||||||
|
|
||||||
|
List<SceneObjectPart> childParts = new List<SceneObjectPart>();
|
||||||
|
List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
|
||||||
|
List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
|
||||||
|
|
||||||
|
foreach (SceneObjectPart part in prims)
|
||||||
|
{
|
||||||
|
if (part != null)
|
||||||
|
{
|
||||||
|
if (part.ParentGroup.PrimCount != 1) // Skip single
|
||||||
|
{
|
||||||
|
if (part.LinkNum < 2) // Root
|
||||||
|
rootParts.Add(part);
|
||||||
|
else
|
||||||
|
childParts.Add(part);
|
||||||
|
|
||||||
|
SceneObjectGroup group = part.ParentGroup;
|
||||||
|
if (!affectedGroups.Contains(group))
|
||||||
|
{
|
||||||
|
affectedGroups.Add(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectPart child in childParts)
|
||||||
|
{
|
||||||
|
// Unlink all child parts from their groups, w/o triggering unwanted events or syncinfo updates
|
||||||
|
child.ParentGroup.DelinkFromGroupBySync(child, true);
|
||||||
|
|
||||||
|
// These are not in affected groups and will not be
|
||||||
|
// handled further. Do the honors here.
|
||||||
|
child.ParentGroup.HasGroupChanged = true;
|
||||||
|
|
||||||
|
//record the after-delink-groups
|
||||||
|
afterDelinkGroups.Add(child.ParentGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectPart root in rootParts)
|
||||||
|
{
|
||||||
|
// In most cases, this will run only one time, and the prim
|
||||||
|
// will be a solo prim
|
||||||
|
// However, editing linked parts and unlinking may be different
|
||||||
|
//
|
||||||
|
SceneObjectGroup group = root.ParentGroup;
|
||||||
|
|
||||||
|
List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
|
||||||
|
int numChildren = newSet.Count;
|
||||||
|
|
||||||
|
// If there are prims left in a link set, but the root is
|
||||||
|
// slated for unlink, we need to do this
|
||||||
|
//
|
||||||
|
if (numChildren != 1)
|
||||||
|
{
|
||||||
|
// Unlink the remaining set
|
||||||
|
//
|
||||||
|
bool sendEventsToRemainder = true;
|
||||||
|
if (numChildren > 1)
|
||||||
|
sendEventsToRemainder = false;
|
||||||
|
|
||||||
|
foreach (SceneObjectPart p in newSet)
|
||||||
|
{
|
||||||
|
if (p != group.RootPart)
|
||||||
|
group.DelinkFromGroupBySync(p, sendEventsToRemainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is more than one prim remaining, we
|
||||||
|
// need to re-link
|
||||||
|
//
|
||||||
|
if (numChildren > 2)
|
||||||
|
{
|
||||||
|
// Remove old root
|
||||||
|
//
|
||||||
|
if (newSet.Contains(root))
|
||||||
|
newSet.Remove(root);
|
||||||
|
|
||||||
|
// Preserve link ordering
|
||||||
|
//
|
||||||
|
newSet.Sort(delegate(SceneObjectPart a, SceneObjectPart b)
|
||||||
|
{
|
||||||
|
return a.LinkNum.CompareTo(b.LinkNum);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Determine new root
|
||||||
|
//
|
||||||
|
SceneObjectPart newRoot = newSet[0];
|
||||||
|
newSet.RemoveAt(0);
|
||||||
|
|
||||||
|
foreach (SceneObjectPart newChild in newSet)
|
||||||
|
newChild.UpdateFlag = 0;
|
||||||
|
|
||||||
|
LinkObjectsBySync(newRoot, newSet);
|
||||||
|
if (!affectedGroups.Contains(newRoot.ParentGroup))
|
||||||
|
affectedGroups.Add(newRoot.ParentGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectGroup g in affectedGroups)
|
||||||
|
{
|
||||||
|
g.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
|
g.HasGroupChanged = true; // Persist
|
||||||
|
|
||||||
|
afterDelinkGroups.Add(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
return afterDelinkGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal bool AddNewSceneObjectByDelink(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
|
||||||
|
{
|
||||||
|
// Ensure that we persist this new scene object if it's not an
|
||||||
|
// attachment
|
||||||
|
if (attachToBackup)
|
||||||
|
sceneObject.HasGroupChanged = true;
|
||||||
|
|
||||||
|
bool triggerSyncNewObject = false;
|
||||||
|
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates, triggerSyncNewObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal bool AddNewSceneObjectByRez(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates, bool triggerSyncNewObject)
|
||||||
|
{
|
||||||
|
// Ensure that we persist this new scene object if it's not an
|
||||||
|
// attachment
|
||||||
|
if (attachToBackup)
|
||||||
|
sceneObject.HasGroupChanged = true;
|
||||||
|
|
||||||
|
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates, triggerSyncNewObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal bool AddNewSceneObjectBySync(SceneObjectGroup sceneObject)
|
||||||
|
{
|
||||||
|
sceneObject.HasGroupChanged = true;
|
||||||
|
bool triggerSyncNewObject = false;
|
||||||
|
if (AddSceneObject(sceneObject, true, true, triggerSyncNewObject))
|
||||||
|
{
|
||||||
|
//Take some special care of the case of this object being an attachment,
|
||||||
|
//since localID of attachedAvatar is different in different sync node's
|
||||||
|
//Scene copies.
|
||||||
|
sceneObject.RootPart.SetAttachmentPoint(sceneObject.RootPart.AttachmentPoint);
|
||||||
|
if (sceneObject.IsAttachment)
|
||||||
|
{
|
||||||
|
ScenePresence avatar = m_parentScene.GetScenePresence(sceneObject.RootPart.AttachedAvatar);
|
||||||
|
//It is possible that the avatar has not been fully
|
||||||
|
//created locally when attachment objects are sync'ed.
|
||||||
|
//So we need to check if the avatar already exists.
|
||||||
|
//If not, handling of NewAvatar will evetually trigger
|
||||||
|
//calling of SetParentLocalId.
|
||||||
|
if (avatar != null)
|
||||||
|
sceneObject.RootPart.SetParentLocalId(avatar.LocalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneObject.HasGroupChanged = true;
|
||||||
|
sceneObject.ScheduleGroupForFullUpdate(null);
|
||||||
|
|
||||||
|
if (OnObjectCreateBySync != null)
|
||||||
|
OnObjectCreateBySync(sceneObject);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion //DSG SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,5 +389,42 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
for (int i = 0; i < parts.Length; i++)
|
for (int i = 0; i < parts.Length; i++)
|
||||||
parts[i].Inventory.ResumeScripts();
|
parts[i].Inventory.ResumeScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
public void SuspendScripts()
|
||||||
|
{
|
||||||
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
parts[i].Inventory.SuspendScripts();
|
||||||
|
}
|
||||||
|
#endregion REGION SYNC
|
||||||
|
|
||||||
|
#region DSG SYNC
|
||||||
|
/// <summary>
|
||||||
|
/// Update an existing inventory item.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The updated item. An item with the same id must already exist
|
||||||
|
/// in this prim's inventory</param>
|
||||||
|
/// <returns>false if the item did not exist, true if the update occurred succesfully</returns>
|
||||||
|
public bool UpdateInventoryItemBySync(TaskInventoryItem item)
|
||||||
|
{
|
||||||
|
SceneObjectPart part = GetChildPart(item.ParentPartID);
|
||||||
|
if (part != null)
|
||||||
|
{
|
||||||
|
part.Inventory.UpdateInventoryItemBySync(item);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[PRIM INVENTORY]: " +
|
||||||
|
"Couldn't find prim ID {0} to update item {1}, {2}",
|
||||||
|
item.ParentPartID, item.Name, item.ItemID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,7 +317,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
|
return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The absolute position of this scene object in the scene
|
/// The absolute position of this scene object in the scene
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -334,6 +334,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|| Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
|
|| Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
|
||||||
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
|
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
|
||||||
{
|
{
|
||||||
|
//DSG DEBUG
|
||||||
|
m_log.DebugFormat("Object {0},{1} at pos {2}, to call CrossPrimGroupIntoNewRegion.", Name, UUID, val);
|
||||||
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
|
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,6 +510,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
public SceneObjectGroup(SceneObjectPart part, bool newGroupBySync)
|
||||||
|
{
|
||||||
|
if (!newGroupBySync)
|
||||||
|
{
|
||||||
|
SetRootPart(part);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetRootPartBySync(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -975,7 +991,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
RootPart.RemFlag(PrimFlags.TemporaryOnRez);
|
RootPart.RemFlag(PrimFlags.TemporaryOnRez);
|
||||||
AttachToBackup();
|
AttachToBackup();
|
||||||
m_scene.EventManager.TriggerParcelPrimCountTainted();
|
m_scene.EventManager.TriggerParcelPrimCountTainted();
|
||||||
m_rootPart.ScheduleFullUpdate();
|
//m_rootPart.ScheduleFullUpdate();
|
||||||
|
//m_rootPart.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.GroupPosition, SceneObjectPartSyncProperties.AttachmentPoint,
|
||||||
|
m_rootPart.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition, SceneObjectPartSyncProperties.AttachmentPoint,
|
||||||
|
SceneObjectPartSyncProperties.AttachedAvatar, SceneObjectPartSyncProperties.Flags}); //Physics properties, such as Position, OffsetPosition, etc, should be tainted in ApplyPhysics()
|
||||||
m_rootPart.ClearUndoState();
|
m_rootPart.ClearUndoState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,13 +1021,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
|
//m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
|
||||||
//AttachToBackup();
|
//AttachToBackup();
|
||||||
//m_rootPart.ScheduleFullUpdate();
|
//m_rootPart.ScheduleFullUpdate();
|
||||||
|
|
||||||
|
//m_rootPart.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.GroupPosition, SceneObjectPartSyncProperties.AttachmentPoint,
|
||||||
|
m_rootPart.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition, SceneObjectPartSyncProperties.AttachmentPoint,
|
||||||
|
SceneObjectPartSyncProperties.AttachedAvatar, SceneObjectPartSyncProperties.Flags});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="part"></param>
|
/// <param name="part"></param>
|
||||||
private void SetPartAsNonRoot(SceneObjectPart part)
|
public void SetPartAsNonRoot(SceneObjectPart part)
|
||||||
{
|
{
|
||||||
part.ParentID = m_rootPart.LocalId;
|
part.ParentID = m_rootPart.LocalId;
|
||||||
part.ClearUndoState();
|
part.ClearUndoState();
|
||||||
|
@ -1174,6 +1197,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
SceneObjectPart part = parts[i];
|
SceneObjectPart part = parts[i];
|
||||||
|
|
||||||
|
//DSG SYNC: object remove should be handled through RegionSyncModule
|
||||||
|
/*
|
||||||
|
// REGION SYNC
|
||||||
|
if (Scene.IsSyncedServer())
|
||||||
|
{
|
||||||
|
Scene.RegionSyncServerModule.DeleteObject(part.RegionHandle, part.LocalId, part);
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
* */
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
Scene.ForEachScenePresence(delegate(ScenePresence avatar)
|
Scene.ForEachScenePresence(delegate(ScenePresence avatar)
|
||||||
{
|
{
|
||||||
if (avatar.ParentID == LocalId)
|
if (avatar.ParentID == LocalId)
|
||||||
|
@ -1241,7 +1275,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_scene.RemoveGroupTarget(this);
|
m_scene.RemoveGroupTarget(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduleGroupForFullUpdate();
|
//ScheduleGroupForFullUpdate();
|
||||||
|
ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){ SceneObjectPartSyncProperties.Flags, SceneObjectPartSyncProperties.LocalFlags,
|
||||||
|
SceneObjectPartSyncProperties.AggregateScriptEvents}); //do we also need to synchronize SOG properties such as m_scriptListens_atRotTarget? (does any acotr other than script engine care about it?)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetText(string text, Vector3 color, double alpha)
|
public void SetText(string text, Vector3 color, double alpha)
|
||||||
|
@ -1253,7 +1289,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Text = text;
|
Text = text;
|
||||||
|
|
||||||
HasGroupChanged = true;
|
HasGroupChanged = true;
|
||||||
m_rootPart.ScheduleFullUpdate();
|
//m_rootPart.ScheduleFullUpdate();
|
||||||
|
m_rootPart.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() {SceneObjectPartSyncProperties.Text, SceneObjectPartSyncProperties.Color});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1315,6 +1352,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
//if we are doing sync across different sync nodes, and are not told to persist the state, don't do anything (only persistence actor will do it)
|
||||||
|
if (m_scene.RegionSyncModule != null && !ToPersistObjectState)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
// Since this is the top of the section of call stack for backing up a particular scene object, don't let
|
// Since this is the top of the section of call stack for backing up a particular scene object, don't let
|
||||||
// any exception propogate upwards.
|
// any exception propogate upwards.
|
||||||
try
|
try
|
||||||
|
@ -1483,6 +1528,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
part.PhysActor.IsPhysical,
|
part.PhysActor.IsPhysical,
|
||||||
newPart.LocalId);
|
newPart.LocalId);
|
||||||
|
|
||||||
|
newPart.PhysActor.UUID = part.UUID;
|
||||||
newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
|
newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1493,7 +1539,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
dupe.HasGroupChanged = true;
|
dupe.HasGroupChanged = true;
|
||||||
dupe.AttachToBackup();
|
dupe.AttachToBackup();
|
||||||
|
|
||||||
ScheduleGroupForFullUpdate();
|
//ScheduleGroupForFullUpdate();
|
||||||
|
ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate});
|
||||||
}
|
}
|
||||||
|
|
||||||
return dupe;
|
return dupe;
|
||||||
|
@ -1746,7 +1793,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
ApplyNextOwnerPermissions();
|
ApplyNextOwnerPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
part.ScheduleFullUpdate();
|
//part.ScheduleFullUpdate();
|
||||||
|
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() {SceneObjectPartSyncProperties.OwnerID, SceneObjectPartSyncProperties.GroupID, SceneObjectPartSyncProperties.LastOwnerID});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1873,33 +1921,54 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Schedule a full update for this scene object
|
/// Schedule a full update for this scene object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ScheduleGroupForFullUpdate()
|
//public void ScheduleGroupForFullUpdate()
|
||||||
|
public void ScheduleGroupForFullUpdate(List<SceneObjectPartSyncProperties> updatedProperties)
|
||||||
{
|
{
|
||||||
// if (IsAttachment)
|
// if (IsAttachment)
|
||||||
// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
|
// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
|
||||||
|
|
||||||
checkAtTargets();
|
checkAtTargets();
|
||||||
RootPart.ScheduleFullUpdate();
|
//RootPart.ScheduleFullUpdate();
|
||||||
|
RootPart.ScheduleFullUpdate(updatedProperties);
|
||||||
|
|
||||||
|
//For group properties, we only need to send it once per SOG,
|
||||||
|
//hence remove them from the updatedProperties for other parts
|
||||||
|
List<SceneObjectPartSyncProperties> otherPartsUpdatedProperties = updatedProperties;
|
||||||
|
if (updatedProperties!=null)
|
||||||
|
{
|
||||||
|
HashSet<SceneObjectPartSyncProperties> hashedList = new HashSet<SceneObjectPartSyncProperties>(updatedProperties);
|
||||||
|
foreach (SceneObjectPartSyncProperties groupProperty in SceneObjectPart.GetGroupProperties())
|
||||||
|
{
|
||||||
|
if (updatedProperties.Contains(groupProperty))
|
||||||
|
{
|
||||||
|
hashedList.Remove(groupProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
otherPartsUpdatedProperties = new List<SceneObjectPartSyncProperties>(hashedList);
|
||||||
|
}
|
||||||
|
|
||||||
SceneObjectPart[] parts = m_parts.GetArray();
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
for (int i = 0; i < parts.Length; i++)
|
for (int i = 0; i < parts.Length; i++)
|
||||||
{
|
{
|
||||||
SceneObjectPart part = parts[i];
|
SceneObjectPart part = parts[i];
|
||||||
if (part != RootPart)
|
if (part != RootPart)
|
||||||
part.ScheduleFullUpdate();
|
//part.ScheduleFullUpdate();
|
||||||
|
part.ScheduleFullUpdate(otherPartsUpdatedProperties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Schedule a terse update for this scene object
|
/// Schedule a terse update for this scene object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ScheduleGroupForTerseUpdate()
|
//public void ScheduleGroupForTerseUpdate()
|
||||||
|
public void ScheduleGroupForTerseUpdate(List<SceneObjectPartSyncProperties> updatedProperties)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID);
|
// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID);
|
||||||
|
|
||||||
SceneObjectPart[] parts = m_parts.GetArray();
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
for (int i = 0; i < parts.Length; i++)
|
for (int i = 0; i < parts.Length; i++)
|
||||||
parts[i].ScheduleTerseUpdate();
|
//parts[i].ScheduleTerseUpdate();
|
||||||
|
parts[i].ScheduleTerseUpdate(updatedProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2057,9 +2126,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// objectGroup.RootPart.SendScheduledUpdates();
|
// objectGroup.RootPart.SendScheduledUpdates();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
//m_log.DebugFormat(
|
||||||
// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
|
// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
|
||||||
// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
|
// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
|
||||||
|
|
||||||
SceneObjectPart linkPart = objectGroup.m_rootPart;
|
SceneObjectPart linkPart = objectGroup.m_rootPart;
|
||||||
|
|
||||||
|
@ -2128,9 +2197,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
objectGroup.m_isDeleted = true;
|
objectGroup.m_isDeleted = true;
|
||||||
|
|
||||||
objectGroup.m_parts.Clear();
|
objectGroup.m_parts.Clear();
|
||||||
|
|
||||||
// Can't do this yet since backup still makes use of the root part without any synchronization
|
// Can't do this yet since backup still makes use of the root part without any synchronization
|
||||||
// objectGroup.m_rootPart = null;
|
// objectGroup.m_rootPart = null;
|
||||||
|
|
||||||
AttachToBackup();
|
AttachToBackup();
|
||||||
|
|
||||||
|
@ -2141,6 +2210,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
//HasGroupChanged = true;
|
//HasGroupChanged = true;
|
||||||
//ScheduleGroupForFullUpdate();
|
//ScheduleGroupForFullUpdate();
|
||||||
|
|
||||||
|
//DSG SYNC
|
||||||
|
//The DeleteObject message will be enqueued to be sent out by another thread, and the call will return quickly.
|
||||||
|
//if (m_scene.RegionSyncModule != null)
|
||||||
|
// m_scene.RegionSyncModule.SendDeleteObject(objectGroup, true);
|
||||||
|
//end of DSG SYNC
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2242,7 +2318,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
|
SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
|
||||||
|
|
||||||
m_scene.AddNewSceneObject(objectGroup, true);
|
//m_scene.AddNewSceneObject(objectGroup, true);
|
||||||
|
//DSG SYNC: calling AddNewSceneObjectByDelink, so that later on we know
|
||||||
|
//the "new" object is added by delink operation, no need to send sync
|
||||||
|
//message of NewObject
|
||||||
|
m_scene.AddNewSceneObjectByDelink(objectGroup, true, true);
|
||||||
|
|
||||||
if (sendEvents)
|
if (sendEvents)
|
||||||
linkPart.TriggerScriptChangedEvent(Changed.LINK);
|
linkPart.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
|
@ -2803,7 +2883,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
//we need to do a terse update even if the move wasn't allowed
|
//we need to do a terse update even if the move wasn't allowed
|
||||||
// so that the position is reset in the client (the object snaps back)
|
// so that the position is reset in the client (the object snaps back)
|
||||||
ScheduleGroupForTerseUpdate();
|
//ScheduleGroupForTerseUpdate();
|
||||||
|
//List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.GroupPosition };
|
||||||
|
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition };
|
||||||
|
if (IsAttachment)
|
||||||
|
{
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.AttachedPos);
|
||||||
|
}
|
||||||
|
ScheduleGroupForTerseUpdate(updatedProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2876,7 +2963,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
AbsolutePosition = newPos;
|
AbsolutePosition = newPos;
|
||||||
|
|
||||||
HasGroupChanged = true;
|
HasGroupChanged = true;
|
||||||
ScheduleGroupForTerseUpdate();
|
//ScheduleGroupForTerseUpdate();
|
||||||
|
//ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Position, SceneObjectPartSyncProperties.OffsetPosition});
|
||||||
|
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition, SceneObjectPartSyncProperties.OffsetPosition });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OffsetForNewRegion(Vector3 offset)
|
public void OffsetForNewRegion(Vector3 offset)
|
||||||
|
@ -2913,7 +3002,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
HasGroupChanged = true;
|
HasGroupChanged = true;
|
||||||
ScheduleGroupForTerseUpdate();
|
//ScheduleGroupForTerseUpdate();
|
||||||
|
//DSG SYNC
|
||||||
|
//Above actions only update m_rootPart's RotationOffset, and m_rootPart.UpdateRotation will taint RotationOffset as updated
|
||||||
|
if (actor != null)
|
||||||
|
{
|
||||||
|
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() {SceneObjectPartSyncProperties.RotationOffset, SceneObjectPartSyncProperties.Orientation });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.RotationOffset });
|
||||||
|
}
|
||||||
|
//end DSG SYNC
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2945,7 +3045,19 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
AbsolutePosition = pos;
|
AbsolutePosition = pos;
|
||||||
|
|
||||||
HasGroupChanged = true;
|
HasGroupChanged = true;
|
||||||
ScheduleGroupForTerseUpdate();
|
//DSG SYNC
|
||||||
|
if (actor != null)
|
||||||
|
{
|
||||||
|
//RotationOffset is only updated for m_rootPart, and m_rootPart.UpdateRotation should already taint RotationOffset as updated
|
||||||
|
//ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.Position, SceneObjectPartSyncProperties.Orientation });
|
||||||
|
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition, SceneObjectPartSyncProperties.Orientation });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.Position });
|
||||||
|
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition});
|
||||||
|
}
|
||||||
|
//ScheduleGroupForTerseUpdate();
|
||||||
|
|
||||||
RootPart.IgnoreUndoUpdate = false;
|
RootPart.IgnoreUndoUpdate = false;
|
||||||
}
|
}
|
||||||
|
@ -3047,7 +3159,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Quaternion newRot = primsRot * oldParentRot;
|
Quaternion newRot = primsRot * oldParentRot;
|
||||||
newRot *= Quaternion.Inverse(axRot);
|
newRot *= Quaternion.Inverse(axRot);
|
||||||
prim.RotationOffset = newRot;
|
prim.RotationOffset = newRot;
|
||||||
prim.ScheduleTerseUpdate();
|
prim.ScheduleTerseUpdate(new List<SceneObjectPartSyncProperties>(){ SceneObjectPartSyncProperties.RotationOffset, SceneObjectPartSyncProperties.OffsetPosition});
|
||||||
|
//prim.ScheduleTerseUpdate();
|
||||||
prim.IgnoreUndoUpdate = false;
|
prim.IgnoreUndoUpdate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3062,7 +3175,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
m_rootPart.ScheduleTerseUpdate();
|
m_rootPart.ScheduleTerseUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.RotationOffset});
|
||||||
|
//m_rootPart.ScheduleTerseUpdate();
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
|
// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
|
||||||
|
@ -3390,6 +3504,460 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
SetFromItemID(uuid);
|
SetFromItemID(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region DSG SYNC
|
||||||
|
|
||||||
|
private bool m_toPersistObjectState = false;
|
||||||
|
public bool ToPersistObjectState
|
||||||
|
{
|
||||||
|
get { return m_toPersistObjectState; }
|
||||||
|
set { m_toPersistObjectState = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//update the existing copy of the object with updated properties in 'updatedSog'
|
||||||
|
//NOTE: updates on script content are handled seperately (e.g. user edited the script and saved it) -- SESyncServerOnUpdateScript(), a handler of EventManager.OnUpdateScript
|
||||||
|
//public void UpdateObjectProperties(SceneObjectGroup updatedSog)
|
||||||
|
|
||||||
|
/*
|
||||||
|
/// <summary>
|
||||||
|
/// Update the existing copy of the object with updated properties in 'updatedSog'. For now we update
|
||||||
|
/// all properties. Later on this should be edited to allow only updating a bucket of properties.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="updatedSog"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Scene.ObjectUpdateResult UpdateObjectGroupBySync(SceneObjectGroup updatedSog)
|
||||||
|
{
|
||||||
|
//This GroupID check should be done by the actor who initiates the object update
|
||||||
|
//if (!this.GroupID.Equals(updatedSog.GroupID))
|
||||||
|
// return Scene.ObjectUpdateResult.Error;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//NOTE!!!
|
||||||
|
//We do not want to simply call SceneObjectGroup.Copy here to clone the object:
|
||||||
|
//the prims (SceneObjectParts) in updatedSog are different instances than those in the local copy,
|
||||||
|
//and we want to preserve the references to the prims in this local copy, especially for scripts
|
||||||
|
//of each prim, where the scripts have references to the local copy. If the local copy is replaced,
|
||||||
|
//the prims (parts) will be replaces and we need to update all the references that were pointing to
|
||||||
|
//the previous prims.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Scene.ObjectUpdateResult groupUpdateResult = Scene.ObjectUpdateResult.Unchanged;
|
||||||
|
Dictionary<UUID, SceneObjectPart> updatedParts = new Dictionary<UUID, SceneObjectPart>();
|
||||||
|
|
||||||
|
lock (m_parts.SyncRoot)
|
||||||
|
{
|
||||||
|
|
||||||
|
//foreach (KeyValuePair<UUID, SceneObjectPart> pair in updatedSog.Parts)
|
||||||
|
Dictionary<UUID, SceneObjectPart> remainedParts = new Dictionary<UUID, SceneObjectPart>();
|
||||||
|
Dictionary<UUID, SceneObjectPart> removedParts = new Dictionary<UUID, SceneObjectPart>();
|
||||||
|
Dictionary<UUID, SceneObjectPart> newParts = new Dictionary<UUID, SceneObjectPart>();
|
||||||
|
|
||||||
|
//Compare the parts in updatedSog and sort them into remained/removed/newParts groups
|
||||||
|
foreach (SceneObjectPart updatedPart in updatedSog.Parts)
|
||||||
|
{
|
||||||
|
UUID partUUID = updatedPart.UUID;
|
||||||
|
if (ContainsPart(partUUID))
|
||||||
|
{
|
||||||
|
SceneObjectPart localPart = GetChildPart(partUUID);
|
||||||
|
remainedParts.Add(partUUID, localPart);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//in case the part is in the SceneGraph already (e.g. LinkObject event)
|
||||||
|
SceneObjectPart localPart = m_scene.GetSceneObjectPart(partUUID);
|
||||||
|
if (localPart != null)
|
||||||
|
{
|
||||||
|
//newParts.Add(partUUID, localPart);
|
||||||
|
//we should simply add the part into the object, sync-protocol should send another messge to soft-delete the previous group the part was in
|
||||||
|
AddPart(localPart);
|
||||||
|
//SceneGraph.GetGroupByPrim will corrent the mapping of <part,group> once it is called.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//This shall not happen, but wired synchronization timing might lead here
|
||||||
|
newParts.Add(partUUID, updatedPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectPart localPart in this.Parts)
|
||||||
|
{
|
||||||
|
if (!remainedParts.ContainsKey(localPart.UUID))
|
||||||
|
removedParts.Add(localPart.UUID, localPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
//For new parts or removed parts, they should be empty except maybe in some wired timing conditions (TO BE VALIDATED)
|
||||||
|
//Add in new parts
|
||||||
|
foreach (SceneObjectPart newPart in newParts.Values)
|
||||||
|
{
|
||||||
|
//AddPart(newPart);
|
||||||
|
m_log.Warn("UpdateObjectGroupBySync: prim " + newPart.UUID + " a brand new part, not in any SceneObjectGroup yet:: not supposed to happen. Checking on sync message time!!!!!");
|
||||||
|
AddNewPart(newPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove parts that are no longer in the group -- !!!!! need to further test how to do correct book-keeping and synchornized with other actors !!!!!!!!
|
||||||
|
foreach (SceneObjectPart rmPart in removedParts.Values)
|
||||||
|
{
|
||||||
|
//m_log.Warn("UpdateObjectGroupBySync: prim " + rmPart.UUID + " no longer in SceneObjectGroup " + this.UUID + ":: not supposed to happen. Checking on sync message time!!!!!");
|
||||||
|
//If we send out DelinkObject message right after the delink operation at the initiating actor and before any updates of the objects involved
|
||||||
|
//have been sent out, this shall not happen. Let's worry about this later if it does appear occasionally.
|
||||||
|
|
||||||
|
DelinkFromGroupBySync(rmPart, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (newParts.Count > 0 || removedParts.Count > 0)
|
||||||
|
{
|
||||||
|
groupUpdateResult = Scene.ObjectUpdateResult.Updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
//now update properties of the parts
|
||||||
|
foreach (SceneObjectPart part in this.Parts)
|
||||||
|
{
|
||||||
|
Scene.ObjectUpdateResult partUpdateResult = Scene.ObjectUpdateResult.Unchanged;
|
||||||
|
SceneObjectPart updatedPart = updatedSog.GetChildPart(part.UUID);
|
||||||
|
partUpdateResult = part.UpdateAllProperties(updatedPart);
|
||||||
|
|
||||||
|
if (partUpdateResult != Scene.ObjectUpdateResult.Unchanged)
|
||||||
|
{
|
||||||
|
groupUpdateResult = partUpdateResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Just to make sure the parts each has the right localID of the rootpart
|
||||||
|
UpdateParentIDs();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Schedule updates to be sent out, if the local copy has just been updated
|
||||||
|
//(1) if we are debugging the actor with a viewer attaching to it,
|
||||||
|
//we need to schedule updates to be sent to the viewer.
|
||||||
|
//(2) or if we are a relaying node to relay updates, we need to forward the updates.
|
||||||
|
//NOTE: LastUpdateTimeStamp and LastUpdateActorID should be kept the same as in the received copy of the object.
|
||||||
|
if (groupUpdateResult == Scene.ObjectUpdateResult.Updated)
|
||||||
|
{
|
||||||
|
ScheduleGroupForFullUpdate_SyncInfoUnchanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
//debug the update result
|
||||||
|
if (groupUpdateResult == Scene.ObjectUpdateResult.Updated)
|
||||||
|
{
|
||||||
|
DebugObjectUpdateResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupUpdateResult;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public string DebugObjectUpdateResult()
|
||||||
|
{
|
||||||
|
//m_log.Debug("ObjectGroup " + UUID + " updated. Rootpart: " +m_rootPart.DebugObjectPartProperties());
|
||||||
|
string sogDebug = "ObjectGroup " + UUID + ".\n Rootpart: " + m_rootPart.DebugObjectPartProperties();
|
||||||
|
|
||||||
|
int partNum = 1;
|
||||||
|
foreach (SceneObjectPart part in Parts)
|
||||||
|
{
|
||||||
|
if (part.UUID != m_rootPart.UUID)
|
||||||
|
{
|
||||||
|
//m_log.Debug("part " + partNum + ", " + part.DebugObjectPartProperties());
|
||||||
|
sogDebug += "\n"+part.DebugObjectPartProperties();
|
||||||
|
partNum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sogDebug;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddNewPart(SceneObjectPart newPart)
|
||||||
|
{
|
||||||
|
//set the parent relationship
|
||||||
|
AddPart(newPart);
|
||||||
|
|
||||||
|
m_scene.AddNewSceneObjectPartBySync(newPart, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Similar actions with DelinkFromGroup, except that m_scene.AddNewSceneObjectBySync is called
|
||||||
|
public SceneObjectGroup DelinkFromGroupBySync(SceneObjectPart delinkPart, bool sendEvents)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[SCENE OBJECT GROUP]: Delinking part {0}, {1}, {4} from group with root part {2}, {3}",
|
||||||
|
delinkPart.Name, delinkPart.UUID, RootPart.Name, RootPart.UUID, delinkPart.LocalId);
|
||||||
|
|
||||||
|
SceneObjectPartBase linkPart = (SceneObjectPartBase)delinkPart;
|
||||||
|
linkPart.ClearUndoState();
|
||||||
|
|
||||||
|
Quaternion worldRot = linkPart.GetWorldRotation();
|
||||||
|
|
||||||
|
// Remove the part from this object
|
||||||
|
lock (m_parts.SyncRoot)
|
||||||
|
{
|
||||||
|
m_parts.Remove(linkPart.UUID);
|
||||||
|
|
||||||
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
|
|
||||||
|
if (parts.Length == 1 && RootPart != null)
|
||||||
|
{
|
||||||
|
// Single prim left
|
||||||
|
RootPart.LinkNum = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
SceneObjectPartBase part = (SceneObjectPartBase)parts[i];
|
||||||
|
if (part.LinkNum > linkPart.LinkNum)
|
||||||
|
{
|
||||||
|
part.LinkNum--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
linkPart.ParentID = 0; //ParentID is a value set only locally and ignored in synchronization, so no need to set its value
|
||||||
|
linkPart.LinkNum = 0;
|
||||||
|
|
||||||
|
if (linkPart.PhysActor != null)
|
||||||
|
{
|
||||||
|
m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to reset the child part's position
|
||||||
|
// ready for life as a separate object after being a part of another object
|
||||||
|
Quaternion parentRot = m_rootPart.RotationOffset;
|
||||||
|
|
||||||
|
Vector3 axPos = linkPart.OffsetPosition;
|
||||||
|
|
||||||
|
axPos *= parentRot;
|
||||||
|
linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z);
|
||||||
|
linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
|
||||||
|
linkPart.OffsetPosition = new Vector3(0, 0, 0);
|
||||||
|
linkPart.RotationOffset = worldRot;
|
||||||
|
|
||||||
|
//SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
|
||||||
|
bool newGroupBySync = true;
|
||||||
|
SceneObjectGroup objectGroup = new SceneObjectGroup(delinkPart, newGroupBySync);
|
||||||
|
|
||||||
|
m_scene.AddNewSceneObjectBySync(objectGroup);
|
||||||
|
|
||||||
|
if (sendEvents)
|
||||||
|
linkPart.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
|
|
||||||
|
linkPart.Rezzed = RootPart.Rezzed;
|
||||||
|
|
||||||
|
// When we delete a group, we currently have to force persist to the database if the object id has changed
|
||||||
|
// (since delete works by deleting all rows which have a given object id)
|
||||||
|
objectGroup.HasGroupChangedDueToDelink = true;
|
||||||
|
|
||||||
|
return objectGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set a part to act as the root part for this scene object, in which SetProperty("LinkNum",) is called instead of "LinkNum=".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="part"></param>
|
||||||
|
public void SetRootPartBySync(SceneObjectPart part)
|
||||||
|
{
|
||||||
|
if (part == null)
|
||||||
|
throw new ArgumentNullException("Cannot give SceneObjectGroup a null root SceneObjectPart");
|
||||||
|
|
||||||
|
part.SetParent(this);
|
||||||
|
m_rootPart = part;
|
||||||
|
if (!IsAttachment)
|
||||||
|
part.ParentID = 0;
|
||||||
|
// part.SetProperty("LinkNum", 0);
|
||||||
|
((SceneObjectPartBase)part).LinkNum = 0;
|
||||||
|
|
||||||
|
m_parts.Add(m_rootPart.UUID, m_rootPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScheduleGroupForFullUpdate_SyncInfoUnchanged()
|
||||||
|
{
|
||||||
|
//if (IsAttachment)
|
||||||
|
// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
|
||||||
|
|
||||||
|
checkAtTargets();
|
||||||
|
RootPart.ScheduleFullUpdate_SyncInfoUnchanged();
|
||||||
|
|
||||||
|
lock (m_parts)
|
||||||
|
{
|
||||||
|
foreach (SceneObjectPart part in this.Parts)
|
||||||
|
{
|
||||||
|
if (part != RootPart)
|
||||||
|
part.ScheduleFullUpdate_SyncInfoUnchanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Similar to LinkToGroup(), except that not calling RegionSyncModule.SendDeleteObject
|
||||||
|
public void LinkToGroupBySync(SceneObjectGroup objectGroup)
|
||||||
|
{
|
||||||
|
|
||||||
|
SceneObjectPartBase linkPart = (SceneObjectPartBase)objectGroup.m_rootPart;
|
||||||
|
|
||||||
|
Vector3 oldGroupPosition = linkPart.GroupPosition;
|
||||||
|
Quaternion oldRootRotation = linkPart.RotationOffset;
|
||||||
|
|
||||||
|
linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
|
||||||
|
linkPart.GroupPosition = AbsolutePosition;
|
||||||
|
Vector3 axPos = linkPart.OffsetPosition;
|
||||||
|
|
||||||
|
Quaternion parentRot = m_rootPart.RotationOffset;
|
||||||
|
axPos *= Quaternion.Inverse(parentRot);
|
||||||
|
|
||||||
|
linkPart.OffsetPosition = axPos;
|
||||||
|
Quaternion oldRot = linkPart.RotationOffset;
|
||||||
|
Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
|
||||||
|
linkPart.RotationOffset = newRot;
|
||||||
|
|
||||||
|
//ParentID is only valid locally, so remote value is ignored and no syncinfo will be modified
|
||||||
|
linkPart.ParentID = m_rootPart.LocalId;
|
||||||
|
if (m_rootPart.LinkNum == 0)
|
||||||
|
((SceneObjectPartBase)m_rootPart).LinkNum = 1;
|
||||||
|
//m_rootPart.SetProperty("LinkNum",1);
|
||||||
|
|
||||||
|
lock (m_parts.SyncRoot)
|
||||||
|
{
|
||||||
|
m_parts.Add(linkPart.UUID, (SceneObjectPart) linkPart);
|
||||||
|
|
||||||
|
// Insert in terms of link numbers, the new links
|
||||||
|
// before the current ones (with the exception of
|
||||||
|
// the root prim. Shuffle the old ones up
|
||||||
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
SceneObjectPartBase part = (SceneObjectPartBase)parts[i];
|
||||||
|
if (part.LinkNum != 1)
|
||||||
|
{
|
||||||
|
// Don't update root prim link number
|
||||||
|
part.LinkNum += objectGroup.PrimCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
linkPart.LinkNum = 2;
|
||||||
|
|
||||||
|
linkPart.SetParent(this);
|
||||||
|
linkPart.CreateSelected = true;
|
||||||
|
|
||||||
|
//if (linkPart.PhysActor != null)
|
||||||
|
//{
|
||||||
|
// m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
|
||||||
|
|
||||||
|
//linkPart.PhysActor = null;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//TODO: rest of parts
|
||||||
|
int linkNum = 3;
|
||||||
|
SceneObjectPart[] ogParts = objectGroup.Parts;
|
||||||
|
for (int i = 0; i < ogParts.Length; i++)
|
||||||
|
{
|
||||||
|
SceneObjectPart part = ogParts[i];
|
||||||
|
if (part.UUID != objectGroup.m_rootPart.UUID)
|
||||||
|
LinkNonRootPartBySync(part, oldGroupPosition, oldRootRotation, linkNum++);
|
||||||
|
part.ClearUndoState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_scene.UnlinkSceneObject(objectGroup, true);
|
||||||
|
objectGroup.m_isDeleted = true;
|
||||||
|
|
||||||
|
objectGroup.m_parts.Clear();
|
||||||
|
|
||||||
|
// Can't do this yet since backup still makes use of the root part without any synchronization
|
||||||
|
// objectGroup.m_rootPart = null;
|
||||||
|
|
||||||
|
AttachToBackup();
|
||||||
|
|
||||||
|
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
|
||||||
|
// position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
|
||||||
|
// unmoved prims!
|
||||||
|
ResetChildPrimPhysicsPositions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LinkNonRootPartBySync(SceneObjectPart linkPart, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum)
|
||||||
|
{
|
||||||
|
Quaternion parentRot = oldGroupRotation;
|
||||||
|
Quaternion oldRot = linkPart.RotationOffset;
|
||||||
|
Quaternion worldRot = parentRot * oldRot;
|
||||||
|
|
||||||
|
parentRot = oldGroupRotation;
|
||||||
|
|
||||||
|
Vector3 axPos = linkPart.OffsetPosition;
|
||||||
|
|
||||||
|
SceneObjectPartBase part = (SceneObjectPartBase)linkPart;
|
||||||
|
axPos *= parentRot;
|
||||||
|
part.OffsetPosition = axPos;
|
||||||
|
part.GroupPosition = oldGroupPosition + part.OffsetPosition;
|
||||||
|
part.OffsetPosition = Vector3.Zero;
|
||||||
|
part.RotationOffset = worldRot;
|
||||||
|
part.SetParent(this);
|
||||||
|
part.ParentID = m_rootPart.LocalId;
|
||||||
|
|
||||||
|
m_parts.Add(part.UUID, linkPart);
|
||||||
|
|
||||||
|
part.LinkNum = linkNum;
|
||||||
|
|
||||||
|
part.OffsetPosition = part.GroupPosition - AbsolutePosition;
|
||||||
|
|
||||||
|
Quaternion rootRotation = m_rootPart.RotationOffset;
|
||||||
|
|
||||||
|
Vector3 pos = part.OffsetPosition;
|
||||||
|
pos *= Quaternion.Inverse(rootRotation);
|
||||||
|
part.OffsetPosition = pos;
|
||||||
|
|
||||||
|
parentRot = m_rootPart.RotationOffset;
|
||||||
|
oldRot = part.RotationOffset;
|
||||||
|
Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
|
||||||
|
part.RotationOffset = newRot;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void UpdatePrimFlagsBySync(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVolumeDetect)
|
||||||
|
{
|
||||||
|
SceneObjectPart selectionPart = GetChildPart(localID);
|
||||||
|
|
||||||
|
if (IsTemporary)
|
||||||
|
{
|
||||||
|
DetachFromBackup();
|
||||||
|
// Remove from database and parcel prim count
|
||||||
|
//
|
||||||
|
m_scene.DeleteFromStorage(UUID);
|
||||||
|
m_scene.EventManager.TriggerParcelPrimCountTainted();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectionPart != null)
|
||||||
|
{
|
||||||
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
SceneObjectPart part = parts[i];
|
||||||
|
if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
|
||||||
|
part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
|
||||||
|
part.Scale.Z > m_scene.RegionInfo.PhysPrimMax)
|
||||||
|
{
|
||||||
|
UsePhysics = false; // Reset physics
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
parts[i].UpdatePrimFlagsBySync(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScriptSetVolumeDetectBySync(bool SetVD)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("ScriptSetVolumeDetectBySync called for SOG {0}", Name);
|
||||||
|
|
||||||
|
bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
|
||||||
|
bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
|
||||||
|
bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
|
||||||
|
UpdatePrimFlagsBySync(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, SetVD);
|
||||||
|
}
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// Per SOP property based sync
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
namespace OpenSim.Region.Framework.Scenes
|
namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
public class SceneObjectPartInventory : IEntityInventory
|
public class SceneObjectPartInventory : IEntityInventory
|
||||||
|
//public class SceneObjectPartInventoryBase : IEntityInventory
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// The part to which the inventory belongs.
|
/// The part to which the inventory belongs.
|
||||||
/// </value>
|
/// </value>
|
||||||
private SceneObjectPart m_part;
|
private SceneObjectPart m_part;
|
||||||
|
//private SceneObjectPartBase m_part;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Serial count for inventory file , used to tell if inventory has changed
|
/// Serial count for inventory file , used to tell if inventory has changed
|
||||||
|
@ -99,6 +101,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// A <see cref="SceneObjectPart"/>
|
/// A <see cref="SceneObjectPart"/>
|
||||||
/// </param>
|
/// </param>
|
||||||
public SceneObjectPartInventory(SceneObjectPart part)
|
public SceneObjectPartInventory(SceneObjectPart part)
|
||||||
|
//public SceneObjectPartInventoryBase(SceneObjectPartBase part)
|
||||||
{
|
{
|
||||||
m_part = part;
|
m_part = part;
|
||||||
}
|
}
|
||||||
|
@ -291,7 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
|
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
|
||||||
m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
|
m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
|
||||||
m_part.ParentGroup.AddActiveScriptCount(1);
|
m_part.ParentGroup.AddActiveScriptCount(1);
|
||||||
m_part.ScheduleFullUpdate();
|
m_part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Flags, SceneObjectPartSyncProperties.TaskInventory});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +322,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
|
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
|
||||||
m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
|
m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
|
||||||
m_part.ParentGroup.AddActiveScriptCount(1);
|
m_part.ParentGroup.AddActiveScriptCount(1);
|
||||||
m_part.ScheduleFullUpdate();
|
m_part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Flags, SceneObjectPartSyncProperties.TaskInventory});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,6 +544,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//m_inventorySerial += 2;
|
//m_inventorySerial += 2;
|
||||||
HasInventoryChanged = true;
|
HasInventoryChanged = true;
|
||||||
m_part.ParentGroup.HasGroupChanged = true;
|
m_part.ParentGroup.HasGroupChanged = true;
|
||||||
|
|
||||||
|
//DSG SYNC: add ScheduleFullUpdate to enable synchronization across actors
|
||||||
|
m_part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.TaskInventory, SceneObjectPartSyncProperties.InventorySerial});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -689,7 +695,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return UpdateInventoryItem(item, fireScriptEvents, true);
|
return UpdateInventoryItem(item, fireScriptEvents, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
|
//public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
|
||||||
|
public virtual bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
|
||||||
{
|
{
|
||||||
TaskInventoryItem it = GetInventoryItem(item.ItemID);
|
TaskInventoryItem it = GetInventoryItem(item.ItemID);
|
||||||
if (it != null)
|
if (it != null)
|
||||||
|
@ -720,6 +727,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
HasInventoryChanged = true;
|
HasInventoryChanged = true;
|
||||||
m_part.ParentGroup.HasGroupChanged = true;
|
m_part.ParentGroup.HasGroupChanged = true;
|
||||||
|
|
||||||
|
//DSG
|
||||||
|
m_part.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.TaskInventory});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -763,7 +773,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (!ContainsScripts())
|
if (!ContainsScripts())
|
||||||
m_part.RemFlag(PrimFlags.Scripted);
|
m_part.RemFlag(PrimFlags.Scripted);
|
||||||
|
|
||||||
m_part.ScheduleFullUpdate();
|
m_part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.TaskInventory});
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
|
@ -1146,5 +1156,130 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
public void SuspendScripts()
|
||||||
|
{
|
||||||
|
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
|
||||||
|
if (engines == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (m_items)
|
||||||
|
{
|
||||||
|
foreach (TaskInventoryItem item in m_items.Values)
|
||||||
|
{
|
||||||
|
if (item.InvType == (int)InventoryType.LSL)
|
||||||
|
{
|
||||||
|
foreach (IScriptModule engine in engines)
|
||||||
|
{
|
||||||
|
if (engine != null)
|
||||||
|
{
|
||||||
|
if (item.OwnerChanged)
|
||||||
|
engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
|
||||||
|
item.OwnerChanged = false;
|
||||||
|
engine.SuspendScript(item.ItemID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion REGION SYNC
|
||||||
|
|
||||||
|
#region DSG SYNC
|
||||||
|
/// <summary>
|
||||||
|
/// Update an existing inventory item.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The updated item. An item with the same id must already exist
|
||||||
|
/// in this prim's inventory.</param>
|
||||||
|
/// <returns>false if the item did not exist, true if the update occurred successfully</returns>
|
||||||
|
public bool UpdateInventoryItemBySync(TaskInventoryItem item)
|
||||||
|
{
|
||||||
|
return UpdateInventoryItemBySync(item, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Similar to UpdateInventoryItem except that ScheduleSyncUpdate is not triggered
|
||||||
|
private bool UpdateInventoryItemBySync(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
|
||||||
|
{
|
||||||
|
TaskInventoryItem it = GetInventoryItem(item.ItemID);
|
||||||
|
if (it != null)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
|
||||||
|
|
||||||
|
item.ParentID = m_part.UUID;
|
||||||
|
item.ParentPartID = m_part.UUID;
|
||||||
|
|
||||||
|
// If group permissions have been set on, check that the groupID is up to date in case it has
|
||||||
|
// changed since permissions were last set.
|
||||||
|
if (item.GroupPermissions != (uint)PermissionMask.None)
|
||||||
|
item.GroupID = m_part.GroupID;
|
||||||
|
|
||||||
|
if (item.AssetID == UUID.Zero)
|
||||||
|
item.AssetID = it.AssetID;
|
||||||
|
|
||||||
|
lock (m_items)
|
||||||
|
{
|
||||||
|
m_items[item.ItemID] = item;
|
||||||
|
m_inventorySerial++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fireScriptEvents)
|
||||||
|
m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
|
||||||
|
|
||||||
|
if (considerChanged)
|
||||||
|
{
|
||||||
|
HasInventoryChanged = true;
|
||||||
|
m_part.ParentGroup.HasGroupChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[PRIM INVENTORY]: " +
|
||||||
|
"Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
|
||||||
|
item.ItemID, m_part.Name, m_part.UUID,
|
||||||
|
m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion DSG SYNC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#region DSG SYNC
|
||||||
|
public class SceneObjectPartInventory : SceneObjectPartInventoryBase
|
||||||
|
{
|
||||||
|
private SceneObjectPart m_part;
|
||||||
|
public SceneObjectPartInventory(SceneObjectPart part):base((SceneObjectPartBase) part)
|
||||||
|
{
|
||||||
|
m_part = part;
|
||||||
|
}
|
||||||
|
|
||||||
|
new protected internal uint Serial
|
||||||
|
{
|
||||||
|
get { return base.Serial; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.Serial = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
|
||||||
|
{
|
||||||
|
if (base.UpdateInventoryItem(item, fireScriptEvents, considerChanged))
|
||||||
|
{
|
||||||
|
m_part.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.TaskInventory, SceneObjectPartSyncProperties.InventorySerial });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
* */
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
// ~ScenePresence()
|
// ~ScenePresence()
|
||||||
// {
|
// {
|
||||||
// m_log.Debug("[ScenePresence] Destructor called");
|
// m_log.Debug("[SCENE PRESENCE] Destructor called");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
@ -125,6 +125,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
private Vector3 m_lastPosition;
|
private Vector3 m_lastPosition;
|
||||||
private Quaternion m_lastRotation;
|
private Quaternion m_lastRotation;
|
||||||
private Vector3 m_lastVelocity;
|
private Vector3 m_lastVelocity;
|
||||||
|
// RA: following kludge lets us remember if we need to send a full update
|
||||||
|
// Used in RegionSyncServerModule
|
||||||
|
public uint lastSentParentID;
|
||||||
//private int m_lastTerseSent;
|
//private int m_lastTerseSent;
|
||||||
|
|
||||||
private bool m_updateflag;
|
private bool m_updateflag;
|
||||||
|
@ -390,6 +393,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
set { m_allowMovement = value; }
|
set { m_allowMovement = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Added for region sync module.
|
||||||
|
// Should not rely on a physics actor like so many of these params seem to
|
||||||
|
public bool Flying
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (PhysicsActor != null)
|
||||||
|
return PhysicsActor.Flying;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool SetAlwaysRun
|
public bool SetAlwaysRun
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -438,6 +453,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public IClientAPI ControllingClient
|
public IClientAPI ControllingClient
|
||||||
{
|
{
|
||||||
get { return m_controllingClient; }
|
get { return m_controllingClient; }
|
||||||
|
set { m_controllingClient = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IClientCore ClientView
|
public IClientCore ClientView
|
||||||
|
@ -505,7 +521,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
|
m_log.Error("[SCENE PRESENCE]: ABSOLUTE POSITION " + e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,10 +558,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
lock (m_scene.SyncRoot)
|
lock (m_scene.SyncRoot)
|
||||||
actor.Velocity = value;
|
actor.Velocity = value;
|
||||||
|
m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message);
|
m_log.Error("[SCENE PRESENCE]: VELOCITY " + e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,6 +610,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
set { m_health = value; }
|
set { m_health = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool m_isSyncedAvatar;
|
||||||
|
public bool IsSyncedAvatar
|
||||||
|
{
|
||||||
|
get { return m_isSyncedAvatar; }
|
||||||
|
set { m_isSyncedAvatar = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool m_isBalancing;
|
||||||
|
public bool IsBalancing
|
||||||
|
{
|
||||||
|
get { return m_isBalancing; }
|
||||||
|
set { m_isBalancing = value; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// These are the region handles known by the avatar.
|
/// These are the region handles known by the avatar.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -770,14 +802,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void RegisterToEvents()
|
public void RegisterToEvents()
|
||||||
{
|
{
|
||||||
|
// REGION SYNC
|
||||||
|
// if (m_scene.IsSyncedServer() || m_scene.RegionSyncEnabled == false)
|
||||||
|
if (m_scene.IsSyncedServer())
|
||||||
|
{
|
||||||
|
// These client messages will not be handled by client managers but instead
|
||||||
|
// they are caught by the RegionSyncClient module and passed up to the auth sim
|
||||||
|
m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
|
||||||
|
//m_controllingClient.OnSetAppearance += SetAppearance;
|
||||||
|
m_log.DebugFormat("[SCENE PRESENCE]: Setting local handler for HandleAgentRequestSit"); //RA
|
||||||
|
m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
|
||||||
|
m_controllingClient.OnAgentSit += HandleAgentSit;
|
||||||
|
m_controllingClient.OnStartAnim += HandleStartAnim;
|
||||||
|
m_controllingClient.OnStopAnim += HandleStopAnim;
|
||||||
|
}
|
||||||
|
|
||||||
m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
|
m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
|
||||||
//m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
|
//m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
|
||||||
m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
|
|
||||||
m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
|
|
||||||
m_controllingClient.OnAgentSit += HandleAgentSit;
|
|
||||||
m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
|
m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
|
||||||
m_controllingClient.OnStartAnim += HandleStartAnim;
|
|
||||||
m_controllingClient.OnStopAnim += HandleStopAnim;
|
|
||||||
m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
|
m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
|
||||||
m_controllingClient.OnAutoPilotGo += DoAutoPilot;
|
m_controllingClient.OnAutoPilotGo += DoAutoPilot;
|
||||||
m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
|
m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
|
||||||
|
@ -1003,7 +1046,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Animator.ResetAnimations();
|
Animator.ResetAnimations();
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
|
// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
|
||||||
// Name, UUID, m_scene.RegionInfo.RegionName);
|
// Name, UUID, m_scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
// Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
|
// Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
|
||||||
|
@ -1056,6 +1099,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
SendTerseUpdateToAllClients();
|
SendTerseUpdateToAllClients();
|
||||||
|
|
||||||
|
//This should only happen on PSA and when the teleport is within the same region.
|
||||||
|
//If teleport is to a remote region, CM will handle it and PSA should be
|
||||||
|
//executing inside this function.
|
||||||
|
SendTeleportUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TeleportWithMomentum(Vector3 pos)
|
public void TeleportWithMomentum(Vector3 pos)
|
||||||
|
@ -1183,14 +1231,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_callbackURI = null;
|
m_callbackURI = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//m_log.DebugFormat("Completed movement");
|
m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
|
||||||
|
|
||||||
m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
|
m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
|
||||||
SendInitialData();
|
SendInitialData();
|
||||||
|
|
||||||
// Create child agents in neighbouring regions
|
// Create child agents in neighbouring regions
|
||||||
if (!m_isChildAgent)
|
//if (!m_isChildAgent && !m_scene.IsAuthoritativeScene())
|
||||||
|
|
||||||
|
if (!m_isChildAgent && !IsSyncedAvatar)
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat("[SCENE PRESENCE]: Requesting neighbouring children. cagent={0}",
|
||||||
|
m_isChildAgent.ToString());
|
||||||
IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
|
IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
|
||||||
if (m_agentTransfer != null)
|
if (m_agentTransfer != null)
|
||||||
m_agentTransfer.EnableChildAgents(this);
|
m_agentTransfer.EnableChildAgents(this);
|
||||||
|
@ -1249,6 +1301,39 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move the avatar to a specific position, velocity and rotation and mark it as changed
|
||||||
|
// Mostly copied from HandleAgentUpdate
|
||||||
|
public void MoveTo(Vector3 pos, Vector3 vel, Quaternion rot)
|
||||||
|
{
|
||||||
|
++m_movementUpdateCount;
|
||||||
|
if (m_movementUpdateCount < 1)
|
||||||
|
m_movementUpdateCount = 1;
|
||||||
|
#region Sanity Checking
|
||||||
|
|
||||||
|
// This is irritating. Really.
|
||||||
|
if (!AbsolutePosition.IsFinite())
|
||||||
|
{
|
||||||
|
RemoveFromPhysicalScene();
|
||||||
|
m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
|
||||||
|
|
||||||
|
m_pos = m_LastFinitePos;
|
||||||
|
if (!m_pos.IsFinite())
|
||||||
|
{
|
||||||
|
m_pos.X = 127f;
|
||||||
|
m_pos.Y = 127f;
|
||||||
|
m_pos.Z = 127f;
|
||||||
|
m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
|
||||||
|
}
|
||||||
|
|
||||||
|
AddToPhysicalScene(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_LastFinitePos = m_pos;
|
||||||
|
}
|
||||||
|
#endregion Sanity Checking
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is the event handler for client movement. If a client is moving, this event is triggering.
|
/// This is the event handler for client movement. If a client is moving, this event is triggering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1569,7 +1654,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//Avoid system crash, can be slower but...
|
//Avoid system crash, can be slower but...
|
||||||
m_log.DebugFormat("Crash! {0}", e.ToString());
|
m_log.DebugFormat("[SCENE PRESENCE] Crash! {0}", e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1605,7 +1690,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
|
// m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
|
// "[SCENE PRESENCE] In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
|
||||||
|
|
||||||
AddNewMovement(agent_control_v3, q);
|
AddNewMovement(agent_control_v3, q);
|
||||||
|
|
||||||
|
@ -1674,7 +1759,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
//Why did I get this error?
|
//Why did I get this error?
|
||||||
m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex);
|
m_log.Error("[SCENE PRESENCE]: DoMoveToPosition" + ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2266,13 +2351,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// Rotate the avatar to the given rotation and apply a movement in the given relative vector
|
/// Rotate the avatar to the given rotation and apply a movement in the given relative vector
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
|
/// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
|
||||||
/// <param name="rotation">The direction in which this avatar should now face.
|
/// <param name="rotation">The direction in which this avatar should now face.</param>
|
||||||
public void AddNewMovement(Vector3 vec, Quaternion rotation)
|
public void AddNewMovement(Vector3 vec, Quaternion rotation)
|
||||||
{
|
{
|
||||||
if (m_isChildAgent)
|
if (m_isChildAgent)
|
||||||
{
|
{
|
||||||
// WHAT???
|
// WHAT???
|
||||||
m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!");
|
m_log.Debug("[SCENE PRESENCE]: AddNewMovement() called on child agent, making root agent!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2388,7 +2473,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Vector3 pos = m_pos;
|
Vector3 pos = m_pos;
|
||||||
pos.Z += m_appearance.HipOffset;
|
pos.Z += m_appearance.HipOffset;
|
||||||
|
|
||||||
//m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
|
//m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
|
||||||
|
|
||||||
remoteClient.SendPrimUpdate(
|
remoteClient.SendPrimUpdate(
|
||||||
this,
|
this,
|
||||||
|
@ -2411,6 +2496,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendTerseUpdateToAllClients()
|
public void SendTerseUpdateToAllClients()
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[SCENE PRESENCE]: TerseUpdate: UUID={0}, pos={1}", m_physicsActor.UUID.ToString(), m_physicsActor.Position.ToString());
|
||||||
|
// REGION SYNC
|
||||||
|
if (m_scene.IsSyncedServer())
|
||||||
|
{
|
||||||
|
m_scene.RegionSyncServerModule.QueuePresenceForTerseUpdate(this);
|
||||||
|
// this.PhysicsRequestingTerseUpdate();
|
||||||
|
// m_scene.RegionSyncModule.QueueSceneObjectPartForUpdate(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int currentTick = Util.EnvironmentTickCount();
|
int currentTick = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
// Decrease update frequency when avatar is moving but velocity is
|
// Decrease update frequency when avatar is moving but velocity is
|
||||||
|
@ -2475,6 +2570,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SendInitialData()
|
private void SendInitialData()
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID);
|
||||||
// Moved this into CompleteMovement to ensure that m_appearance is initialized before
|
// Moved this into CompleteMovement to ensure that m_appearance is initialized before
|
||||||
// the inventory arrives
|
// the inventory arrives
|
||||||
// m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
|
// m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
|
||||||
|
@ -2489,7 +2585,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[SCENEPRESENCE]: AvatarFactory not set for {0}", Name);
|
m_log.WarnFormat("[SCENE PRESENCE]: AvatarFactory not set for {0}", Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we aren't using a cached appearance, then clear out the baked textures
|
// If we aren't using a cached appearance, then clear out the baked textures
|
||||||
|
@ -2515,7 +2611,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// If the avatars baked textures are all in the cache, then we have a
|
// If the avatars baked textures are all in the cache, then we have a
|
||||||
// complete appearance... send it out, if not, then we'll send it when
|
// complete appearance... send it out, if not, then we'll send it when
|
||||||
// the avatar finishes updating its appearance
|
// the avatar finishes updating its appearance
|
||||||
SendAppearanceToAllOtherAgents();
|
m_scene.AvatarFactory.QueueAppearanceSend(UUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2525,10 +2621,19 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendAvatarDataToAllAgents()
|
public void SendAvatarDataToAllAgents()
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID);
|
||||||
|
// REGION SYNC
|
||||||
|
// The server sends appearance to all client managers since there are no local clients
|
||||||
|
if (m_scene.IsSyncedServer())
|
||||||
|
{
|
||||||
|
m_scene.RegionSyncServerModule.SendAppearance(UUID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// only send update from root agents to other clients; children are only "listening posts"
|
// only send update from root agents to other clients; children are only "listening posts"
|
||||||
if (IsChildAgent)
|
if (IsChildAgent)
|
||||||
{
|
{
|
||||||
m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent");
|
m_log.Warn("[SCENE PRESENCE] attempt to send avatar data from a child agent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2551,6 +2656,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendOtherAgentsAvatarDataToMe()
|
public void SendOtherAgentsAvatarDataToMe()
|
||||||
{
|
{
|
||||||
|
// REGION SYNC
|
||||||
|
// The server should not be doing anything via the ForEachScenePresence method
|
||||||
|
if (m_scene.IsSyncedServer())
|
||||||
|
return;
|
||||||
m_perfMonMS = Util.EnvironmentTickCount();
|
m_perfMonMS = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -2578,7 +2687,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="avatar"></param>
|
/// <param name="avatar"></param>
|
||||||
public void SendAvatarDataToAgent(ScenePresence avatar)
|
public void SendAvatarDataToAgent(ScenePresence avatar)
|
||||||
{
|
{
|
||||||
// m_log.WarnFormat("[SP] Send avatar data from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId);
|
m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
|
||||||
|
|
||||||
avatar.ControllingClient.SendAvatarDataImmediate(this);
|
avatar.ControllingClient.SendAvatarDataImmediate(this);
|
||||||
if (Animator != null)
|
if (Animator != null)
|
||||||
|
@ -2591,10 +2700,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendAppearanceToAllOtherAgents()
|
public void SendAppearanceToAllOtherAgents()
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} ({1})", Name, UUID);
|
||||||
|
// REGION SYNC
|
||||||
|
// The server should not be doing anything via the ForEachScenePresence method
|
||||||
|
if (m_scene.IsSyncedServer())
|
||||||
|
{
|
||||||
|
m_scene.RegionSyncServerModule.SendAppearance(UUID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// only send update from root agents to other clients; children are only "listening posts"
|
// only send update from root agents to other clients; children are only "listening posts"
|
||||||
if (IsChildAgent)
|
if (IsChildAgent)
|
||||||
{
|
{
|
||||||
m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent");
|
m_log.Warn("[SCENE PRESENCE] attempt to send avatar data from a child agent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2620,6 +2737,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendOtherAgentsAppearanceToMe()
|
public void SendOtherAgentsAppearanceToMe()
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} ({1})", Name, UUID);
|
||||||
m_perfMonMS = Util.EnvironmentTickCount();
|
m_perfMonMS = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -2636,7 +2754,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
scenePresence.SendAppearanceToAgent(this);
|
scenePresence.SendAppearanceToAgent(this);
|
||||||
count++;
|
count++;
|
||||||
});
|
});
|
||||||
|
|
||||||
m_scene.StatsReporter.AddAgentUpdates(count);
|
m_scene.StatsReporter.AddAgentUpdates(count);
|
||||||
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
||||||
}
|
}
|
||||||
|
@ -2647,7 +2764,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="avatar"></param>
|
/// <param name="avatar"></param>
|
||||||
public void SendAppearanceToAgent(ScenePresence avatar)
|
public void SendAppearanceToAgent(ScenePresence avatar)
|
||||||
{
|
{
|
||||||
// m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId);
|
m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
|
||||||
|
|
||||||
avatar.ControllingClient.SendAppearance(
|
avatar.ControllingClient.SendAppearance(
|
||||||
m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
|
m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
|
||||||
|
@ -2731,7 +2848,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Also removes the avatar from the physical scene if transit has started.
|
/// Also removes the avatar from the physical scene if transit has started.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected void CheckForBorderCrossing()
|
public void CheckForBorderCrossing()
|
||||||
{
|
{
|
||||||
if (IsChildAgent)
|
if (IsChildAgent)
|
||||||
return;
|
return;
|
||||||
|
@ -3297,13 +3414,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
|
new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
|
||||||
|
|
||||||
scene.AddPhysicsActorTaint(m_physicsActor);
|
scene.AddPhysicsActorTaint(m_physicsActor);
|
||||||
//m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
|
m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
|
||||||
m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
|
m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
|
||||||
m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
|
m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
|
||||||
m_physicsActor.SubscribeEvents(500);
|
m_physicsActor.SubscribeEvents(500);
|
||||||
m_physicsActor.LocalID = LocalId;
|
m_physicsActor.LocalID = LocalId;
|
||||||
|
m_physicsActor.UUID = this.UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OutOfBoundsCall(Vector3 pos)
|
private void OutOfBoundsCall(Vector3 pos)
|
||||||
{
|
{
|
||||||
//bool flying = m_physicsActor.Flying;
|
//bool flying = m_physicsActor.Flying;
|
||||||
|
@ -3784,7 +3902,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID);
|
m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_log.DebugFormat("[ATTACHMENT]: Rezzing attachments for scene presence {0} ({1})", Name, UUID);
|
||||||
List<AvatarAttachment> attachments = m_appearance.GetAttachments();
|
List<AvatarAttachment> attachments = m_appearance.GetAttachments();
|
||||||
foreach (AvatarAttachment attach in attachments)
|
foreach (AvatarAttachment attach in attachments)
|
||||||
{
|
{
|
||||||
|
@ -3861,5 +3979,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region REGION SYNC
|
||||||
|
public void SendTeleportUpdate()
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[SCENE PRESENCE]: TerseUpdate: UUID={0}, pos={1}", m_physicsActor.UUID.ToString(), m_physicsActor.Position.ToString());
|
||||||
|
// REGION SYNC
|
||||||
|
if (m_scene.IsSyncedServer())
|
||||||
|
{
|
||||||
|
m_scene.RegionSyncServerModule.SendTeleportUpdate(this);
|
||||||
|
// this.PhysicsRequestingTerseUpdate();
|
||||||
|
// m_scene.RegionSyncModule.QueueSceneObjectPartForUpdate(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion //REGION SYNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,11 +57,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// Add the part to the queue of parts for which we need to send an update to the client
|
/// Add the part to the queue of parts for which we need to send an update to the client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="part"></param>
|
/// <param name="part"></param>
|
||||||
public void QueuePartForUpdate(SceneObjectPart part)
|
//public void QueuePartForUpdate(SceneObjectPart part)
|
||||||
|
public void QueuePartForUpdate(SceneObjectPartBase part)
|
||||||
{
|
{
|
||||||
lock (m_partsUpdateQueue)
|
lock (m_partsUpdateQueue)
|
||||||
{
|
{
|
||||||
m_partsUpdateQueue.Enqueue(part);
|
m_partsUpdateQueue.Enqueue((SceneObjectPart)part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -428,7 +428,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
#region SOPXmlProcessors
|
#region SOPXmlProcessors
|
||||||
private static void ProcessAllowedDrop(SceneObjectPart obj, XmlTextReader reader)
|
private static void ProcessAllowedDrop(SceneObjectPart obj, XmlTextReader reader)
|
||||||
{
|
{
|
||||||
obj.AllowedDrop = Util.ReadBoolean(reader);
|
obj.AllowedDrop = Util.ReadBoolean(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ProcessCreatorID(SceneObjectPart obj, XmlTextReader reader)
|
private static void ProcessCreatorID(SceneObjectPart obj, XmlTextReader reader)
|
||||||
|
@ -494,26 +494,31 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
private static void ProcessGroupPosition(SceneObjectPart obj, XmlTextReader reader)
|
private static void ProcessGroupPosition(SceneObjectPart obj, XmlTextReader reader)
|
||||||
{
|
{
|
||||||
obj.GroupPosition = Util.ReadVector(reader, "GroupPosition");
|
obj.GroupPosition = Util.ReadVector(reader, "GroupPosition");
|
||||||
|
//obj.SetGroupPosition(Util.ReadVector(reader, "GroupPosition"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ProcessOffsetPosition(SceneObjectPart obj, XmlTextReader reader)
|
private static void ProcessOffsetPosition(SceneObjectPart obj, XmlTextReader reader)
|
||||||
{
|
{
|
||||||
obj.OffsetPosition = Util.ReadVector(reader, "OffsetPosition"); ;
|
obj.OffsetPosition = Util.ReadVector(reader, "OffsetPosition"); ;
|
||||||
|
//obj.SetOffsetPosition(Util.ReadVector(reader, "OffsetPosition"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ProcessRotationOffset(SceneObjectPart obj, XmlTextReader reader)
|
private static void ProcessRotationOffset(SceneObjectPart obj, XmlTextReader reader)
|
||||||
{
|
{
|
||||||
obj.RotationOffset = Util.ReadQuaternion(reader, "RotationOffset");
|
obj.RotationOffset = Util.ReadQuaternion(reader, "RotationOffset");
|
||||||
|
//obj.SetRotationOffset(Util.ReadQuaternion(reader, "RotationOffset"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ProcessVelocity(SceneObjectPart obj, XmlTextReader reader)
|
private static void ProcessVelocity(SceneObjectPart obj, XmlTextReader reader)
|
||||||
{
|
{
|
||||||
obj.Velocity = Util.ReadVector(reader, "Velocity");
|
obj.Velocity = Util.ReadVector(reader, "Velocity");
|
||||||
|
//obj.SetVelocity(Util.ReadVector(reader, "Velocity"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ProcessAngularVelocity(SceneObjectPart obj, XmlTextReader reader)
|
private static void ProcessAngularVelocity(SceneObjectPart obj, XmlTextReader reader)
|
||||||
{
|
{
|
||||||
obj.AngularVelocity = Util.ReadVector(reader, "AngularVelocity");
|
obj.AngularVelocity = Util.ReadVector(reader, "AngularVelocity");
|
||||||
|
//obj.SetVelocity(Util.ReadVector(reader, "AngularVelocity"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ProcessAcceleration(SceneObjectPart obj, XmlTextReader reader)
|
private static void ProcessAcceleration(SceneObjectPart obj, XmlTextReader reader)
|
||||||
|
@ -1109,7 +1114,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
|
|
||||||
////////// Write /////////
|
////////// Write /////////
|
||||||
|
|
||||||
public static void SOGToXml2(XmlTextWriter writer, SceneObjectGroup sog, Dictionary<string, object>options)
|
public static void SOGToXml2(XmlTextWriter writer, SceneObjectGroup sog, Dictionary<string, object> options)
|
||||||
{
|
{
|
||||||
writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
|
writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
|
||||||
SOPToXml2(writer, sog.RootPart, options);
|
SOPToXml2(writer, sog.RootPart, options);
|
||||||
|
@ -1267,7 +1272,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
writer.WriteElementString(name, flagsStr.Replace(",", ""));
|
writer.WriteElementString(name, flagsStr.Replace(",", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteTaskInventory(XmlTextWriter writer, TaskInventoryDictionary tinv, Dictionary<string, object> options, Scene scene)
|
//DSG SYNC: make it a public function, so that we can call serialization of TaskInventory from other places
|
||||||
|
//static void WriteTaskInventory(XmlTextWriter writer, TaskInventoryDictionary tinv, Dictionary<string, object> options, Scene scene)
|
||||||
|
public static void WriteTaskInventory(XmlTextWriter writer, TaskInventoryDictionary tinv, Dictionary<string, object> options, Scene scene)
|
||||||
{
|
{
|
||||||
if (tinv.Count > 0) // otherwise skip this
|
if (tinv.Count > 0) // otherwise skip this
|
||||||
{
|
{
|
||||||
|
@ -1321,7 +1328,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteShape(XmlTextWriter writer, PrimitiveBaseShape shp, Dictionary<string, object> options)
|
//DSG SYNC: make it a public function, so that we can call serialization of Shape from other places
|
||||||
|
//static void WriteShape(XmlTextWriter writer, PrimitiveBaseShape shp, Dictionary<string, object> options)
|
||||||
|
public static void WriteShape(XmlTextWriter writer, PrimitiveBaseShape shp, Dictionary<string, object> options)
|
||||||
{
|
{
|
||||||
if (shp != null)
|
if (shp != null)
|
||||||
{
|
{
|
||||||
|
@ -1365,6 +1374,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
writer.WriteElementString("ProfileBegin", shp.ProfileBegin.ToString());
|
writer.WriteElementString("ProfileBegin", shp.ProfileBegin.ToString());
|
||||||
writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
|
writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
|
||||||
writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
|
writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
|
||||||
|
//DSG SYNC: added serialization of Scale
|
||||||
|
WriteVector(writer, "Scale", shp.Scale);
|
||||||
|
//end of DSG SYNC
|
||||||
writer.WriteElementString("State", shp.State.ToString());
|
writer.WriteElementString("State", shp.State.ToString());
|
||||||
|
|
||||||
WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
|
WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
|
||||||
|
@ -1496,7 +1508,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name)
|
//DSG SYNC: make it public to be called outside
|
||||||
|
//static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name)
|
||||||
|
public static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name)
|
||||||
{
|
{
|
||||||
TaskInventoryDictionary tinv = new TaskInventoryDictionary();
|
TaskInventoryDictionary tinv = new TaskInventoryDictionary();
|
||||||
|
|
||||||
|
@ -1542,7 +1556,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
/// <param name="name">The name of the xml element containing the shape</param>
|
/// <param name="name">The name of the xml element containing the shape</param>
|
||||||
/// <param name="errors">true if any errors were encountered during parsing, false otherwise</param>
|
/// <param name="errors">true if any errors were encountered during parsing, false otherwise</param>
|
||||||
/// <returns>The shape parsed</returns>
|
/// <returns>The shape parsed</returns>
|
||||||
static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors)
|
//DSG SYNC: make it public to be called outside
|
||||||
|
//static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors)
|
||||||
|
public static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors)
|
||||||
{
|
{
|
||||||
errors = false;
|
errors = false;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace OpenSim.Region.Framework.Scenes.Types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Enqueue(SceneObjectPart part)
|
public void Enqueue(SceneObjectPart part)
|
||||||
{
|
{
|
||||||
lock (m_syncObject)
|
lock (m_syncObject)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,8 @@ using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Scenes
|
namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
public class UndoState
|
public class UndoState
|
||||||
|
@ -154,7 +156,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
part.Resize(Scale);
|
part.Resize(Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
part.ParentGroup.ScheduleGroupForTerseUpdate();
|
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>();
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.RotationOffset);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.OffsetPosition);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.Scale);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.AbsolutePosition);
|
||||||
|
part.ParentGroup.ScheduleGroupForTerseUpdate(updatedProperties);
|
||||||
|
//part.ParentGroup.ScheduleGroupForTerseUpdate();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -182,7 +190,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
part.Resize(Scale);
|
part.Resize(Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
part.ScheduleTerseUpdate();
|
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>();
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.RotationOffset);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.OffsetPosition);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.Scale);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.AbsolutePosition);
|
||||||
|
part.ScheduleTerseUpdate(updatedProperties);
|
||||||
|
//part.ScheduleTerseUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
part.Undoing = false;
|
part.Undoing = false;
|
||||||
|
@ -208,7 +222,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
part.Resize(Scale);
|
part.Resize(Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
part.ParentGroup.ScheduleGroupForTerseUpdate();
|
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>();
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.RotationOffset);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.OffsetPosition);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.Scale);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.AbsolutePosition);
|
||||||
|
part.ParentGroup.ScheduleGroupForTerseUpdate(updatedProperties);
|
||||||
|
//part.ParentGroup.ScheduleGroupForTerseUpdate();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -221,7 +241,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (Scale != Vector3.Zero)
|
if (Scale != Vector3.Zero)
|
||||||
part.Resize(Scale);
|
part.Resize(Scale);
|
||||||
|
|
||||||
part.ScheduleTerseUpdate();
|
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>();
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.RotationOffset);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.OffsetPosition);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.Scale);
|
||||||
|
updatedProperties.Add(SceneObjectPartSyncProperties.AbsolutePosition);
|
||||||
|
part.ScheduleTerseUpdate(updatedProperties);
|
||||||
|
//part.ScheduleTerseUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
part.Undoing = false;
|
part.Undoing = false;
|
||||||
|
@ -249,4 +275,4 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_terrainModule.UndoTerrain(m_terrainChannel);
|
m_terrainModule.UndoTerrain(m_terrainChannel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -636,6 +636,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
|
||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint MaxCoarseLocations
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
public uint CircuitCode
|
public uint CircuitCode
|
||||||
{
|
{
|
||||||
get { return (uint)Util.RandomClass.Next(0,int.MaxValue); }
|
get { return (uint)Util.RandomClass.Next(0,int.MaxValue); }
|
||||||
|
@ -650,6 +655,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
|
||||||
public event GenericMessage OnGenericMessage;
|
public event GenericMessage OnGenericMessage;
|
||||||
public event ImprovedInstantMessage OnInstantMessage;
|
public event ImprovedInstantMessage OnInstantMessage;
|
||||||
public event ChatMessage OnChatFromClient;
|
public event ChatMessage OnChatFromClient;
|
||||||
|
public event ChatMessageRaw OnChatFromClientRaw;
|
||||||
public event TextureRequest OnRequestTexture;
|
public event TextureRequest OnRequestTexture;
|
||||||
public event RezObject OnRezObject;
|
public event RezObject OnRezObject;
|
||||||
public event ModifyTerrain OnModifyTerrain;
|
public event ModifyTerrain OnModifyTerrain;
|
||||||
|
@ -670,6 +676,9 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
|
||||||
public event RequestMapBlocks OnRequestMapBlocks;
|
public event RequestMapBlocks OnRequestMapBlocks;
|
||||||
public event RequestMapName OnMapNameRequest;
|
public event RequestMapName OnMapNameRequest;
|
||||||
public event TeleportLocationRequest OnTeleportLocationRequest;
|
public event TeleportLocationRequest OnTeleportLocationRequest;
|
||||||
|
//DSG:
|
||||||
|
public event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
|
||||||
|
//end of DSG
|
||||||
public event DisconnectUser OnDisconnectUser;
|
public event DisconnectUser OnDisconnectUser;
|
||||||
public event RequestAvatarProperties OnRequestAvatarProperties;
|
public event RequestAvatarProperties OnRequestAvatarProperties;
|
||||||
public event SetAlwaysRun OnSetAlwaysRun;
|
public event SetAlwaysRun OnSetAlwaysRun;
|
||||||
|
@ -680,6 +689,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
|
||||||
public event GenericCall1 OnCompleteMovementToRegion;
|
public event GenericCall1 OnCompleteMovementToRegion;
|
||||||
public event UpdateAgent OnPreAgentUpdate;
|
public event UpdateAgent OnPreAgentUpdate;
|
||||||
public event UpdateAgent OnAgentUpdate;
|
public event UpdateAgent OnAgentUpdate;
|
||||||
|
public event UpdateAgentRaw OnAgentUpdateRaw;
|
||||||
public event AgentRequestSit OnAgentRequestSit;
|
public event AgentRequestSit OnAgentRequestSit;
|
||||||
public event AgentSit OnAgentSit;
|
public event AgentSit OnAgentSit;
|
||||||
public event AvatarPickerRequest OnAvatarPickerRequest;
|
public event AvatarPickerRequest OnAvatarPickerRequest;
|
||||||
|
|
|
@ -23,104 +23,104 @@
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
||||||
{
|
{
|
||||||
/// <summary>AutoBackupModuleState: Auto-Backup state for one region (scene).
|
/// <summary>AutoBackupModuleState: Auto-Backup state for one region (scene).
|
||||||
/// If you use this class in any way outside of AutoBackupModule, you should treat the class as opaque.
|
/// If you use this class in any way outside of AutoBackupModule, you should treat the class as opaque.
|
||||||
/// Since it is not part of the framework, you really should not rely upon it outside of the AutoBackupModule implementation.
|
/// Since it is not part of the framework, you really should not rely upon it outside of the AutoBackupModule implementation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
///
|
///
|
||||||
public class AutoBackupModuleState
|
public class AutoBackupModuleState
|
||||||
{
|
{
|
||||||
private Dictionary<Guid, string> m_liveRequests = null;
|
private Dictionary<Guid, string> m_liveRequests = null;
|
||||||
|
|
||||||
public AutoBackupModuleState()
|
public AutoBackupModuleState()
|
||||||
{
|
{
|
||||||
this.Enabled = false;
|
this.Enabled = false;
|
||||||
this.BackupDir = ".";
|
this.BackupDir = ".";
|
||||||
this.BusyCheck = true;
|
this.BusyCheck = true;
|
||||||
this.Timer = null;
|
this.Timer = null;
|
||||||
this.NamingType = NamingType.Time;
|
this.NamingType = NamingType.Time;
|
||||||
this.Script = null;
|
this.Script = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<Guid, string> LiveRequests
|
public Dictionary<Guid, string> LiveRequests
|
||||||
{
|
{
|
||||||
get {
|
get {
|
||||||
return this.m_liveRequests ??
|
return this.m_liveRequests ??
|
||||||
(this.m_liveRequests = new Dictionary<Guid, string>(1));
|
(this.m_liveRequests = new Dictionary<Guid, string>(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Enabled
|
public bool Enabled
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public System.Timers.Timer Timer
|
public System.Timers.Timer Timer
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double IntervalMinutes
|
public double IntervalMinutes
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (this.Timer == null)
|
if (this.Timer == null)
|
||||||
{
|
{
|
||||||
return -1.0;
|
return -1.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return this.Timer.Interval / 60000.0;
|
return this.Timer.Interval / 60000.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool BusyCheck
|
public bool BusyCheck
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Script
|
public string Script
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BackupDir
|
public string BackupDir
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NamingType NamingType
|
public NamingType NamingType
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public new string ToString()
|
public new string ToString()
|
||||||
{
|
{
|
||||||
string retval = "";
|
string retval = "";
|
||||||
|
|
||||||
retval += "[AUTO BACKUP]: AutoBackup: " + (Enabled ? "ENABLED" : "DISABLED") + "\n";
|
retval += "[AUTO BACKUP]: AutoBackup: " + (Enabled ? "ENABLED" : "DISABLED") + "\n";
|
||||||
retval += "[AUTO BACKUP]: Interval: " + IntervalMinutes + " minutes" + "\n";
|
retval += "[AUTO BACKUP]: Interval: " + IntervalMinutes + " minutes" + "\n";
|
||||||
retval += "[AUTO BACKUP]: Do Busy Check: " + (BusyCheck ? "Yes" : "No") + "\n";
|
retval += "[AUTO BACKUP]: Do Busy Check: " + (BusyCheck ? "Yes" : "No") + "\n";
|
||||||
retval += "[AUTO BACKUP]: Naming Type: " + NamingType.ToString() + "\n";
|
retval += "[AUTO BACKUP]: Naming Type: " + NamingType.ToString() + "\n";
|
||||||
retval += "[AUTO BACKUP]: Backup Dir: " + BackupDir + "\n";
|
retval += "[AUTO BACKUP]: Backup Dir: " + BackupDir + "\n";
|
||||||
retval += "[AUTO BACKUP]: Script: " + Script + "\n";
|
retval += "[AUTO BACKUP]: Script: " + Script + "\n";
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint MaxCoarseLocations { get { return 0; } }
|
||||||
|
|
||||||
#region Internal Functions
|
#region Internal Functions
|
||||||
|
|
||||||
private void SendOnChatFromClient(string message, ChatTypeEnum chatType)
|
private void SendOnChatFromClient(string message, ChatTypeEnum chatType)
|
||||||
|
@ -163,6 +165,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
public event GenericMessage OnGenericMessage;
|
public event GenericMessage OnGenericMessage;
|
||||||
public event ImprovedInstantMessage OnInstantMessage;
|
public event ImprovedInstantMessage OnInstantMessage;
|
||||||
public event ChatMessage OnChatFromClient;
|
public event ChatMessage OnChatFromClient;
|
||||||
|
public event ChatMessageRaw OnChatFromClientRaw;
|
||||||
public event TextureRequest OnRequestTexture;
|
public event TextureRequest OnRequestTexture;
|
||||||
public event RezObject OnRezObject;
|
public event RezObject OnRezObject;
|
||||||
public event ModifyTerrain OnModifyTerrain;
|
public event ModifyTerrain OnModifyTerrain;
|
||||||
|
@ -181,6 +184,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
public event RequestMapBlocks OnRequestMapBlocks;
|
public event RequestMapBlocks OnRequestMapBlocks;
|
||||||
public event RequestMapName OnMapNameRequest;
|
public event RequestMapName OnMapNameRequest;
|
||||||
public event TeleportLocationRequest OnTeleportLocationRequest;
|
public event TeleportLocationRequest OnTeleportLocationRequest;
|
||||||
|
//DSG:
|
||||||
|
public event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
|
||||||
|
//end of DSG
|
||||||
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
|
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
|
||||||
public event DisconnectUser OnDisconnectUser;
|
public event DisconnectUser OnDisconnectUser;
|
||||||
public event RequestAvatarProperties OnRequestAvatarProperties;
|
public event RequestAvatarProperties OnRequestAvatarProperties;
|
||||||
|
@ -192,6 +198,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
public event GenericCall1 OnCompleteMovementToRegion;
|
public event GenericCall1 OnCompleteMovementToRegion;
|
||||||
public event UpdateAgent OnPreAgentUpdate;
|
public event UpdateAgent OnPreAgentUpdate;
|
||||||
public event UpdateAgent OnAgentUpdate;
|
public event UpdateAgent OnAgentUpdate;
|
||||||
|
public event UpdateAgentRaw OnAgentUpdateRaw;
|
||||||
public event AgentRequestSit OnAgentRequestSit;
|
public event AgentRequestSit OnAgentRequestSit;
|
||||||
public event AgentSit OnAgentSit;
|
public event AgentSit OnAgentSit;
|
||||||
public event AvatarPickerRequest OnAvatarPickerRequest;
|
public event AvatarPickerRequest OnAvatarPickerRequest;
|
||||||
|
|
|
@ -172,4 +172,4 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -640,7 +640,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
|
||||||
{
|
{
|
||||||
s_tree.Scale += copse.m_rate;
|
s_tree.Scale += copse.m_rate;
|
||||||
s_tree.ParentGroup.HasGroupChanged = true;
|
s_tree.ParentGroup.HasGroupChanged = true;
|
||||||
s_tree.ScheduleFullUpdate();
|
//s_tree.ScheduleFullUpdate();
|
||||||
|
s_tree.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Scale});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -24,10 +24,12 @@
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
|
using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
@ -36,6 +38,8 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
||||||
{
|
{
|
||||||
public class BasicScene : PhysicsScene
|
public class BasicScene : PhysicsScene
|
||||||
{
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private List<BasicActor> _actors = new List<BasicActor>();
|
private List<BasicActor> _actors = new List<BasicActor>();
|
||||||
private float[] _heightMap;
|
private float[] _heightMap;
|
||||||
|
|
||||||
|
@ -123,7 +127,16 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
||||||
actorPosition.X = ((int)Constants.RegionSize - 0.1f);
|
actorPosition.X = ((int)Constants.RegionSize - 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
float height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z;
|
float height = 25.0F;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z;
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[BASICPHYSICS]: Actor out of range: {0}", actor.SOPName, actor.Position.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
if (actor.Flying)
|
if (actor.Flying)
|
||||||
{
|
{
|
||||||
if (actor.Position.Z + (actor.Velocity.Z*timeStep) <
|
if (actor.Position.Z + (actor.Velocity.Z*timeStep) <
|
||||||
|
|
|
@ -115,6 +115,49 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Structure to hold previous values of the PhysicsActor. This is used to see
|
||||||
|
/// if the values changed before sending updates to the Physics Engine.
|
||||||
|
/// </summary>
|
||||||
|
public struct PhysActorLastValues
|
||||||
|
{
|
||||||
|
public uint updateTime;
|
||||||
|
public uint localID;
|
||||||
|
public Vector3 size;
|
||||||
|
public Vector3 position;
|
||||||
|
public Vector3 force;
|
||||||
|
public Vector3 velocity;
|
||||||
|
public Vector3 rotationalVelocity;
|
||||||
|
public Vector3 torque;
|
||||||
|
public Quaternion orientation;
|
||||||
|
public Boolean isPhysical;
|
||||||
|
public Boolean flying;
|
||||||
|
public double buoyancy;
|
||||||
|
public bool Changed(PhysicsActor pa)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
if (localID != pa.LocalID) { localID = pa.LocalID; ret = true; }
|
||||||
|
if (size != pa.Size) { size = pa.Size; ret = true; }
|
||||||
|
if (!AlmostEqual(position, pa.Position)) { position = pa.Position; ret = true; }
|
||||||
|
if (!AlmostEqual(force, pa.Force)) { force = pa.Force; ret = true; }
|
||||||
|
if (!AlmostEqual(velocity, pa.Velocity)) { velocity = pa.Velocity; ret = true; }
|
||||||
|
if (!AlmostEqual(rotationalVelocity, pa.RotationalVelocity)) { rotationalVelocity = pa.RotationalVelocity; ret = true; }
|
||||||
|
if (!AlmostEqual(torque, pa.Torque)) { torque = pa.Torque; ret = true; }
|
||||||
|
if (orientation != pa.Orientation) { orientation = pa.Orientation; ret = true; }
|
||||||
|
if (isPhysical != pa.IsPhysical) { isPhysical = pa.IsPhysical; ret = true; }
|
||||||
|
if (flying != pa.Flying) { flying = pa.Flying; ret = true; }
|
||||||
|
if (buoyancy != pa.Buoyancy) { buoyancy = pa.Buoyancy; ret = true; }
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
private bool AlmostEqual(Vector3 a, Vector3 b)
|
||||||
|
{
|
||||||
|
if (Math.Abs(a.X - b.X) > 0.01) return false;
|
||||||
|
if (Math.Abs(a.Y - b.Y) > 0.01) return false;
|
||||||
|
if (Math.Abs(a.Z - b.Z) > 0.01) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class PhysicsActor
|
public abstract class PhysicsActor
|
||||||
{
|
{
|
||||||
public delegate void RequestTerseUpdate();
|
public delegate void RequestTerseUpdate();
|
||||||
|
@ -142,12 +185,24 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
|
|
||||||
public abstract PrimitiveBaseShape Shape { set; }
|
public abstract PrimitiveBaseShape Shape { set; }
|
||||||
|
|
||||||
|
// RA: used to be abstract but changed to allow 'get' without changing all the phys engines
|
||||||
uint m_baseLocalID;
|
uint m_baseLocalID;
|
||||||
public virtual uint LocalID
|
public virtual uint LocalID
|
||||||
{
|
{
|
||||||
set { m_baseLocalID = value; }
|
set { m_baseLocalID = value; }
|
||||||
get { return m_baseLocalID; }
|
get { return m_baseLocalID; }
|
||||||
}
|
}
|
||||||
|
public UUID m_UUID;
|
||||||
|
public virtual UUID UUID
|
||||||
|
{
|
||||||
|
set { m_UUID = value; }
|
||||||
|
get { return m_UUID; }
|
||||||
|
}
|
||||||
|
public PhysActorLastValues lastValues;
|
||||||
|
// ID of actor which last updated the values. Send if I did the change.
|
||||||
|
public string ChangingActorID = "YY";
|
||||||
|
// set to true of prim is updated
|
||||||
|
public bool SyncUpdated;
|
||||||
|
|
||||||
public abstract bool Grabbed { set; }
|
public abstract bool Grabbed { set; }
|
||||||
|
|
||||||
|
@ -222,7 +277,12 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
public abstract Vector3 Velocity { get; set; }
|
public abstract Vector3 Velocity { get; set; }
|
||||||
public abstract Vector3 Torque { get; set; }
|
public abstract Vector3 Torque { get; set; }
|
||||||
public abstract float CollisionScore { get; set;}
|
public abstract float CollisionScore { get; set;}
|
||||||
public abstract Vector3 Acceleration { get; }
|
// RA: used to be abstract but made virtual so 'set' does not need to be added to all phys engines
|
||||||
|
private Vector3 _acceleration;
|
||||||
|
public virtual Vector3 Acceleration {
|
||||||
|
get { return _acceleration; }
|
||||||
|
set { _acceleration = value; }
|
||||||
|
}
|
||||||
public abstract Quaternion Orientation { get; set; }
|
public abstract Quaternion Orientation { get; set; }
|
||||||
public abstract int PhysicsActorType { get; set; }
|
public abstract int PhysicsActorType { get; set; }
|
||||||
public abstract bool IsPhysical { get; set; }
|
public abstract bool IsPhysical { get; set; }
|
||||||
|
@ -285,6 +345,7 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
public override uint LocalID
|
public override uint LocalID
|
||||||
{
|
{
|
||||||
set { return; }
|
set { return; }
|
||||||
|
get { return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Grabbed
|
public override bool Grabbed
|
||||||
|
@ -419,6 +480,7 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
public override Vector3 Acceleration
|
public override Vector3 Acceleration
|
||||||
{
|
{
|
||||||
get { return Vector3.Zero; }
|
get { return Vector3.Zero; }
|
||||||
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsPhysical
|
public override bool IsPhysical
|
||||||
|
|
|
@ -32,6 +32,7 @@ using OpenMetaverse;
|
||||||
using Ode.NET;
|
using Ode.NET;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.OdePlugin
|
namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
@ -202,6 +203,25 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
m_name = avName;
|
m_name = avName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void RequestPhysicsterseUpdate()
|
||||||
|
{
|
||||||
|
if (PhysEngineToSceneConnectorModule.IsPhysEngineActorS)
|
||||||
|
{
|
||||||
|
// if the values have changed and it was I who changed them, send an update
|
||||||
|
// if (this.lastValues.Changed(this) && ChangingActorID == RegionSyncServerModule.ActorID)
|
||||||
|
if (ChangingActorID == RegionSyncServerModule.ActorID)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[ODE CHARACTER]: Sending terse update for {0}", LocalID);
|
||||||
|
ChangingActorID = "XXX"; // it's been sent. I am not changing it.
|
||||||
|
PhysEngineToSceneConnectorModule.RouteUpdate(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override int PhysicsActorType
|
public override int PhysicsActorType
|
||||||
{
|
{
|
||||||
get { return (int) ActorTypes.Agent; }
|
get { return (int) ActorTypes.Agent; }
|
||||||
|
@ -220,6 +240,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public override uint LocalID
|
public override uint LocalID
|
||||||
{
|
{
|
||||||
set { m_localID = value; }
|
set { m_localID = value; }
|
||||||
|
get { return m_localID; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Grabbed
|
public override bool Grabbed
|
||||||
|
@ -408,6 +429,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
get { return _position; }
|
get { return _position; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
|
if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
if (value.IsFinite())
|
if (value.IsFinite())
|
||||||
|
@ -453,6 +475,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
|
get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
if (value.IsFinite())
|
if (value.IsFinite())
|
||||||
{
|
{
|
||||||
m_pidControllerActive = true;
|
m_pidControllerActive = true;
|
||||||
|
@ -774,6 +797,13 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
m_pidControllerActive = true;
|
m_pidControllerActive = true;
|
||||||
_target_velocity = value;
|
_target_velocity = value;
|
||||||
|
if (_target_velocity.X == 0 && _target_velocity.Y == 0 && _target_velocity.Z == 0)
|
||||||
|
{
|
||||||
|
// if stopping, force real velocity to zero
|
||||||
|
_velocity = Vector3.Zero;
|
||||||
|
// m_log.DebugFormat("{0}: Set velocity {1}", "[PHYSICS]", _target_velocity); // RADEBUG
|
||||||
|
}
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -813,6 +843,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public override Vector3 Acceleration
|
public override Vector3 Acceleration
|
||||||
{
|
{
|
||||||
get { return _acceleration; }
|
get { return _acceleration; }
|
||||||
|
set { _acceleration = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAcceleration(Vector3 accel)
|
public void SetAcceleration(Vector3 accel)
|
||||||
|
@ -830,6 +861,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
if (force.IsFinite())
|
if (force.IsFinite())
|
||||||
{
|
{
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
if (pushforce)
|
if (pushforce)
|
||||||
{
|
{
|
||||||
m_pidControllerActive = false;
|
m_pidControllerActive = false;
|
||||||
|
@ -906,10 +938,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
d.Vector3 localpos = d.BodyGetPosition(Body);
|
d.Vector3 localpos = d.BodyGetPosition(Body);
|
||||||
Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
|
Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
|
||||||
|
|
||||||
if (!localPos.IsFinite())
|
if (!localPos.IsFinite() || localpos.X < 0.0 || localpos.X > 256.0 || localpos.Y < 0.0 || localpos.Y > 256.0 || localpos.Z < 0.0)
|
||||||
{
|
{
|
||||||
|
m_log.Warn("[PHYSICS]: Avatar Position is non-finite or out of bounds!");
|
||||||
m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
|
|
||||||
defects.Add(this);
|
defects.Add(this);
|
||||||
// _parent_scene.RemoveCharacter(this);
|
// _parent_scene.RemoveCharacter(this);
|
||||||
|
|
||||||
|
@ -960,10 +991,12 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
|
if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
|
||||||
{
|
{
|
||||||
// keep track of where we stopped. No more slippin' & slidin'
|
// keep track of where we stopped. No more slippin' & slidin'
|
||||||
|
// m_log.DebugFormat("[PHYSICS]: Move setting zero. zeroFlag={0}, pidControllerActive={1}", _zeroFlag, m_pidControllerActive); // RADEBUG
|
||||||
if (!_zeroFlag)
|
if (!_zeroFlag)
|
||||||
{
|
{
|
||||||
_zeroFlag = true;
|
_zeroFlag = true;
|
||||||
_zeroPosition = d.BodyGetPosition(Body);
|
_zeroPosition = d.BodyGetPosition(Body);
|
||||||
|
_velocity = _target_velocity;
|
||||||
}
|
}
|
||||||
if (m_pidControllerActive)
|
if (m_pidControllerActive)
|
||||||
{
|
{
|
||||||
|
@ -1141,13 +1174,15 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
_velocity.Y = 0.0f;
|
_velocity.Y = 0.0f;
|
||||||
_velocity.Z = 0.0f;
|
_velocity.Z = 0.0f;
|
||||||
|
|
||||||
|
/*
|
||||||
// Did we send out the 'stopped' message?
|
// Did we send out the 'stopped' message?
|
||||||
if (!m_lastUpdateSent)
|
if (!m_lastUpdateSent)
|
||||||
{
|
{
|
||||||
m_lastUpdateSent = true;
|
m_lastUpdateSent = true;
|
||||||
//base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1183,6 +1218,12 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
m_hackSentFall = false;
|
m_hackSentFall = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!m_lastUpdateSent)
|
||||||
|
{
|
||||||
|
m_lastUpdateSent = true;
|
||||||
|
ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
|
this.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1349,7 +1390,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
_position.Z = m_taintPosition.Z;
|
_position.Z = m_taintPosition.Z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
|
this.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddCollisionFrameTime(int p)
|
internal void AddCollisionFrameTime(int p)
|
||||||
|
|
|
@ -50,7 +50,9 @@ using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using Ode.NET;
|
using Ode.NET;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.OdePlugin
|
namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
|
@ -253,6 +255,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
m_taintadd = true;
|
m_taintadd = true;
|
||||||
_parent_scene.AddPhysicsActorTaint(this);
|
_parent_scene.AddPhysicsActorTaint(this);
|
||||||
// don't do .add() here; old geoms get recycled with the same hash
|
// don't do .add() here; old geoms get recycled with the same hash
|
||||||
|
// m_log.DebugFormat("[PHYSICS] Created ODEPrim: n={0}, m={1}, pbs={2}, phys={3}",
|
||||||
|
// primName, mesh == null ? "NULL" : "DEFINED", pbs == null ? "NULL" : "DEFINED", pisPhysical);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int PhysicsActorType
|
public override int PhysicsActorType
|
||||||
|
@ -272,6 +276,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
set {
|
set {
|
||||||
//m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
|
//m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
|
||||||
m_localID = value; }
|
m_localID = value; }
|
||||||
|
get { return m_localID; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Grabbed
|
public override bool Grabbed
|
||||||
|
@ -2467,6 +2472,7 @@ Console.WriteLine("changeshape not need meshing");
|
||||||
public override Vector3 Acceleration
|
public override Vector3 Acceleration
|
||||||
{
|
{
|
||||||
get { return _acceleration; }
|
get { return _acceleration; }
|
||||||
|
set { _acceleration = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2622,7 +2628,7 @@ Console.WriteLine("changeshape not need meshing");
|
||||||
_position = l_position;
|
_position = l_position;
|
||||||
//_parent_scene.remActivePrim(this);
|
//_parent_scene.remActivePrim(this);
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2657,7 +2663,7 @@ Console.WriteLine("changeshape not need meshing");
|
||||||
m_rotationalVelocity.Z = 0;
|
m_rotationalVelocity.Z = 0;
|
||||||
|
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
|
|
||||||
m_throttleUpdates = false;
|
m_throttleUpdates = false;
|
||||||
throttleCounter = 0;
|
throttleCounter = 0;
|
||||||
|
@ -2710,7 +2716,7 @@ Console.WriteLine("changeshape not need meshing");
|
||||||
|
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
{
|
{
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastUpdateSent = true;
|
m_lastUpdateSent = true;
|
||||||
|
@ -2722,7 +2728,7 @@ Console.WriteLine("changeshape not need meshing");
|
||||||
{
|
{
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
{
|
{
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2757,7 +2763,7 @@ Console.WriteLine("changeshape not need meshing");
|
||||||
{
|
{
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
{
|
{
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -83,4 +83,4 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.PEPlugin
|
||||||
|
{
|
||||||
|
public class PECharacter : PhysicsActor
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool _stopped;
|
||||||
|
private Vector3 _size;
|
||||||
|
private PrimitiveBaseShape _pbs;
|
||||||
|
private uint _localID = 0;
|
||||||
|
private bool _grabbed;
|
||||||
|
private bool _selected;
|
||||||
|
private Vector3 _position;
|
||||||
|
private float _mass = 80f;
|
||||||
|
public float _density = 60f;
|
||||||
|
public float CAPSULE_RADIUS = 0.37f;
|
||||||
|
public float CAPSULE_LENGTH = 2.140599f;
|
||||||
|
private Vector3 _force;
|
||||||
|
private Vector3 _velocity;
|
||||||
|
private Vector3 _torque;
|
||||||
|
private float _collisionScore;
|
||||||
|
private Vector3 _acceleration;
|
||||||
|
private Quaternion _orientation;
|
||||||
|
private int _physicsActorType;
|
||||||
|
private bool _isPhysical;
|
||||||
|
private bool _flying;
|
||||||
|
private bool _setAlwaysRun;
|
||||||
|
private bool _throttleUpdates;
|
||||||
|
private bool _isColliding;
|
||||||
|
private bool _collidingGround;
|
||||||
|
private bool _collidingObj;
|
||||||
|
private bool _floatOnWater;
|
||||||
|
private Vector3 _rotationalVelocity;
|
||||||
|
private bool _kinematic;
|
||||||
|
private float _buoyancy;
|
||||||
|
|
||||||
|
private Vector3 _PIDTarget;
|
||||||
|
private bool _usePID;
|
||||||
|
private float _PIDTau;
|
||||||
|
private bool _useHoverPID;
|
||||||
|
private float _PIDHoverHeight;
|
||||||
|
private PIDHoverType _PIDHoverType;
|
||||||
|
private float _PIDHoverTao;
|
||||||
|
|
||||||
|
public PECharacter(String avName, PEScene parent_scene, Vector3 pos,
|
||||||
|
CollisionLocker dode, Vector3 size, float pid_d, float pid_p,
|
||||||
|
float capsule_radius, float tensor, float density, float height_fudge_factor,
|
||||||
|
float walk_divisor, float rundivisor)
|
||||||
|
{
|
||||||
|
_position = pos;
|
||||||
|
_size = size;
|
||||||
|
_density = density;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RequestPhysicsterseUpdate()
|
||||||
|
{
|
||||||
|
if (PhysEngineToSceneConnectorModule.IsPhysEngineActorS)
|
||||||
|
{
|
||||||
|
// if the values have changed and it was I who changed them, send an update
|
||||||
|
if (this.lastValues.Changed(this) && ChangingActorID == RegionSyncServerModule.ActorID)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[ODE CHARACTER]: Sending terse update for {0}", LocalID);
|
||||||
|
PhysEngineToSceneConnectorModule.RouteUpdate(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override bool Stopped {
|
||||||
|
get { return _stopped; }
|
||||||
|
}
|
||||||
|
public override Vector3 Size {
|
||||||
|
get { return _size; }
|
||||||
|
set { _size = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override PrimitiveBaseShape Shape {
|
||||||
|
set { _pbs = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override uint LocalID {
|
||||||
|
set { _localID = value;
|
||||||
|
}
|
||||||
|
get { return _localID; }
|
||||||
|
}
|
||||||
|
public override bool Grabbed {
|
||||||
|
set { _grabbed = value;
|
||||||
|
// m_log.Debug("[RPE] PEChar set Grabbed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool Selected {
|
||||||
|
set { _selected = value;
|
||||||
|
// m_log.Debug("[RPE] PEChar set Selected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void CrossingFailure() { return; }
|
||||||
|
public override void link(PhysicsActor obj) { return; }
|
||||||
|
public override void delink() { return; }
|
||||||
|
public override void LockAngularMotion(Vector3 axis) { return; }
|
||||||
|
|
||||||
|
public override Vector3 Position {
|
||||||
|
get { return _position; }
|
||||||
|
set { _position = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float Mass {
|
||||||
|
get {
|
||||||
|
float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
|
||||||
|
_mass = _density*AVvolume;
|
||||||
|
return _mass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Vector3 Force {
|
||||||
|
get { return _force; }
|
||||||
|
set { _force = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int VehicleType {
|
||||||
|
get { return 0; }
|
||||||
|
set { return; }
|
||||||
|
}
|
||||||
|
public override void VehicleFloatParam(int param, float value) { }
|
||||||
|
public override void VehicleVectorParam(int param, Vector3 value) {}
|
||||||
|
public override void VehicleRotationParam(int param, Quaternion rotation) { }
|
||||||
|
public override void VehicleFlags(int param, bool remove) { }
|
||||||
|
|
||||||
|
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
|
||||||
|
public override void SetVolumeDetect(int param) { return; }
|
||||||
|
|
||||||
|
public override Vector3 GeometricCenter { get { return Vector3.Zero; } }
|
||||||
|
public override Vector3 CenterOfMass { get { return Vector3.Zero; } }
|
||||||
|
public override Vector3 Velocity {
|
||||||
|
get { return _velocity; }
|
||||||
|
set { _velocity = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Vector3 Torque {
|
||||||
|
get { return _torque; }
|
||||||
|
set { _torque = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float CollisionScore {
|
||||||
|
get { return _collisionScore; }
|
||||||
|
set { _collisionScore = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Vector3 Acceleration {
|
||||||
|
get { return _acceleration; }
|
||||||
|
}
|
||||||
|
public override Quaternion Orientation {
|
||||||
|
get { return _orientation; }
|
||||||
|
set { _orientation = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override int PhysicsActorType {
|
||||||
|
get { return _physicsActorType; }
|
||||||
|
set { _physicsActorType = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool IsPhysical {
|
||||||
|
get { return _isPhysical; }
|
||||||
|
set { _isPhysical = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool Flying {
|
||||||
|
get { return _flying; }
|
||||||
|
set { _flying = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool
|
||||||
|
SetAlwaysRun {
|
||||||
|
get { return _setAlwaysRun; }
|
||||||
|
set { _setAlwaysRun = value; }
|
||||||
|
}
|
||||||
|
public override bool ThrottleUpdates {
|
||||||
|
get { return _throttleUpdates; }
|
||||||
|
set { _throttleUpdates = value; }
|
||||||
|
}
|
||||||
|
public override bool IsColliding {
|
||||||
|
get { return _isColliding; }
|
||||||
|
set { _isColliding = value; }
|
||||||
|
}
|
||||||
|
public override bool CollidingGround {
|
||||||
|
get { return _collidingGround; }
|
||||||
|
set { _collidingGround = value; }
|
||||||
|
}
|
||||||
|
public override bool CollidingObj {
|
||||||
|
get { return _collidingObj; }
|
||||||
|
set { _collidingObj = value; }
|
||||||
|
}
|
||||||
|
public override bool FloatOnWater {
|
||||||
|
set { _floatOnWater = value; }
|
||||||
|
}
|
||||||
|
public override Vector3 RotationalVelocity {
|
||||||
|
get { return _rotationalVelocity; }
|
||||||
|
set { _rotationalVelocity = value; }
|
||||||
|
}
|
||||||
|
public override bool Kinematic {
|
||||||
|
get { return _kinematic; }
|
||||||
|
set { _kinematic = value; }
|
||||||
|
}
|
||||||
|
public override float Buoyancy {
|
||||||
|
get { return _buoyancy; }
|
||||||
|
set { _buoyancy = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for MoveTo
|
||||||
|
public override Vector3 PIDTarget {
|
||||||
|
set { _PIDTarget = value; }
|
||||||
|
}
|
||||||
|
public override bool PIDActive {
|
||||||
|
set { _usePID = value; }
|
||||||
|
}
|
||||||
|
public override float PIDTau {
|
||||||
|
set { _PIDTau = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for llSetHoverHeight and maybe vehicle height
|
||||||
|
// Hover Height will override MoveTo target's Z
|
||||||
|
public override bool PIDHoverActive {
|
||||||
|
set { _useHoverPID = value; }
|
||||||
|
}
|
||||||
|
public override float PIDHoverHeight {
|
||||||
|
set { _PIDHoverHeight = value; }
|
||||||
|
}
|
||||||
|
public override PIDHoverType PIDHoverType {
|
||||||
|
set { _PIDHoverType = value; }
|
||||||
|
}
|
||||||
|
public override float PIDHoverTau {
|
||||||
|
set { _PIDHoverTao = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// For RotLookAt
|
||||||
|
public override Quaternion APIDTarget { set { return; } }
|
||||||
|
public override bool APIDActive { set { return; } }
|
||||||
|
public override float APIDStrength { set { return; } }
|
||||||
|
public override float APIDDamping { set { return; } }
|
||||||
|
|
||||||
|
public override void AddForce(Vector3 force, bool pushforce) {
|
||||||
|
if (force.IsFinite())
|
||||||
|
{
|
||||||
|
// base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
|
_velocity.X += force.X;
|
||||||
|
_velocity.Y += force.Y;
|
||||||
|
_velocity.Z += force.Z;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
|
||||||
|
}
|
||||||
|
//m_lastUpdateSent = false;
|
||||||
|
}
|
||||||
|
public override void AddAngularForce(Vector3 force, bool pushforce) {
|
||||||
|
}
|
||||||
|
public override void SetMomentum(Vector3 momentum) {
|
||||||
|
}
|
||||||
|
public override void SubscribeEvents(int ms) {
|
||||||
|
}
|
||||||
|
public override void UnSubscribeEvents() {
|
||||||
|
}
|
||||||
|
public override bool SubscribedEvents() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.PEPlugin
|
||||||
|
{
|
||||||
|
public class PEPlugin : IPhysicsPlugin
|
||||||
|
{
|
||||||
|
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private PEScene _mScene;
|
||||||
|
|
||||||
|
public PEPlugin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Init()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhysicsScene GetScene(String sceneIdentifier)
|
||||||
|
{
|
||||||
|
if (_mScene == null)
|
||||||
|
{
|
||||||
|
_mScene = new PEScene(sceneIdentifier);
|
||||||
|
}
|
||||||
|
return (_mScene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return ("RemotePhysicsEngine");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,287 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.PEPlugin
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class PEPrim : PhysicsActor
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool _stopped;
|
||||||
|
private Vector3 _size;
|
||||||
|
private PrimitiveBaseShape _pbs;
|
||||||
|
private uint _localID = 0;
|
||||||
|
private bool _grabbed;
|
||||||
|
private bool _selected;
|
||||||
|
private Vector3 _position;
|
||||||
|
private float _mass;
|
||||||
|
private Vector3 _force;
|
||||||
|
private Vector3 _velocity;
|
||||||
|
private Vector3 _torque;
|
||||||
|
private float _collisionScore;
|
||||||
|
private Vector3 _acceleration;
|
||||||
|
private Quaternion _orientation;
|
||||||
|
private int _physicsActorType;
|
||||||
|
private bool _isPhysical;
|
||||||
|
private bool _flying;
|
||||||
|
private bool _setAlwaysRun;
|
||||||
|
private bool _throttleUpdates;
|
||||||
|
private bool _isColliding;
|
||||||
|
private bool _collidingGround;
|
||||||
|
private bool _collidingObj;
|
||||||
|
private bool _floatOnWater;
|
||||||
|
private Vector3 _rotationalVelocity;
|
||||||
|
private bool _kinematic;
|
||||||
|
private float _buoyancy;
|
||||||
|
|
||||||
|
private Vector3 _PIDTarget;
|
||||||
|
private bool _usePID;
|
||||||
|
private float _PIDTau;
|
||||||
|
private bool _useHoverPID;
|
||||||
|
private float _PIDHoverHeight;
|
||||||
|
private PIDHoverType _PIDHoverType;
|
||||||
|
private float _PIDHoverTao;
|
||||||
|
|
||||||
|
public PEPrim(String primName, PEScene parent_scene, Vector3 pos, Vector3 size,
|
||||||
|
Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
|
||||||
|
{
|
||||||
|
_position = pos;
|
||||||
|
_size = size;
|
||||||
|
_orientation = rotation;
|
||||||
|
// m_log.DebugFormat("[REMOTE PRIM ENGINE] PEPrim creation of {0}", primName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Stopped {
|
||||||
|
get { return _stopped; }
|
||||||
|
}
|
||||||
|
public override Vector3 Size {
|
||||||
|
get { return _size; }
|
||||||
|
set { _size = value;
|
||||||
|
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Size");
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override PrimitiveBaseShape Shape {
|
||||||
|
set { _pbs = value;
|
||||||
|
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Shape");
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override uint LocalID {
|
||||||
|
set { _localID = value;
|
||||||
|
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set LocalID");
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
get { return _localID; }
|
||||||
|
}
|
||||||
|
public override bool Grabbed {
|
||||||
|
set { _grabbed = value;
|
||||||
|
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Grabbed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool Selected {
|
||||||
|
set { _selected = value;
|
||||||
|
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Selected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void CrossingFailure() { return; }
|
||||||
|
public override void link(PhysicsActor obj) { return; }
|
||||||
|
public override void delink() { return; }
|
||||||
|
public override void LockAngularMotion(Vector3 axis) { return; }
|
||||||
|
|
||||||
|
public override Vector3 Position {
|
||||||
|
get { return _position; }
|
||||||
|
set { _position = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Position");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float Mass {
|
||||||
|
get { return _mass; }
|
||||||
|
}
|
||||||
|
public override Vector3 Force {
|
||||||
|
get { return _force; }
|
||||||
|
set { _force = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Force");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int VehicleType {
|
||||||
|
get { return 0; }
|
||||||
|
set { return; }
|
||||||
|
}
|
||||||
|
public override void VehicleFloatParam(int param, float value) { }
|
||||||
|
public override void VehicleVectorParam(int param, Vector3 value) {}
|
||||||
|
public override void VehicleRotationParam(int param, Quaternion rotation) { }
|
||||||
|
public override void VehicleFlags(int param, bool remove) { }
|
||||||
|
|
||||||
|
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
|
||||||
|
public override void SetVolumeDetect(int param) { return; }
|
||||||
|
|
||||||
|
public override Vector3 GeometricCenter { get { return Vector3.Zero; } }
|
||||||
|
public override Vector3 CenterOfMass { get { return Vector3.Zero; } }
|
||||||
|
public override Vector3 Velocity {
|
||||||
|
get { return _velocity; }
|
||||||
|
set { _velocity = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Vector3 Torque {
|
||||||
|
get { return _torque; }
|
||||||
|
set { _torque = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float CollisionScore {
|
||||||
|
get { return _collisionScore; }
|
||||||
|
set { _collisionScore = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Vector3 Acceleration {
|
||||||
|
get { return _acceleration; }
|
||||||
|
}
|
||||||
|
public override Quaternion Orientation {
|
||||||
|
get { return _orientation; }
|
||||||
|
set { _orientation = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override int PhysicsActorType {
|
||||||
|
get { return _physicsActorType; }
|
||||||
|
set { _physicsActorType = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool IsPhysical {
|
||||||
|
get { return _isPhysical; }
|
||||||
|
set { _isPhysical = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool Flying {
|
||||||
|
get { return _flying; }
|
||||||
|
set { _flying = value;
|
||||||
|
// SyncUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool
|
||||||
|
SetAlwaysRun {
|
||||||
|
get { return _setAlwaysRun; }
|
||||||
|
set { _setAlwaysRun = value; }
|
||||||
|
}
|
||||||
|
public override bool ThrottleUpdates {
|
||||||
|
get { return _throttleUpdates; }
|
||||||
|
set { _throttleUpdates = value; }
|
||||||
|
}
|
||||||
|
public override bool IsColliding {
|
||||||
|
get { return _isColliding; }
|
||||||
|
set { _isColliding = value; }
|
||||||
|
}
|
||||||
|
public override bool CollidingGround {
|
||||||
|
get { return _collidingGround; }
|
||||||
|
set { _collidingGround = value; }
|
||||||
|
}
|
||||||
|
public override bool CollidingObj {
|
||||||
|
get { return _collidingObj; }
|
||||||
|
set { _collidingObj = value; }
|
||||||
|
}
|
||||||
|
public override bool FloatOnWater {
|
||||||
|
set { _floatOnWater = value; }
|
||||||
|
}
|
||||||
|
public override Vector3 RotationalVelocity {
|
||||||
|
get { return _rotationalVelocity; }
|
||||||
|
set { _rotationalVelocity = value; }
|
||||||
|
}
|
||||||
|
public override bool Kinematic {
|
||||||
|
get { return _kinematic; }
|
||||||
|
set { _kinematic = value; }
|
||||||
|
}
|
||||||
|
public override float Buoyancy {
|
||||||
|
get { return _buoyancy; }
|
||||||
|
set { _buoyancy = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for MoveTo
|
||||||
|
public override Vector3 PIDTarget {
|
||||||
|
set { _PIDTarget = value; }
|
||||||
|
}
|
||||||
|
public override bool PIDActive {
|
||||||
|
set { _usePID = value; }
|
||||||
|
}
|
||||||
|
public override float PIDTau {
|
||||||
|
set { _PIDTau = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for llSetHoverHeight and maybe vehicle height
|
||||||
|
// Hover Height will override MoveTo target's Z
|
||||||
|
public override bool PIDHoverActive {
|
||||||
|
set { _useHoverPID = value; }
|
||||||
|
}
|
||||||
|
public override float PIDHoverHeight {
|
||||||
|
set { _PIDHoverHeight = value; }
|
||||||
|
}
|
||||||
|
public override PIDHoverType PIDHoverType {
|
||||||
|
set { _PIDHoverType = value; }
|
||||||
|
}
|
||||||
|
public override float PIDHoverTau {
|
||||||
|
set { _PIDHoverTao = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// For RotLookAt
|
||||||
|
public override Quaternion APIDTarget { set { return; } }
|
||||||
|
public override bool APIDActive { set { return; } }
|
||||||
|
public override float APIDStrength { set { return; } }
|
||||||
|
public override float APIDDamping { set { return; } }
|
||||||
|
|
||||||
|
public override void AddForce(Vector3 force, bool pushforce) {
|
||||||
|
}
|
||||||
|
public override void AddAngularForce(Vector3 force, bool pushforce) {
|
||||||
|
}
|
||||||
|
public override void SetMomentum(Vector3 momentum) {
|
||||||
|
}
|
||||||
|
public override void SubscribeEvents(int ms) {
|
||||||
|
}
|
||||||
|
public override void UnSubscribeEvents() {
|
||||||
|
}
|
||||||
|
public override bool SubscribedEvents() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Nini.Config;
|
||||||
|
using log4net;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Region.Framework;
|
||||||
|
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.PEPlugin
|
||||||
|
{
|
||||||
|
public class PEScene : PhysicsScene
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private List<PECharacter> m_avatars = new List<PECharacter>();
|
||||||
|
private List<PEPrim> m_prims = new List<PEPrim>();
|
||||||
|
private float[] m_heightMap;
|
||||||
|
|
||||||
|
public PEScene(string identifier)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialise(IMesher meshmerizer, IConfigSource config)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
|
||||||
|
{
|
||||||
|
PECharacter actor = new PECharacter(avName, this, position, null, size, 0f, 0f, .5f, 1f,
|
||||||
|
1f, 1f, .5f, .5f);
|
||||||
|
lock (m_avatars) m_avatars.Add(actor);
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RemoveAvatar(PhysicsActor actor)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (m_avatars) m_avatars.Remove((PECharacter)actor);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[RPE]: Attempt to remove avatar that is not in physics scene: {0}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RemovePrim(PhysicsActor prim)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (m_prims) m_prims.Remove((PEPrim)prim);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[RPE]: Attempt to remove prim that is not in physics scene: {0}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
|
Vector3 size, Quaternion rotation, bool isPhysical, uint localID)
|
||||||
|
{
|
||||||
|
PEPrim prim = new PEPrim(primName, this, position, size, rotation, null, pbs, isPhysical, null);
|
||||||
|
prim.LocalID = localID;
|
||||||
|
lock (m_prims) m_prims.Add(prim);
|
||||||
|
return prim;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
|
||||||
|
|
||||||
|
public override float Simulate(float timeStep)
|
||||||
|
{
|
||||||
|
// if we are a physics engine server, send update information
|
||||||
|
if (SceneToPhysEngineSyncServer.IsPhysEngineScene2S())
|
||||||
|
{
|
||||||
|
if (SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S())
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count);
|
||||||
|
/*
|
||||||
|
lock (m_prims)
|
||||||
|
{
|
||||||
|
foreach (PEPrim prim in m_prims)
|
||||||
|
{
|
||||||
|
// if the values have changed and it was I who changed them, send an update
|
||||||
|
if (prim.ChangingActorID == RegionSyncServerModule.ActorID && prim.lastValues.Changed(prim))
|
||||||
|
{
|
||||||
|
SceneToPhysEngineSyncServer.RouteUpdate(prim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
lock (m_avatars)
|
||||||
|
{
|
||||||
|
foreach (PECharacter actor in m_avatars)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count);
|
||||||
|
// if the values have changed and it was I who changed them, send an update
|
||||||
|
if (actor.ChangingActorID == RegionSyncServerModule.ActorID && actor.lastValues.Changed(actor))
|
||||||
|
{
|
||||||
|
SceneToPhysEngineSyncServer.RouteUpdate(actor);
|
||||||
|
actor.ChangingActorID = "YY";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 60f;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// code borrowed from BasicPhysics to do just avatar movement
|
||||||
|
foreach (PECharacter actor in m_avatars)
|
||||||
|
{
|
||||||
|
Vector3 actorPosition = actor.Position;
|
||||||
|
Vector3 actorVelocity = actor.Velocity;
|
||||||
|
|
||||||
|
actorPosition.X += actor.Velocity.X*timeStep;
|
||||||
|
actorPosition.Y += actor.Velocity.Y*timeStep;
|
||||||
|
|
||||||
|
actorPosition.Y = Math.Max(actorPosition.Y, 0.1f);
|
||||||
|
actorPosition.Y = Math.Min(actorPosition.Y, Constants.RegionSize - 0.1f);
|
||||||
|
actorPosition.X = Math.Max(actorPosition.X, 0.1f);
|
||||||
|
actorPosition.X = Math.Min(actorPosition.X, Constants.RegionSize - 0.1f);
|
||||||
|
|
||||||
|
float height = 25.0F;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
height = m_heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z;
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[RPE]: Actor out of range: {0}", actor.SOPName, actor.Position.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor.Flying)
|
||||||
|
{
|
||||||
|
if (actor.Position.Z + (actor.Velocity.Z*timeStep) <
|
||||||
|
m_heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 2)
|
||||||
|
{
|
||||||
|
actorPosition.Z = height;
|
||||||
|
actorVelocity.Z = 0;
|
||||||
|
actor.IsColliding = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
actorPosition.Z += actor.Velocity.Z*timeStep;
|
||||||
|
actor.IsColliding = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
actorPosition.Z = height;
|
||||||
|
actorVelocity.Z = 0;
|
||||||
|
actor.IsColliding = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
actor.Position = actorPosition;
|
||||||
|
actor.Velocity = actorVelocity;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return 60f; // returns frames per second
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void GetResults() { }
|
||||||
|
|
||||||
|
public override void SetTerrain(float[] heightMap) {
|
||||||
|
m_heightMap = heightMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetWaterLevel(float baseheight) { }
|
||||||
|
|
||||||
|
public override void DeleteTerrain() { }
|
||||||
|
|
||||||
|
public override void Dispose() { }
|
||||||
|
|
||||||
|
public override Dictionary<uint, float> GetTopColliders()
|
||||||
|
{
|
||||||
|
return new Dictionary<uint, float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsThreaded { get { return false; } }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue