Compare commits

...

117 Commits

Author SHA1 Message Date
Melanie
f0f852b27f Final code drop for appearance. Adding Avination's baked texture storage server. 2014-02-04 02:29:02 +00:00
Melanie
1197658233 Adding the Avination XBakesModule, the client for the persistent bakes system 2014-02-04 02:09:39 +00:00
Melanie
e1d1c27965 Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim 2014-02-04 01:55:41 +00:00
Melanie
49c2213a01 Dropping the rest of Avination's modified appearance code for core.
Module to follow.
2014-02-04 01:54:16 +00:00
Robert Adams
41b6602a77 Add "--no-objects" parameter to 'load oar'. 2014-02-02 22:16:01 -08:00
Robert Adams
8c6a0cb44a Really add the old parameter names to load oar to keep downward compatibiliy 2014-02-02 17:18:08 -08:00
Robert Adams
2a4dd34616 Change new 'load oar' parameters to be hyphenated to be consistant with
existing parameters. ('--forceterrain' becomes '--force-terrain').
The old forms have been kept for downward compatiblity.
2014-02-02 12:21:18 -08:00
Robert Adams
9c97fb8e12 Implement terrain merging in TerrainChannel.
Modify archiver to use terrain merging when loading oars.
This makes displacement AND rotation properly work on terrain when loading oars.
Especially useful when loading legacy region oars into large varregions.
2014-02-02 11:17:49 -08:00
dahlia
a8e64cd59a Overload INPCModule.CreateNPC() to allow agentID to be specified. Note: this is intended for use in region modules and is not exposed to scripts. 2014-02-01 04:09:20 -08:00
Oren Hurvitz
abb193ec94 In UuidGatherer, gather materials referenced in the prim's TextureEntry
Signed-off-by: dahlia <dahlia@nomail>
2014-02-01 02:56:15 -08:00
Justin Clark-Casey (justincc)
b2878eb773 Merge branch 'justincc-master' 2014-01-31 00:51:22 +00:00
Oren Hurvitz
b8e22f02e7 Make sure Web streams are disposed after use 2014-01-31 00:44:22 +00:00
David Rowe
1380b37d71 Made error messages more consistent 2014-01-31 00:24:52 +00:00
David Rowe
3d62f4369d Replaced throwing exceptions with calls to Error() 2014-01-31 00:24:47 +00:00
David Rowe
d405254971 Replaced llSay()ing LSL errors with calls Error() 2014-01-31 00:24:43 +00:00
David Rowe
9db4090c07 Replaced LSLError() calls with calls to Error() 2014-01-31 00:24:40 +00:00
David Rowe
c9550e473d Updated "deprecated" LSL errors to use Deprecrated() 2014-01-31 00:24:36 +00:00
David Rowe
257f9cec40 Updated "not implemented" LSL errors to use NotImplemented() 2014-01-31 00:24:31 +00:00
David Rowe
13bb9ea682 Updated ShoutError() calls to use new LSL error methods 2014-01-31 00:21:22 +00:00
David Rowe
67ec95bde8 Updated methods for handling LSL script errors, deprecated, and not implemented 2014-01-31 00:20:10 +00:00
Justin Clark-Casey (justincc)
c467dfcd81 Merge branch 'justincc-master' 2014-01-30 00:42:20 +00:00
Justin Clark-Casey (justincc)
b73baeb4a4 Record whether login to home fails because no home set (UUID.Zero) or region not found. 2014-01-30 00:40:56 +00:00
Justin Clark-Casey (justincc)
b50e5704b8 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2014-01-30 00:06:09 +00:00
Justin Clark-Casey (justincc)
7807b19a89 Merge branch 'justincc-master' 2014-01-30 00:05:12 +00:00
Justin Clark-Casey (justincc)
bdab05df0e Add "show grid user" robust/standalone console command for debug purposes.
Shows all data on entries which match or start with a given ID.
This would usually be a UUID.
2014-01-30 00:03:22 +00:00
Robert Adams
0842e2e15b BulletSim: default physical terrain implementation to heightmap.
It originally looked like mesh terrain would perform better for vehicles
but, after much use, heightmap is the clear winner.
Force terrain implementation to heightmap if the physics region is
larger than legacy region size. This solves running out of memory for
very large regions.
2014-01-29 06:44:14 -08:00
Mic Bowman
fbf33ef1de Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2014-01-28 22:42:35 -08:00
Mic Bowman
3f5c6c897f One more run at fixing the sun module. Parameter setting fixed to
work through the OSSL interface. And setting the parameters now
adjusts all the dependent variables correctly so the sun moves
at the modified rate.
2014-01-28 22:40:39 -08:00
Robert Adams
1900254e77 Restore brush tests with correct values and adjustments for new terrain height
rounding characteristics.
2014-01-28 21:43:18 -08:00
Robert Adams
678c107915 Temporarily disable brush test. It will come back when tuning is complete. 2014-01-28 16:58:27 -08:00
Robert Adams
dde0e547a7 Change area of brush test to account for rounding errors in terrain implementation 2014-01-28 16:48:34 -08:00
Robert Adams
226b5e4d75 Increase the strength of brushes in brush test in an attempt to overcome rounding
introduced with new terrain height class.
2014-01-28 16:36:56 -08:00
Mic Bowman
cfe1bced7d Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2014-01-28 16:34:49 -08:00
Mic Bowman
2877c7d94d Actually make the parameter updates change the behavior of
sun movement.
2014-01-28 16:34:22 -08:00
Robert Adams
0c3493f619 clear land tainting when tested. Then testing, pass scene to LandObject as now needed to get region size 2014-01-28 16:25:01 -08:00
Robert Adams
d25265ae82 Fix terrain tests by properly initializing low detail terrain to zero height.
Also remove PI heightmap test as new heightmaps only have two significant digits.
2014-01-28 15:58:45 -08:00
Mic Bowman
1d533b0f01 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2014-01-28 15:47:24 -08:00
Mic Bowman
bfb0011cd3 Some major surgery on the sun module. Updates to the client were gated
by a "mode" check. That mode check has been removed (it didn't result
in any change of behavior anyway). Also added a command line variable
update to set the sun position time offset (offset from the system
clock). Default is no offset to preserve existing behavior.
2014-01-28 15:43:47 -08:00
Robert Adams
e5d59dc696 Repair database routines so they properly return null when asked for
the heighmap of a region that does not exist.
2014-01-28 15:29:06 -08:00
Robert Adams
8eec717f5f Merge branch 'master' into varregion 2014-01-28 08:50:28 -08:00
Robert Adams
4faf11e001 varregion: fix for teleporting by double clicking on a map location.
Thanks Garmin.
2014-01-28 08:49:22 -08:00
Robert Adams
49af6b53e7 varregion: enable teleporting to a varregion by clicking on the map and
pressing the 'teleport' button.
This commit adds returning region map info for all the subregions of a
varregion. This also handles the selection of the extra region and then
the displacement of the postion so the teleport is to the correct location.
2014-01-26 19:32:28 -08:00
Robert Adams
13a9d5409c Merge branch 'master' into varregion
Conflicts:
	OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
	OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
	OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
2014-01-26 07:56:47 -08:00
Robert Adams
6831e58616 varregion: modify MapImageModule structure so it will better merge
with changes made in master.
2014-01-26 07:38:28 -08:00
Robert Adams
afb2e07111 varregion: pass region size in more HG services. 2014-01-24 06:30:38 -08:00
Mic Bowman
674a3a5639 Enable the simulator to handle region size information returned from
a hypergrid gatekeeper. Fields are "size_x" and "size_y". Server side
will be updated separately.
2014-01-23 16:20:18 -08:00
Robert Adams
4c362a83f9 Merge branch 'master' into varregion 2014-01-21 11:31:51 -08:00
Robert Adams
90fa3202c6 varregion: remove debugging splat file saving that fills up the
maptile dir and causes errors.
2014-01-19 13:37:51 -08:00
Robert Adams
5e6a47f13f varregion: remove --noterrain and --noparcel parameters in 'load oar'.
Add --forceterrain and --forceparcel to 'load oar'. In order to not change
the operation of --merge (which does an object merge and suppresses terrain
and parcel information loading), added the --force* parameters to be used
when loading multiple oars to build up a varregion.

Added --rotation and --rotationcenter parameters to 'load oar' which apply a rotation to
the loaded oar objects before displacing. The rotation is in degrees (pos or neg)
and the center defaults to "<128, 128, 0>".
2014-01-19 12:45:16 -08:00
Robert Adams
6fbfb47b92 varregion: add --noterrain and --noparcel to 'load oar'.
--noterrain suppresses the loading of the terrain from the oar.
--noparcels suppresses the loading of parcel information from the oar.
2014-01-19 11:03:08 -08:00
Robert Adams
dd6db72939 varregion: add --displacement parameter to 'load oar'.
Adds displacment to all objects and terrain loaded from the oar.
As an example, if you have a 512x512 region and an old 256x256 oar, doing
  load oar --displacement "<128,128,0>" oarFile.oar
will load the object (and terrain) into the middle of the 512x512 region.
If displacement is not specified, 'load oar' works like it always has.
If you have a 5
2014-01-19 10:09:43 -08:00
Robert Adams
f127e4b4ee Merge branch 'master' into varregion 2014-01-19 07:38:53 -08:00
Robert Adams
54a4b9eab4 varregion: Update Warp3D to properly handle varregions.
This includes additions to Warp3D:
   Optional rendering of mesh and scupltie prims (INI parameter. Off by default)
   Texturing of large prims (INI parameter. On by default)
   Better garbage collection
2014-01-19 07:33:56 -08:00
Robert Adams
813f0da00b Add J2K decoder routine that converts directly to an image. 2014-01-19 07:32:41 -08:00
Robert Adams
08fa0a6a8a Fix casting error for float type INI file parameter parsing. 2014-01-19 07:26:55 -08:00
Robert Adams
60de0bc3c2 varregion: split up generated maptile images for storage in map. This
makes maps for varregions show up properly.
2014-01-19 05:09:03 -08:00
Robert Adams
cc5cffc212 varregion: properly pack the region size parameters so he viewer will parse them.
This gets rid of the viewer crash when teleporting into varregions and allows
multiple, adjacent varregions (of the same size) with border crossings.
2014-01-11 22:00:52 -08:00
Robert Adams
1eea6fd452 varregion: Debug messages for region crossing debugging. 2014-01-11 22:00:24 -08:00
Robert Adams
3760d10cd0 varregion: remove unnecessary border checking code in ScenePresence. 2014-01-11 21:59:22 -08:00
Robert Adams
1cf17a3cf7 Merge branch 'master' into varregion
Conflicts:
	OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
	OpenSim/Region/Framework/Scenes/SceneBase.cs
	OpenSim/Services/Interfaces/IGridService.cs
	OpenSim/Services/LLLoginService/LLLoginResponse.cs
(conflicts were debug statements that are commented out in master branch)
2014-01-11 08:52:23 -08:00
Robert Adams
fd045d520e Merge branch 'master' into varregion
Conflicts:
	OpenSim/Framework/Constants.cs
	OpenSim/Framework/RegionInfo.cs
	OpenSim/Services/GridService/GridService.cs
	OpenSim/Services/Interfaces/IGridService.cs
Most conflicts had to do with Util routines not in master branch yet.
2014-01-04 08:57:51 -08:00
Robert Adams
9984ecf862 varregion: Add region size to teleport event messages (EnableSimulator,
CorssRegion, TeleportFinishEvent).
Have Simian grid service return the region size.
Many teleport related debug log messages. Can be removed when teleport
works (like that's ever going to happen).
2014-01-03 07:41:06 -08:00
Robert Adams
01c0bbf181 varregion: extract banned region logic into a class for cleanlyness.
Add 'not found' caching in EntityTransferModule.GetRegionContainingWorldLocation
so hitting borders and bad teleports do not continuiously hammer on the GridService.
2013-12-27 08:23:37 -08:00
Robert Adams
2d2bea4aa7 varregion: many more updates removing the constant RegionSize and replacing
with a passed region size. This time in the map code and grid services code.
2013-12-26 22:45:59 -08:00
Robert Adams
e5f7c8b6e8 varregion: add lots of DEBUG level log messages. Especially for teleport. 2013-12-24 12:31:26 -08:00
Robert Adams
b40b57776b varregion: remove unused Scene.HaveNeighbor routine. Its computation
was wrong for large regions anyway.
2013-12-24 12:28:54 -08:00
Robert Adams
5c9fa15f30 varregion: fix bug where destination region is not found and object is
not restored to its original location.
2013-12-24 11:51:50 -08:00
Robert Adams
a01862509e Merge branch 'master' into varregion 2013-12-20 06:52:28 -08:00
Robert Adams
6937eec258 Merge branch 'master' into varregion
Add new region crossing code to varregion

Conflicts:
	OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
2013-12-17 06:18:13 -08:00
Robert Adams
13a9a4b653 varregion: rename 'LegacyRegionLocX' back to 'RegionLocX' and same for Y and Z.
Rename 'RegionWorldLocX' to 'WorldLocX' and same for Y and Z.
This keeps the downward compatibility and follows the scheme of 'region'
and 'world' location naming that is happening in the Util module.
2013-12-14 07:53:01 -08:00
Robert Adams
4eb52eb19e Merge branch 'master' into varregion 2013-12-05 21:07:44 -08:00
Robert Adams
31bacfbb63 Merge branch 'master' into varregion 2013-12-01 15:51:42 -08:00
Robert Adams
6cd0d7a62b varregion: Add MaxRegionSize constant and enforce in RegionInfo.
Intermediate checkin of changing border cross computation from checking
boundry limits to requests to GridService. Not totally functional.
2013-11-30 15:28:39 -08:00
Robert Adams
109136c074 varregion: add ITerrainChannel.GetHeightAtXYZ() for eventual mesh terrain.
Implementation of same in TerrainChannel.cs.
Check for bounds in TerrainChannel[x,y] to prevent array access exceptions.
2013-11-28 08:22:41 -08:00
Robert Adams
7aa00632b9 varregion: many replacements of in-place arithmetic with calls to
the Util functions for converting world addresses to region addresses
and converting region handles to locations.
2013-11-28 08:20:16 -08:00
Robert Adams
3193bcaae1 Merge branch 'master' into varregion 2013-11-24 07:23:12 -08:00
Robert Adams
604b39cea9 Merge branch 'master' into varregion 2013-11-15 14:56:13 -08:00
Robert Adams
d67236c09d Merge branch 'master' into varregion 2013-11-13 16:10:25 -08:00
Robert Adams
e2a1fa806d varregion: extend TerrainModule to use the region size from RegionInfo
rather than using Constants.RegionSize. This allows loading and saving
of terrain heightmaps that match the size of non-legacy sized regions.
2013-11-10 21:12:17 -08:00
Robert Adams
c12e68e34d varregion: fix GetLandObject error return and initialization of square
land object bitmaps. This fixes creation of child presences and the
editing of parcels.
Also lots of commented out debugging messages.
2013-11-10 19:52:31 -08:00
Robert Adams
7061784cc6 Merge branch 'master' into varregion 2013-11-08 20:55:28 -08:00
Robert Adams
beeec1c467 varregion: elimination of Constants.RegionSize from all over OpenSimulator.
Routines in Util to compute region world coordinates from region coordinates
as well as the conversion to and from region handles. These routines have
replaced a lot of math scattered throughout the simulator.
Should be no functional changes.
2013-11-08 20:53:37 -08:00
Robert Adams
a7a837550e varregion: Massive work to LandManagementModule and LandObject to
handle variable sized regions. Many changes for both the region and parcels.
Most of the constant "4" (for the 4x4 parcel units) have been replaced
with symbols and math.
2013-11-08 20:51:09 -08:00
Robert Adams
f7bd0da026 Merge branch 'master' into varregion 2013-11-06 06:32:11 -08:00
Robert Adams
a75ce7423c Merge branch 'master' into varregion 2013-11-05 21:42:27 -08:00
Robert Adams
d0854e4ace varregion: properly sense size of terrain heightmap and store as
compressed 2D database blob if a varregion.
2013-11-05 21:33:02 -08:00
Robert Adams
c931b16c1f Merge branch 'master' into varregion 2013-11-04 22:12:57 -08:00
Robert Adams
f2810bf03a varregion: add plumbing to pass region size from Scene down to the
physics engine.
Older physics engines will default to the legacy region size.
Update BulletSim to use the new region size information.
2013-11-04 22:10:54 -08:00
Robert Adams
cd1a23fc14 varregion: remove uses of region size constant. In particular, update scene
to check for border crossings based on the size of the region.
2013-11-04 22:09:52 -08:00
Robert Adams
ac94dc8a14 varregion: remove unused terrain serialization code in SQLite and PGSQL modules 2013-11-04 22:06:20 -08:00
Robert Adams
9bf363e9be varregion: send the proper terrain patch layer code for large terrain.
Code cleanups.
2013-11-03 08:14:51 -08:00
Robert Adams
79b031bd0c varregion: send region size in LLLoginResponse. 2013-11-02 15:42:26 -07:00
Robert Adams
6df7d4219d varregion: add linkage for region size in creations and conversions
of GridRegion. New variables for size and code to initialize same.
2013-11-02 15:40:48 -07:00
Robert Adams
f66737fe56 varregion: Enforce the configuration of square regions in RegionInfo.cs. 2013-11-02 15:36:16 -07:00
Robert Adams
92c06a5d0b varregion: fix lawn-mower terrain fill so it works for non-square regions.
Add some debugging logs on region creation to report region size.
2013-11-01 16:37:27 -07:00
Robert Adams
976530569a varregion: enforce multiple of 256 for region size when parameters fetched from user.
Output info and warning messages for non-legacy region sizes.
2013-11-01 16:06:19 -07:00
Robert Adams
ff5885ab23 varregion: push TerrainData implementation up and down the database storage stack.
Implement both LoadTerrain and StoreTerrain for all DBs.
Move all database blob serialization/deserialization into TerrainData.
2013-11-01 11:35:31 -07:00
Robert Adams
39777db8ef varregion: fix problem of X/Y dimensions swapped and incorrect terrain
compression base computation.
Complete replacement of float[] for terrain heightmap with TerrainData instance.
2013-10-31 09:24:06 -07:00
Robert Adams
2be0347f50 Merge branch 'master' into varregion 2013-10-28 09:30:26 -07:00
Robert Adams
c581506058 varregion: update PGSQL driver for storing variable terrain size blobs. 2013-10-16 08:13:06 -07:00
Robert Adams
8937a2244d Merge branch 'master' into varregion 2013-10-16 07:53:44 -07:00
Robert Adams
97bc5263de varregion: move the compressed heighmap compression factor from
Constants into TerrainData.
Save compression factor with the terrain blob in the database.
2013-10-16 07:52:30 -07:00
Robert Adams
86bf79aa2b Merge branch 'master' into varregion 2013-10-07 13:58:17 -07:00
Robert Adams
7416809077 varregion: plug in TerrainData class and modify TerrainModule and LLClientView to use same. This passes a terrain info class around rather than passing a one dimensional array thus allowing variable regions. Update the database storage for variable region sizes. This should be downward compatible (same format for 256x256 regions). 2013-10-07 13:57:40 -07:00
Robert Adams
25ae59b9eb varregion: remove scattered use of Constants.RegionSize by having routines reference RegionInfo.RegionWorldLoc?. 2013-10-07 13:57:30 -07:00
Robert Adams
9b150194f6 varregion: add new TerrainData and TerrainCompressor routines. TerrainCompressor needed to replace the one in libopenmetaverse that doesn't know about the larger terrain packets. 2013-10-07 13:57:16 -07:00
Robert Adams
8c432c7c9b Merge branch 'varregion' of git://opensimulator.org/git/opensim into varregion 2013-09-28 07:35:30 -07:00
Robert Adams
8c1d80fdfd varregion: serious rework of TerrainChannel:
-- addition of varaible region size in X and Y
    -- internal storage of heightmap changed from double[] to short[]
    -- helper routines for handling internal structure while keeping existing API
    -- to and from XML that adds region size information (for downward compatibility,
        output in the legacy XML format if X and Y are 256)
Updated and commented Constants.RegionSize but didn't change the name for compatibility.
2013-09-28 07:33:56 -07:00
Robert Adams
aea5d3a842 Remove time based terrain storage in SQLite so revision number can be used
to denote terrain format revision.
Add terrain DB format revision codes to ISimulationDataStore.cs.
Setup so legacy compatible terrain storage and fetch is possible while
allowing future format extensions.
2013-09-28 07:33:55 -07:00
Robert Adams
fa1c688342 varregion: go back to using Constants.RegionSize so as not to break
external modules. People shouldn't use it but don't want to cause
too much breakage of legacy modules.
2013-09-28 07:33:54 -07:00
Robert Adams
139639d25e VarRegion: add RegionSize[XYZ] to RegionInfo.cs.
Update RegionInfo parameter and serialization routines to serialize
the region size if it is not the LegacyRegionSize.
2013-09-28 07:33:53 -07:00
Robert Adams
317c04fe17 VarRegion: change RegionInfo storage of region coordinates from region
count number to integer world coordinates.
Added new methods RegionWorldLoc[XY].
Refactored name of 'RegionLoc*' to 'LegacyRegionLoc*' throughout OpenSim.
Kept old 'RegionLoc*' entrypoint to RegionInfo for downward compatability
of external region management packages.
2013-09-28 07:33:52 -07:00
Robert Adams
fbc9072a5c varregion: serious rework of TerrainChannel:
-- addition of varaible region size in X and Y
    -- internal storage of heightmap changed from double[] to short[]
    -- helper routines for handling internal structure while keeping existing API
    -- to and from XML that adds region size information (for downward compatibility,
        output in the legacy XML format if X and Y are 256)
Updated and commented Constants.RegionSize but didn't change the name for compatibility.
2013-09-25 17:30:53 -07:00
Robert Adams
7fa64cce7d Remove time based terrain storage in SQLite so revision number can be used
to denote terrain format revision.
Add terrain DB format revision codes to ISimulationDataStore.cs.
Setup so legacy compatible terrain storage and fetch is possible while
allowing future format extensions.
2013-09-25 17:30:51 -07:00
Robert Adams
ab1474b5de varregion: go back to using Constants.RegionSize so as not to break
external modules. People shouldn't use it but don't want to cause
too much breakage of legacy modules.
2013-09-25 17:30:49 -07:00
Robert Adams
0765a83a8c VarRegion: add RegionSize[XYZ] to RegionInfo.cs.
Update RegionInfo parameter and serialization routines to serialize
the region size if it is not the LegacyRegionSize.
2013-09-25 17:30:47 -07:00
Robert Adams
96abbbb6fb VarRegion: change RegionInfo storage of region coordinates from region
count number to integer world coordinates.
Added new methods RegionWorldLoc[XY].
Refactored name of 'RegionLoc*' to 'LegacyRegionLoc*' throughout OpenSim.
Kept old 'RegionLoc*' entrypoint to RegionInfo for downward compatability
of external region management packages.
2013-09-25 17:30:45 -07:00
120 changed files with 5469 additions and 2232 deletions

View File

@@ -1022,7 +1022,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// Set home position
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
(int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
(int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation));
if (null == home)
{
m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", firstName, lastName);
@@ -1252,7 +1252,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
if ((null != regionXLocation) && (null != regionYLocation))
{
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
(int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
(int)Util.RegionToWorldLoc((uint)regionXLocation), (int)Util.RegionToWorldLoc((uint)regionYLocation));
if (null == home) {
m_log.WarnFormat("[RADMIN]: Unable to set home region for updated user account {0} {1}", firstName, lastName);
} else {
@@ -1484,8 +1484,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
}
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
Dictionary<string, object> archiveOptions = new Dictionary<string,object>();
if (mergeOar) archiveOptions.Add("merge", null);
if (skipAssets) archiveOptions.Add("skipAssets", null);
if (archiver != null)
archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty);
archiver.DearchiveRegion(filename, Guid.Empty, archiveOptions);
else
throw new Exception("Archiver module not present for scene");
@@ -2881,7 +2884,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// Set home position
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
(int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
(int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation));
if (null == home) {
m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", names[0], names[1]);
} else {

View File

@@ -54,12 +54,12 @@ namespace OpenSim.Data
/// <summary>
/// Return the x-coordinate of this region.
/// </summary>
public int coordX { get { return posX / (int)Constants.RegionSize; } }
public int coordX { get { return (int)Util.WorldToRegionLoc((uint)posX); } }
/// <summary>
/// Return the y-coordinate of this region.
/// </summary>
public int coordY { get { return posY / (int)Constants.RegionSize; } }
public int coordY { get { return (int)Util.WorldToRegionLoc((uint)posY); } }
public Dictionary<string, object> Data;
}

View File

@@ -49,6 +49,7 @@ namespace OpenSim.Data.MSSQL
// private static FileSystemDataStore Instance = new FileSystemDataStore();
private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[REGION DB MSSQL]";
/// <summary>
/// The database manager
@@ -530,43 +531,53 @@ ELSE
/// <returns></returns>
public double[,] LoadTerrain(UUID regionID)
{
double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
terrain.Initialize();
double[,] ret = null;
TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
if (terrData != null)
ret = terrData.GetDoubles();
return ret;
}
// Returns 'null' if region not found
public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
{
TerrainData terrData = null;
string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
// MySqlParameter param = new MySqlParameter();
cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
int rev;
if (reader.Read())
// MySqlParameter param = new MySqlParameter();
cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
BinaryReader br = new BinaryReader(str);
for (int x = 0; x < (int)Constants.RegionSize; x++)
int rev;
if (reader.Read())
{
for (int y = 0; y < (int)Constants.RegionSize; y++)
{
terrain[x, y] = br.ReadDouble();
}
rev = (int)reader["Revision"];
byte[] blob = (byte[])reader["Heightfield"];
terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
rev = (int)reader["Revision"];
else
{
_Log.Info("[REGION DB]: No terrain found for region");
return null;
}
_Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
else
{
_Log.Info("[REGION DB]: No terrain found for region");
return null;
}
_Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
}
return terrain;
return terrData;
}
// Legacy entry point for when terrain was always a 256x256 hieghtmap
public void StoreTerrain(double[,] ter, UUID regionID)
{
StoreTerrain(new HeightmapTerrainData(ter), regionID);
}
/// <summary>
@@ -574,10 +585,8 @@ ELSE
/// </summary>
/// <param name="terrain">terrain map data.</param>
/// <param name="regionID">regionID.</param>
public void StoreTerrain(double[,] terrain, UUID regionID)
public void StoreTerrain(TerrainData terrData, UUID regionID)
{
int revision = Util.UnixTimeSinceEpoch();
//Delete old terrain map
string sql = "delete from terrain where RegionUUID=@RegionUUID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
@@ -590,17 +599,23 @@ ELSE
sql = "insert into terrain(RegionUUID, Revision, Heightfield) values(@RegionUUID, @Revision, @Heightfield)";
int terrainDBRevision;
Array terrainDBblob;
terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
cmd.Parameters.Add(_Database.CreateParameter("@Revision", revision));
cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", serializeTerrain(terrain)));
conn.Open();
cmd.ExecuteNonQuery();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
cmd.Parameters.Add(_Database.CreateParameter("@Revision", terrainDBRevision));
cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", terrainDBblob));
conn.Open();
cmd.ExecuteNonQuery();
}
}
_Log.Info("[REGION DB]: Stored terrain revision r " + revision);
_Log.InfoFormat("{0} Stored terrain revision r={1}", LogHeader, terrainDBRevision);
}
/// <summary>
@@ -1344,30 +1359,6 @@ VALUES
#region Private Methods
/// <summary>
/// Serializes the terrain data for storage in DB.
/// </summary>
/// <param name="val">terrain data</param>
/// <returns></returns>
private static Array serializeTerrain(double[,] val)
{
MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) * sizeof(double));
BinaryWriter bw = new BinaryWriter(str);
// TODO: COMPATIBILITY - Add byte-order conversions
for (int x = 0; x < (int)Constants.RegionSize; x++)
for (int y = 0; y < (int)Constants.RegionSize; y++)
{
double height = val[x, y];
if (height == 0.0)
height = double.Epsilon;
bw.Write(height);
}
return str.ToArray();
}
/// <summary>
/// Stores new regionsettings.
/// </summary>

View File

@@ -48,6 +48,7 @@ namespace OpenSim.Data.MySQL
public class MySQLSimulationData : ISimulationDataStore
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[REGION DB MYSQL]";
private string m_connectionString;
private object m_dbLock = new object();
@@ -91,7 +92,7 @@ namespace OpenSim.Data.MySQL
}
catch (Exception e)
{
m_log.Error("[REGION DB]: MySQL error in ExecuteReader: " + e.Message);
m_log.ErrorFormat("{0} MySQL error in ExecuteReader: {1}", LogHeader, e);
throw;
}
@@ -572,10 +573,14 @@ namespace OpenSim.Data.MySQL
}
}
// Legacy entry point for when terrain was always a 256x256 hieghtmap
public void StoreTerrain(double[,] ter, UUID regionID)
{
m_log.Info("[REGION DB]: Storing terrain");
StoreTerrain(new HeightmapTerrainData(ter), regionID);
}
public void StoreTerrain(TerrainData terrData, UUID regionID)
{
lock (m_dbLock)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
@@ -589,11 +594,18 @@ namespace OpenSim.Data.MySQL
ExecuteNonQuery(cmd);
cmd.CommandText = "insert into terrain (RegionUUID, " +
"Revision, Heightfield) values (?RegionUUID, " +
"1, ?Heightfield)";
cmd.Parameters.AddWithValue("Heightfield", SerializeTerrain(ter));
int terrainDBRevision;
Array terrainDBblob;
terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
m_log.InfoFormat("{0} Storing terrain. X={1}, Y={2}, rev={3}",
LogHeader, terrData.SizeX, terrData.SizeY, terrainDBRevision);
cmd.CommandText = "insert into terrain (RegionUUID, Revision, Heightfield)"
+ "values (?RegionUUID, ?Revision, ?Heightfield)";
cmd.Parameters.AddWithValue("Revision", terrainDBRevision);
cmd.Parameters.AddWithValue("Heightfield", terrainDBblob);
ExecuteNonQuery(cmd);
}
@@ -601,9 +613,20 @@ namespace OpenSim.Data.MySQL
}
}
// Legacy region loading
public double[,] LoadTerrain(UUID regionID)
{
double[,] terrain = null;
double[,] ret = null;
TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
if (terrData != null)
ret = terrData.GetDoubles();
return ret;
}
// Returns 'null' if region not found
public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
{
TerrainData terrData = null;
lock (m_dbLock)
{
@@ -623,32 +646,15 @@ namespace OpenSim.Data.MySQL
while (reader.Read())
{
int rev = Convert.ToInt32(reader["Revision"]);
terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
terrain.Initialize();
using (MemoryStream mstr = new MemoryStream((byte[])reader["Heightfield"]))
{
using (BinaryReader br = new BinaryReader(mstr))
{
for (int x = 0; x < (int)Constants.RegionSize; x++)
{
for (int y = 0; y < (int)Constants.RegionSize; y++)
{
terrain[x, y] = br.ReadDouble();
}
}
}
m_log.InfoFormat("[REGION DB]: Loaded terrain revision r{0}", rev);
}
byte[] blob = (byte[])reader["Heightfield"];
terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
}
}
}
}
return terrain;
return terrData;
}
public void RemoveLandObject(UUID globalID)
@@ -1524,30 +1530,6 @@ namespace OpenSim.Data.MySQL
return entry;
}
/// <summary>
///
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
private static Array SerializeTerrain(double[,] val)
{
MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double));
BinaryWriter bw = new BinaryWriter(str);
// TODO: COMPATIBILITY - Add byte-order conversions
for (int x = 0; x < (int)Constants.RegionSize; x++)
for (int y = 0; y < (int)Constants.RegionSize; y++)
{
double height = val[x, y];
if (height == 0.0)
height = double.Epsilon;
bw.Write(height);
}
return str.ToArray();
}
/// <summary>
/// Fill the prim command with prim values
/// </summary>

View File

@@ -132,15 +132,33 @@ namespace OpenSim.Data.Null
return new List<SceneObjectGroup>();
}
Dictionary<UUID, double[,]> m_terrains = new Dictionary<UUID, double[,]>();
public void StoreTerrain(double[,] ter, UUID regionID)
Dictionary<UUID, TerrainData> m_terrains = new Dictionary<UUID, TerrainData>();
public void StoreTerrain(TerrainData ter, UUID regionID)
{
if (m_terrains.ContainsKey(regionID))
m_terrains.Remove(regionID);
m_terrains.Add(regionID, ter);
}
// Legacy. Just don't do this.
public void StoreTerrain(double[,] ter, UUID regionID)
{
TerrainData terrData = new HeightmapTerrainData(ter);
StoreTerrain(terrData, regionID);
}
// Legacy. Just don't do this.
// Returns 'null' if region not found
public double[,] LoadTerrain(UUID regionID)
{
if (m_terrains.ContainsKey(regionID))
{
return m_terrains[regionID].GetDoubles();
}
return null;
}
public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
{
if (m_terrains.ContainsKey(regionID))
{

View File

@@ -46,6 +46,7 @@ namespace OpenSim.Data.PGSQL
public class PGSQLSimulationData : ISimulationDataStore
{
private const string _migrationStore = "RegionStore";
private const string LogHeader = "[REGION DB PGSQL]";
// private static FileSystemDataStore Instance = new FileSystemDataStore();
private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -523,44 +524,54 @@ namespace OpenSim.Data.PGSQL
/// <returns></returns>
public double[,] LoadTerrain(UUID regionID)
{
double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
terrain.Initialize();
double[,] ret = null;
TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
if (terrData != null)
ret = terrData.GetDoubles();
return ret;
}
// Returns 'null' if region not found
public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
{
TerrainData terrData = null;
string sql = @"select ""RegionUUID"", ""Revision"", ""Heightfield"" from terrain
where ""RegionUUID"" = :RegionUUID order by ""Revision"" desc limit 1; ";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
// PGSqlParameter param = new PGSqlParameter();
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader())
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
int rev;
if (reader.Read())
// PGSqlParameter param = new PGSqlParameter();
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader())
{
MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
BinaryReader br = new BinaryReader(str);
for (int x = 0; x < (int)Constants.RegionSize; x++)
int rev;
if (reader.Read())
{
for (int y = 0; y < (int)Constants.RegionSize; y++)
{
terrain[x, y] = br.ReadDouble();
}
rev = Convert.ToInt32(reader["Revision"]);
byte[] blob = (byte[])reader["Heightfield"];
terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
rev = (int)reader["Revision"];
else
{
_Log.Info("[REGION DB]: No terrain found for region");
return null;
}
_Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
else
{
_Log.Info("[REGION DB]: No terrain found for region");
return null;
}
_Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
}
return terrain;
return terrData;
}
// Legacy entry point for when terrain was always a 256x256 heightmap
public void StoreTerrain(double[,] terrain, UUID regionID)
{
StoreTerrain(new HeightmapTerrainData(terrain), regionID);
}
/// <summary>
@@ -568,35 +579,43 @@ namespace OpenSim.Data.PGSQL
/// </summary>
/// <param name="terrain">terrain map data.</param>
/// <param name="regionID">regionID.</param>
public void StoreTerrain(double[,] terrain, UUID regionID)
public void StoreTerrain(TerrainData terrData, UUID regionID)
{
int revision = Util.UnixTimeSinceEpoch();
//Delete old terrain map
string sql = @"delete from terrain where ""RegionUUID""=:RegionUUID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
conn.Open();
cmd.ExecuteNonQuery();
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
conn.Open();
cmd.ExecuteNonQuery();
_Log.InfoFormat("{0} Deleted terrain revision id = {1}", LogHeader, regionID);
}
}
_Log.Info("[REGION DB]: Deleted terrain revision r " + revision);
int terrainDBRevision;
Array terrainDBblob;
terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
sql = @"insert into terrain(""RegionUUID"", ""Revision"", ""Heightfield"") values(:RegionUUID, :Revision, :Heightfield)";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
cmd.Parameters.Add(_Database.CreateParameter("Revision", revision));
cmd.Parameters.Add(_Database.CreateParameter("Heightfield", serializeTerrain(terrain)));
conn.Open();
cmd.ExecuteNonQuery();
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
cmd.Parameters.Add(_Database.CreateParameter("Revision", terrainDBRevision));
cmd.Parameters.Add(_Database.CreateParameter("Heightfield", terrainDBblob));
conn.Open();
cmd.ExecuteNonQuery();
_Log.InfoFormat("{0} Stored terrain id = {1}, terrainSize = <{2},{3}>",
LogHeader, regionID, terrData.SizeX, terrData.SizeY);
}
}
_Log.Info("[REGION DB]: Stored terrain revision r " + revision);
}
/// <summary>
@@ -1349,30 +1368,6 @@ namespace OpenSim.Data.PGSQL
#region Private Methods
/// <summary>
/// Serializes the terrain data for storage in DB.
/// </summary>
/// <param name="val">terrain data</param>
/// <returns></returns>
private static Array serializeTerrain(double[,] val)
{
MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) * sizeof(double));
BinaryWriter bw = new BinaryWriter(str);
// TODO: COMPATIBILITY - Add byte-order conversions
for (int x = 0; x < (int)Constants.RegionSize; x++)
for (int y = 0; y < (int)Constants.RegionSize; y++)
{
double height = val[x, y];
if (height == 0.0)
height = double.Epsilon;
bw.Write(height);
}
return str.ToArray();
}
/// <summary>
/// Stores new regionsettings.
/// </summary>

View File

@@ -51,6 +51,7 @@ namespace OpenSim.Data.SQLite
public class SQLiteSimulationData : ISimulationDataStore
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[REGION DB SQLLITE]";
private const string primSelect = "select * from prims";
private const string shapeSelect = "select * from primshapes";
@@ -819,45 +820,44 @@ namespace OpenSim.Data.SQLite
prim.Inventory.RestoreInventoryItems(inventory);
}
// Legacy entry point for when terrain was always a 256x256 hieghtmap
public void StoreTerrain(double[,] ter, UUID regionID)
{
StoreTerrain(new HeightmapTerrainData(ter), regionID);
}
/// <summary>
/// Store a terrain revision in region storage
/// </summary>
/// <param name="ter">terrain heightfield</param>
/// <param name="regionID">region UUID</param>
public void StoreTerrain(double[,] ter, UUID regionID)
public void StoreTerrain(TerrainData terrData, UUID regionID)
{
lock (ds)
{
int revision = Util.UnixTimeSinceEpoch();
// This is added to get rid of the infinitely growing
// terrain databases which negatively impact on SQLite
// over time. Before reenabling this feature there
// needs to be a limitter put on the number of
// revisions in the database, as this old
// implementation is a DOS attack waiting to happen.
using (
SqliteCommand cmd =
new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision",
m_conn))
SqliteCommand cmd = new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID", m_conn))
{
cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
cmd.Parameters.Add(new SqliteParameter(":Revision", revision));
cmd.ExecuteNonQuery();
}
// the following is an work around for .NET. The perf
// issues associated with it aren't as bad as you think.
m_log.Debug("[SQLITE REGION DB]: Storing terrain revision r" + revision.ToString());
String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" +
" values(:RegionUUID, :Revision, :Heightfield)";
int terrainDBRevision;
Array terrainDBblob;
terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
m_log.DebugFormat("{0} Storing terrain revision r {1}", LogHeader, terrainDBRevision);
using (SqliteCommand cmd = new SqliteCommand(sql, m_conn))
{
cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
cmd.Parameters.Add(new SqliteParameter(":Revision", revision));
cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter)));
cmd.Parameters.Add(new SqliteParameter(":Revision", terrainDBRevision));
cmd.Parameters.Add(new SqliteParameter(":Heightfield", terrainDBblob));
cmd.ExecuteNonQuery();
}
}
@@ -870,11 +870,20 @@ namespace OpenSim.Data.SQLite
/// <returns>Heightfield data</returns>
public double[,] LoadTerrain(UUID regionID)
{
double[,] ret = null;
TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
if (terrData != null)
ret = terrData.GetDoubles();
return ret;
}
// Returns 'null' if region not found
public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
{
TerrainData terrData = null;
lock (ds)
{
double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
terret.Initialize();
String sql = "select RegionUUID, Revision, Heightfield from terrain" +
" where RegionUUID=:RegionUUID order by Revision desc";
@@ -887,21 +896,9 @@ namespace OpenSim.Data.SQLite
int rev = 0;
if (row.Read())
{
// TODO: put this into a function
using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"]))
{
using (BinaryReader br = new BinaryReader(str))
{
for (int x = 0; x < (int)Constants.RegionSize; x++)
{
for (int y = 0; y < (int)Constants.RegionSize; y++)
{
terret[x, y] = br.ReadDouble();
}
}
}
}
rev = Convert.ToInt32(row["Revision"]);
byte[] blob = (byte[])row["Heightfield"];
terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
else
{
@@ -912,8 +909,8 @@ namespace OpenSim.Data.SQLite
m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString());
}
}
return terret;
}
return terrData;
}
public void RemoveLandObject(UUID globalID)
@@ -2016,40 +2013,6 @@ namespace OpenSim.Data.SQLite
return entry;
}
/// <summary>
///
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
private static Array serializeTerrain(double[,] val)
{
MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) * sizeof(double));
BinaryWriter bw = new BinaryWriter(str);
// TODO: COMPATIBILITY - Add byte-order conversions
for (int x = 0; x < (int)Constants.RegionSize; x++)
for (int y = 0; y < (int)Constants.RegionSize; y++)
bw.Write(val[x, y]);
return str.ToArray();
}
// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val)
// {
// row["RegionUUID"] = regionUUID;
// row["Revision"] = rev;
// MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double));
// BinaryWriter bw = new BinaryWriter(str);
// // TODO: COMPATIBILITY - Add byte-order conversions
// for (int x = 0; x < (int)Constants.RegionSize; x++)
// for (int y = 0; y < (int)Constants.RegionSize; y++)
// bw.Write(val[x, y]);
// row["Heightfield"] = str.ToArray();
// }
/// <summary>
///
/// </summary>

View File

@@ -27,6 +27,7 @@
using System;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Framework
{
@@ -40,9 +41,26 @@ namespace OpenSim.Framework
public byte WaterHeight;
public ushort X;
public ushort Y;
public ushort SizeX;
public ushort SizeY;
public MapBlockData()
{
}
public OSDMap ToOSD()
{
OSDMap map = new OSDMap();
map["X"] = X;
map["Y"] = Y;
map["SizeX"] = SizeX;
map["SizeY"] = SizeY;
map["Name"] = Name;
map["Access"] = Access;
map["RegionFlags"] = RegionFlags;
map["WaterHeight"] = WaterHeight;
map["MapImageID"] = MapImageId;
return map;
}
}
}

View File

@@ -26,6 +26,7 @@
*/
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Framework
{
@@ -37,5 +38,37 @@ namespace OpenSim.Framework
public int Extra;
public int Extra2;
public string name;
public mapItemReply(uint pX, uint pY, UUID pId, string pName, int pExt1, int pExt2)
{
x = pX;
y = pY;
id = pId;
name = pName;
Extra = pExt1;
Extra2 = pExt2;
}
public OSDMap ToOSD()
{
OSDMap map = new OSDMap();
map["X"] = OSD.FromInteger((int)x);
map["Y"] = OSD.FromInteger((int)y);
map["ID"] = OSD.FromUUID(id);
map["Name"] = OSD.FromString(name);
map["Extra"] = OSD.FromInteger(Extra);
map["Extra2"] = OSD.FromInteger(Extra2);
return map;
}
public void FromOSD(OSDMap map)
{
x = (uint) map["X"].AsInteger();
y = (uint) map["Y"].AsInteger();
id = map["ID"].AsUUID();
Extra = map["Extra"].AsInteger();
Extra2 = map["Extra2"].AsInteger();
name = map["Name"].AsString();
}
}
}

View File

@@ -0,0 +1,423 @@
/*
* 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 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.Reflection;
using OpenMetaverse;
using log4net;
namespace OpenSim.Framework
{
public abstract class TerrainData
{
// Terrain always is a square
public int SizeX { get; protected set; }
public int SizeY { get; protected set; }
public int SizeZ { get; protected set; }
// A height used when the user doesn't specify anything
public const float DefaultTerrainHeight = 21f;
public abstract float this[int x, int y] { get; set; }
// Someday terrain will have caves
public abstract float this[int x, int y, int z] { get; set; }
public bool IsTainted { get; protected set; }
public abstract bool IsTaintedAt(int xx, int yy);
public abstract void ClearTaint();
public abstract void ClearLand();
public abstract void ClearLand(float height);
// Return a representation of this terrain for storing as a blob in the database.
// Returns 'true' to say blob was stored in the 'out' locations.
public abstract bool GetDatabaseBlob(out int DBFormatRevisionCode, out Array blob);
// Given a revision code and a blob from the database, create and return the right type of TerrainData.
// The sizes passed are the expected size of the region. The database info will be used to
// initialize the heightmap of that sized region with as much data is in the blob.
// Return created TerrainData or 'null' if unsuccessful.
public static TerrainData CreateFromDatabaseBlobFactory(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob)
{
// For the moment, there is only one implementation class
return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob);
}
// return a special compressed representation of the heightmap in shorts
public abstract short[] GetCompressedMap();
public abstract float CompressionFactor { get; }
public abstract double[,] GetDoubles();
public abstract TerrainData Clone();
}
// The terrain is stored in the database as a blob with a 'revision' field.
// Some implementations of terrain storage would fill the revision field with
// the time the terrain was stored. When real revisions were added and this
// feature removed, that left some old entries with the time in the revision
// field.
// Thus, if revision is greater than 'RevisionHigh' then terrain db entry is
// left over and it is presumed to be 'Legacy256'.
// Numbers are arbitrary and are chosen to to reduce possible mis-interpretation.
// If a revision does not match any of these, it is assumed to be Legacy256.
public enum DBTerrainRevision
{
// Terrain is 'double[256,256]'
Legacy256 = 11,
// Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions
// The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
Variable2D = 22,
// Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions
// and third int is the 'compression factor'. The heights are compressed as
// "short compressedHeight = (short)(height * compressionFactor);"
// The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
Compressed2D = 27,
// A revision that is not listed above or any revision greater than this value is 'Legacy256'.
RevisionHigh = 1234
}
// Version of terrain that is a heightmap.
// This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge
// of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer.
// The heighmap is kept as an array of short integers. The integer values are converted to
// and from floats by TerrainCompressionFactor. Shorts are used to limit storage used.
public class HeightmapTerrainData : TerrainData
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[HEIGHTMAP TERRAIN DATA]";
// TerrainData.this[x, y]
public override float this[int x, int y]
{
get { return FromCompressedHeight(m_heightmap[x, y]); }
set {
short newVal = ToCompressedHeight(value);
if (m_heightmap[x, y] != newVal)
{
m_heightmap[x, y] = newVal;
m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
}
}
}
// TerrainData.this[x, y, z]
public override float this[int x, int y, int z]
{
get { return this[x, y]; }
set { this[x, y] = value; }
}
// TerrainData.ClearTaint
public override void ClearTaint()
{
IsTainted = false;
for (int ii = 0; ii < m_taint.GetLength(0); ii++)
for (int jj = 0; jj < m_taint.GetLength(1); jj++)
m_taint[ii, jj] = false;
}
// TerrainData.ClearLand
public override void ClearLand()
{
ClearLand(DefaultTerrainHeight);
}
// TerrainData.ClearLand(float)
public override void ClearLand(float pHeight)
{
short flatHeight = ToCompressedHeight(pHeight);
for (int xx = 0; xx < SizeX; xx++)
for (int yy = 0; yy < SizeY; yy++)
m_heightmap[xx, yy] = flatHeight;
}
public override bool IsTaintedAt(int xx, int yy)
{
int tx = xx / Constants.TerrainPatchSize;
int ty = yy / Constants.TerrainPatchSize;
bool ret = m_taint[tx, ty];
m_taint[tx, ty] = false;
return ret;
}
// TerrainData.GetDatabaseBlob
// The user wants something to store in the database.
public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
{
bool ret = false;
if (SizeX == Constants.RegionSize && SizeY == Constants.RegionSize)
{
DBRevisionCode = (int)DBTerrainRevision.Legacy256;
blob = ToLegacyTerrainSerialization();
ret = true;
}
else
{
DBRevisionCode = (int)DBTerrainRevision.Compressed2D;
blob = ToCompressedTerrainSerialization();
ret = true;
}
return ret;
}
// TerrainData.CompressionFactor
private float m_compressionFactor = 100.0f;
public override float CompressionFactor { get { return m_compressionFactor; } }
// TerrainData.GetCompressedMap
public override short[] GetCompressedMap()
{
short[] newMap = new short[SizeX * SizeY];
int ind = 0;
for (int xx = 0; xx < SizeX; xx++)
for (int yy = 0; yy < SizeY; yy++)
newMap[ind++] = m_heightmap[xx, yy];
return newMap;
}
// TerrainData.Clone
public override TerrainData Clone()
{
HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
ret.m_heightmap = (short[,])this.m_heightmap.Clone();
return ret;
}
// TerrainData.GetDoubles
public override double[,] GetDoubles()
{
double[,] ret = new double[SizeX, SizeY];
for (int xx = 0; xx < SizeX; xx++)
for (int yy = 0; yy < SizeY; yy++)
ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]);
return ret;
}
// =============================================================
private short[,] m_heightmap;
// Remember subregions of the heightmap that has changed.
private bool[,] m_taint;
// To save space (especially for large regions), keep the height as a short integer
// that is coded as the float height times the compression factor (usually '100'
// to make for two decimal points).
public short ToCompressedHeight(double pHeight)
{
return (short)(pHeight * CompressionFactor);
}
public float FromCompressedHeight(short pHeight)
{
return ((float)pHeight) / CompressionFactor;
}
// To keep with the legacy theme, create an instance of this class based on the
// way terrain used to be passed around.
public HeightmapTerrainData(double[,] pTerrain)
{
SizeX = pTerrain.GetLength(0);
SizeY = pTerrain.GetLength(1);
SizeZ = (int)Constants.RegionHeight;
m_compressionFactor = 100.0f;
m_heightmap = new short[SizeX, SizeY];
for (int ii = 0; ii < SizeX; ii++)
{
for (int jj = 0; jj < SizeY; jj++)
{
m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]);
}
}
// m_log.DebugFormat("{0} new by doubles. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
ClearTaint();
}
// Create underlying structures but don't initialize the heightmap assuming the caller will immediately do that
public HeightmapTerrainData(int pX, int pY, int pZ)
{
SizeX = pX;
SizeY = pY;
SizeZ = pZ;
m_compressionFactor = 100.0f;
m_heightmap = new short[SizeX, SizeY];
m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
// m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
ClearTaint();
ClearLand(0f);
}
public HeightmapTerrainData(short[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
{
m_compressionFactor = pCompressionFactor;
int ind = 0;
for (int xx = 0; xx < SizeX; xx++)
for (int yy = 0; yy < SizeY; yy++)
m_heightmap[xx, yy] = cmap[ind++];
// m_log.DebugFormat("{0} new by compressed map. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
}
// Create a heighmap from a database blob
public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ)
{
switch ((DBTerrainRevision)pFormatCode)
{
case DBTerrainRevision.Compressed2D:
FromCompressedTerrainSerialization(pBlob);
m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
break;
default:
FromLegacyTerrainSerialization(pBlob);
m_log.DebugFormat("{0} HeightmapTerrainData create from legacy serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
break;
}
}
// Just create an array of doubles. Presumes the caller implicitly knows the size.
public Array ToLegacyTerrainSerialization()
{
Array ret = null;
using (MemoryStream str = new MemoryStream((int)Constants.RegionSize * (int)Constants.RegionSize * sizeof(double)))
{
using (BinaryWriter bw = new BinaryWriter(str))
{
for (int xx = 0; xx < Constants.RegionSize; xx++)
{
for (int yy = 0; yy < Constants.RegionSize; yy++)
{
double height = this[xx, yy];
if (height == 0.0)
height = double.Epsilon;
bw.Write(height);
}
}
}
ret = str.ToArray();
}
return ret;
}
// Just create an array of doubles. Presumes the caller implicitly knows the size.
public void FromLegacyTerrainSerialization(byte[] pBlob)
{
// In case database info doesn't match real terrain size, initialize the whole terrain.
ClearLand();
using (MemoryStream mstr = new MemoryStream(pBlob))
{
using (BinaryReader br = new BinaryReader(mstr))
{
for (int xx = 0; xx < (int)Constants.RegionSize; xx++)
{
for (int yy = 0; yy < (int)Constants.RegionSize; yy++)
{
float val = (float)br.ReadDouble();
if (xx < SizeX && yy < SizeY)
m_heightmap[xx, yy] = ToCompressedHeight(val);
}
}
}
ClearTaint();
}
}
// See the reader below.
public Array ToCompressedTerrainSerialization()
{
Array ret = null;
using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(Int16))))
{
using (BinaryWriter bw = new BinaryWriter(str))
{
bw.Write((Int32)DBTerrainRevision.Compressed2D);
bw.Write((Int32)SizeX);
bw.Write((Int32)SizeY);
bw.Write((Int32)CompressionFactor);
for (int yy = 0; yy < SizeY; yy++)
for (int xx = 0; xx < SizeX; xx++)
{
bw.Write((Int16)m_heightmap[xx, yy]);
}
}
ret = str.ToArray();
}
return ret;
}
// Initialize heightmap from blob consisting of:
// int32, int32, int32, int32, int16[]
// where the first int32 is format code, next two int32s are the X and y of heightmap data and
// the forth int is the compression factor for the following int16s
// This is just sets heightmap info. The actual size of the region was set on this instance's
// creation and any heights not initialized by theis blob are set to the default height.
public void FromCompressedTerrainSerialization(byte[] pBlob)
{
Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor;
using (MemoryStream mstr = new MemoryStream(pBlob))
{
using (BinaryReader br = new BinaryReader(mstr))
{
hmFormatCode = br.ReadInt32();
hmSizeX = br.ReadInt32();
hmSizeY = br.ReadInt32();
hmCompressionFactor = br.ReadInt32();
m_compressionFactor = hmCompressionFactor;
// In case database info doesn't match real terrain size, initialize the whole terrain.
ClearLand();
for (int yy = 0; yy < hmSizeY; yy++)
{
for (int xx = 0; xx < hmSizeX; xx++)
{
Int16 val = br.ReadInt16();
if (xx < SizeX && yy < SizeY)
m_heightmap[xx, yy] = val;
}
}
}
ClearTaint();
m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}",
LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor);
}
}
}
}

View File

@@ -160,15 +160,19 @@ namespace OpenSim.Framework
public virtual ulong HomeRegion
{
get
{
return Utils.UIntsToLong(
m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize);
{
return Util.RegionWorldLocToHandle(Util.RegionToWorldLoc(m_homeRegionX), Util.RegionToWorldLoc(m_homeRegionY));
// return Utils.UIntsToLong( m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize);
}
set
{
m_homeRegionX = (uint) (value >> 40);
m_homeRegionY = (((uint) (value)) >> 8);
uint regionWorldLocX, regionWorldLocY;
Util.RegionHandleToWorldLoc(value, out regionWorldLocX, out regionWorldLocY);
m_homeRegionX = Util.WorldToRegionLoc(regionWorldLocX);
m_homeRegionY = Util.WorldToRegionLoc(regionWorldLocY);
// m_homeRegionX = (uint) (value >> 40);
// m_homeRegionY = (((uint) (value)) >> 8);
}
}

View File

@@ -1030,7 +1030,7 @@ namespace OpenSim.Framework
finally
{
if (requestStream != null)
requestStream.Close();
requestStream.Dispose();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
@@ -1183,7 +1183,7 @@ namespace OpenSim.Framework
finally
{
if (requestStream != null)
requestStream.Close();
requestStream.Dispose();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
@@ -1268,4 +1268,4 @@ namespace OpenSim.Framework
return deserial;
}
}
}
}

View File

@@ -266,10 +266,21 @@ namespace OpenSim
SavePrimsXml2);
m_console.Commands.AddCommand("Archiving", false, "load oar",
"load oar [--merge] [--skip-assets] [<OAR path>]",
"load oar [--merge] [--skip-assets]"
+ " [--force-terrain] [--force-parcels]"
+ " [--no-objects]"
+ " [--rotation degrees] [--rotation-center \"<x,y,z>\"]"
+ " [--displacement \"<x,y,z>\"]"
+ " [<OAR path>]",
"Load a region's data from an OAR archive.",
"--merge will merge the OAR with the existing scene." + Environment.NewLine
"--merge will merge the OAR with the existing scene (suppresses terrain and parcel info loading)." + Environment.NewLine
+ "--skip-assets will load the OAR but ignore the assets it contains." + Environment.NewLine
+ "--displacement will add this value to the position of every object loaded" + Environment.NewLine
+ "--force-terrain forces the loading of terrain from the oar (undoes suppression done by --merge)" + Environment.NewLine
+ "--force-parcels forces the loading of parcels from the oar (undoes suppression done by --merge)" + Environment.NewLine
+ "--rotation specified rotation to be applied to the oar. Specified in degrees." + Environment.NewLine
+ "--rotation-center Location (relative to original OAR) to apply rotation. Default is <128,128,0>" + Environment.NewLine
+ "--no-objects suppresses the addition of any objects (good for loading only the terrain)" + Environment.NewLine
+ "The path can be either a filesystem location or a URI."
+ " If this is not given then the command looks for an OAR named region.oar in the current directory.",
LoadOar);

View File

@@ -690,7 +690,8 @@ namespace OpenSim
clientServer = clientNetworkServers;
scene.LoadWorldMap();
scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName);
Vector3 regionExtent = new Vector3(regionInfo.RegionSizeX, regionInfo.RegionSizeY, regionInfo.RegionSizeZ);
scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName, regionExtent);
scene.PhysicsScene.RequestAssetMethod = scene.PhysicsRequestAsset;
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight);
@@ -752,10 +753,10 @@ namespace OpenSim
# region Setup methods
protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier)
protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier, Vector3 regionExtent)
{
return GetPhysicsScene(
m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, Config, osSceneIdentifier);
m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, Config, osSceneIdentifier, regionExtent);
}
/// <summary>

View File

@@ -59,6 +59,7 @@ namespace OpenSim.Region.ClientStack.Linden
public class EventQueueGetModule : IEventQueue, INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[EVENT QUEUE GET MODULE]";
/// <value>
/// Debug level.
@@ -714,7 +715,7 @@ namespace OpenSim.Region.ClientStack.Linden
public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
{
m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>",
"[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
LogHeader, handle, avatarID, regionSizeX, regionSizeY);
OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
Enqueue(item, avatarID);
@@ -724,7 +725,7 @@ namespace OpenSim.Region.ClientStack.Linden
ulong regionHandle, int regionSizeX, int regionSizeY)
{
m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>",
"[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
Enqueue(item, avatarID);
}
@@ -734,8 +735,8 @@ namespace OpenSim.Region.ClientStack.Linden
uint locationID, uint flags, string capsURL,
UUID avatarID, int regionSizeX, int regionSizeY)
{
m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize={3},{4}>",
"[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize=<{3},{4}>",
LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
@@ -747,7 +748,7 @@ namespace OpenSim.Region.ClientStack.Linden
string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
{
m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
"[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
LogHeader, handle, avatarID, regionSizeX, regionSizeY);
OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
capsURL, avatarID, sessionID, regionSizeX, regionSizeY);

View File

@@ -77,8 +77,8 @@ namespace OpenSim.Region.ClientStack.Linden
llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
llsdSimInfo.Add("RegionSizeX", new OSDInteger(regionSizeX));
llsdSimInfo.Add("RegionSizeY", new OSDInteger(regionSizeY));
llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint) regionSizeX));
llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint) regionSizeY));
OSDArray arr = new OSDArray(1);
arr.Add(llsdSimInfo);
@@ -138,8 +138,8 @@ namespace OpenSim.Region.ClientStack.Linden
regionDataMap.Add("SeedCapability", OSD.FromString(capsURL));
regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes()));
regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port));
regionDataMap.Add("RegionSizeX", new OSDInteger(regionSizeX));
regionDataMap.Add("RegionSizeY", new OSDInteger(regionSizeY));
regionDataMap.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
regionDataMap.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
OSDArray regionDataArr = new OSDArray(1);
regionDataArr.Add(regionDataMap);
@@ -166,8 +166,8 @@ namespace OpenSim.Region.ClientStack.Linden
info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
info.Add("RegionSizeX", new OSDInteger(regionSizeX));
info.Add("RegionSizeY", new OSDInteger(regionSizeY));
info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
OSDArray infoArr = new OSDArray();
infoArr.Add(info);

View File

@@ -27,6 +27,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
@@ -53,8 +54,8 @@ namespace OpenSim.Region.ClientStack.Linden
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadBakedTextureModule")]
public class UploadBakedTextureModule : INonSharedRegionModule
{
// private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// For historical reasons this is fixed, but there
@@ -63,39 +64,211 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_scene;
private bool m_persistBakedTextures;
private string m_URL;
private IBakedTextureModule m_BakedTextureModule;
public void Initialise(IConfigSource source)
{
IConfig config = source.Configs["ClientStack.LindenCaps"];
if (config == null)
return;
m_URL = config.GetString("Cap_UploadBakedTexture", string.Empty);
IConfig appearanceConfig = source.Configs["Appearance"];
if (appearanceConfig != null)
m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
}
public void AddRegion(Scene s)
{
m_scene = s;
}
public void RemoveRegion(Scene s)
{
s.EventManager.OnRegisterCaps -= RegisterCaps;
s.EventManager.OnNewPresence -= RegisterNewPresence;
s.EventManager.OnRemovePresence -= DeRegisterPresence;
m_BakedTextureModule = null;
m_scene = null;
}
public void RegionLoaded(Scene s)
{
m_scene.EventManager.OnRegisterCaps += RegisterCaps;
m_scene.EventManager.OnNewPresence += RegisterNewPresence;
m_scene.EventManager.OnRemovePresence += DeRegisterPresence;
}
private void DeRegisterPresence(UUID agentId)
{
ScenePresence presence = null;
if (m_scene.TryGetScenePresence(agentId, out presence))
{
presence.ControllingClient.OnSetAppearance -= CaptureAppearanceSettings;
}
}
private void RegisterNewPresence(ScenePresence presence)
{
presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings;
}
private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
{
int maxCacheitemsLoop = cacheItems.Length;
if (maxCacheitemsLoop > AvatarWearable.MAX_WEARABLES)
{
maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES;
m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES);
}
m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
if (cacheItems.Length > 0)
{
m_log.Debug("[Cacheitems]: " + cacheItems.Length);
for (int iter = 0; iter < maxCacheitemsLoop; iter++)
{
m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
cacheItems[iter].TextureID);
}
ScenePresence p = null;
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p))
{
WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems;
if (existingitems == null)
{
if (m_BakedTextureModule != null)
{
WearableCacheItem[] savedcache = null;
try
{
if (p.Appearance.WearableCacheItemsDirty)
{
savedcache = m_BakedTextureModule.Get(p.UUID);
p.Appearance.WearableCacheItems = savedcache;
p.Appearance.WearableCacheItemsDirty = false;
}
}
/*
* The following Catch types DO NOT WORK with m_BakedTextureModule.Get
* it jumps to the General Packet Exception Handler if you don't catch Exception!
*
catch (System.Net.Sockets.SocketException)
{
cacheItems = null;
}
catch (WebException)
{
cacheItems = null;
}
catch (InvalidOperationException)
{
cacheItems = null;
} */
catch (Exception)
{
// The service logs a sufficient error message.
}
if (savedcache != null)
existingitems = savedcache;
}
}
// Existing items null means it's a fully new appearance
if (existingitems == null)
{
for (int i = 0; i < maxCacheitemsLoop; i++)
{
if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
{
Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
if (face == null)
{
textureEntry.CreateFace(cacheItems[i].TextureIndex);
textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
AppearanceManager.DEFAULT_AVATAR_TEXTURE;
continue;
}
cacheItems[i].TextureID =face.TextureID;
if (m_scene.AssetService != null)
cacheItems[i].TextureAsset =
m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
}
else
{
m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length);
}
}
}
else
{
// for each uploaded baked texture
for (int i = 0; i < maxCacheitemsLoop; i++)
{
if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
{
Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
if (face == null)
{
textureEntry.CreateFace(cacheItems[i].TextureIndex);
textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
AppearanceManager.DEFAULT_AVATAR_TEXTURE;
continue;
}
cacheItems[i].TextureID =
face.TextureID;
}
else
{
m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length);
}
}
for (int i = 0; i < maxCacheitemsLoop; i++)
{
if (cacheItems[i].TextureAsset == null)
{
cacheItems[i].TextureAsset =
m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
}
}
}
p.Appearance.WearableCacheItems = cacheItems;
if (m_BakedTextureModule != null)
{
m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems);
p.Appearance.WearableCacheItemsDirty = true;
}
}
}
}
public void PostInitialise()
{
}
public void Close() { }
public string Name { get { return "UploadBakedTextureModule"; } }
@@ -107,26 +280,23 @@ namespace OpenSim.Region.ClientStack.Linden
public void RegisterCaps(UUID agentID, Caps caps)
{
// UUID capID = UUID.Random();
UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler(
caps, m_scene.AssetService, m_persistBakedTextures);
//caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
if (m_URL == "localhost")
{
caps.RegisterHandler(
caps.RegisterHandler(
"UploadBakedTexture",
new RestStreamHandler(
"POST",
"/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
avatarhandler.UploadBakedTexture,
"UploadBakedTexture",
new RestStreamHandler(
"POST",
"/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
new UploadBakedTextureHandler(
caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture,
"UploadBakedTexture",
agentID.ToString()));
}
else
{
caps.RegisterHandler("UploadBakedTexture", m_URL);
}
agentID.ToString()));
}
}
}
}

View File

@@ -34,11 +34,13 @@ using System.Text;
using System.Threading;
using System.Timers;
using System.Xml;
using log4net;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.Messages.Linden;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Framework.Monitoring;
@@ -48,7 +50,6 @@ using OpenSim.Services.Interfaces;
using Timer = System.Timers.Timer;
using AssetLandmark = OpenSim.Framework.AssetLandmark;
using RegionFlags = OpenMetaverse.RegionFlags;
using Nini.Config;
using System.IO;
using PermissionMask = OpenSim.Framework.PermissionMask;
@@ -307,6 +308,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[LLCLIENTVIEW]";
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
/// <summary>
@@ -323,6 +325,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private readonly byte[] m_channelVersion = Utils.EmptyBytes;
private readonly IGroupsModule m_GroupsModule;
private int m_cachedTextureSerial;
private PriorityQueue m_entityUpdates;
private PriorityQueue m_entityProps;
private Prioritizer m_prioritizer;
@@ -447,7 +450,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// ~LLClientView()
// {
// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode);
// m_log.DebugFormat("{0} Destructor called for {1}, circuit code {2}", LogHeader, Name, CircuitCode);
// }
/// <summary>
@@ -513,9 +516,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// there is some unidentified connection problem, not where we have issues due to deadlock
if (!IsActive && !force)
{
m_log.DebugFormat(
"[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set",
Name, m_scene.Name);
m_log.DebugFormat( "{0} Not attempting to close inactive client {1} in {2} since force flag is not set",
LogHeader, Name, m_scene.Name);
return;
}
@@ -1153,7 +1155,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="map">heightmap</param>
public virtual void SendLayerData(float[] map)
{
Util.FireAndForget(DoSendLayerData, map);
Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData());
}
/// <summary>
@@ -1162,10 +1164,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="o"></param>
private void DoSendLayerData(object o)
{
float[] map = LLHeightFieldMoronize((float[])o);
TerrainData map = (TerrainData)o;
try
{
// Send LayerData in typerwriter pattern
//for (int y = 0; y < 16; y++)
//{
// for (int x = 0; x < 16; x++)
@@ -1175,7 +1178,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//}
// Send LayerData in a spiral pattern. Fun!
SendLayerTopRight(map, 0, 0, 15, 15);
SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1);
}
catch (Exception e)
{
@@ -1183,7 +1186,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2)
{
// Row
for (int i = x1; i <= x2; i++)
@@ -1193,11 +1196,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int j = y1 + 1; j <= y2; j++)
SendLayerData(x2, j, map);
if (x2 - x1 > 0)
if (x2 - x1 > 0 && y2 - y1 > 0)
SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
}
void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
void SendLayerBottomLeft(TerrainData map, int x1, int y1, int x2, int y2)
{
// Row in reverse
for (int i = x2; i >= x1; i--)
@@ -1207,7 +1210,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int j = y2 - 1; j >= y1; j--)
SendLayerData(x1, j, map);
if (x2 - x1 > 0)
if (x2 - x1 > 0 && y2 - y1 > 0)
SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
}
@@ -1229,22 +1232,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// OutPacket(layerpack, ThrottleOutPacketType.Land);
// }
// Legacy form of invocation that passes around a bare data array.
// Just ignore what was passed and use the real terrain info that is part of the scene.
public void SendLayerData(int px, int py, float[] map)
{
SendLayerData(px, py, m_scene.Heightmap.GetTerrainData());
}
/// <summary>
/// Sends a specified patch to a client
/// Sends a terrain packet for the point specified.
/// This is a legacy call that has refarbed the terrain into a flat map of floats.
/// We just use the terrain from the region we know about.
/// </summary>
/// <param name="px">Patch coordinate (x) 0..15</param>
/// <param name="py">Patch coordinate (y) 0..15</param>
/// <param name="map">heightmap</param>
public void SendLayerData(int px, int py, float[] map)
public void SendLayerData(int px, int py, TerrainData terrData)
{
try
{
int[] patches = new int[] { py * 16 + px };
float[] heightmap = (map.Length == 65536) ?
map :
LLHeightFieldMoronize(map);
LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py);
// When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
// To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
@@ -1262,14 +1269,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (m_justEditedTerrain)
{
layerpack.Header.Reliable = false;
OutPacket(layerpack,
ThrottleOutPacketType.Unknown );
OutPacket(layerpack, ThrottleOutPacketType.Unknown );
}
else
{
layerpack.Header.Reliable = true;
OutPacket(layerpack,
ThrottleOutPacketType.Land);
OutPacket(layerpack, ThrottleOutPacketType.Land);
}
}
catch (Exception e)
@@ -1278,38 +1283,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
/// <summary>
/// Munges heightfield into the LLUDP backed in restricted heightfield.
/// </summary>
/// <param name="map">float array in the base; Constants.RegionSize</param>
/// <returns>float array in the base 256</returns>
internal float[] LLHeightFieldMoronize(float[] map)
{
if (map.Length == 65536)
return map;
else
{
float[] returnmap = new float[65536];
if (map.Length < 65535)
{
// rebase the vector stride to 256
for (int i = 0; i < Constants.RegionSize; i++)
Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize);
}
else
{
for (int i = 0; i < 256; i++)
Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
}
//Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
return returnmap;
}
}
/// <summary>
/// Send the wind matrix to the client
/// </summary>
@@ -2785,8 +2758,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
if (req.AssetInf.Data == null)
{
m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null",
req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
m_log.ErrorFormat("{0} Cannot send asset {1} ({2}), asset data is null",
LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
return;
}
@@ -8970,6 +8943,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
if (handlerTeleportLocationRequest != null)
{
// Adjust teleport location to base of a larger region if requested to teleport to a sub-region
uint locX, locY;
Util.RegionHandleToWorldLoc(tpLocReq.Info.RegionHandle, out locX, out locY);
if ((locX >= m_scene.RegionInfo.WorldLocX)
&& (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX))
&& (locY >= m_scene.RegionInfo.WorldLocY)
&& (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) )
{
tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle;
tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX;
tpLocReq.Info.Position.Y += locY - m_scene.RegionInfo.WorldLocY;
}
handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
tpLocReq.Info.LookAt, 16);
}
@@ -11757,36 +11743,158 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <returns></returns>
protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
{
//m_log.Debug("texture cached: " + packet.ToString());
AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
if (cachedtex.AgentData.SessionID != SessionId)
return false;
List<CachedTextureRequestArg> requestArgs = new List<CachedTextureRequestArg>();
for (int i = 0; i < cachedtex.WearableData.Length; i++)
{
CachedTextureRequestArg arg = new CachedTextureRequestArg();
arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex;
arg.WearableHashID = cachedtex.WearableData[i].ID;
requestArgs.Add(arg);
}
// TODO: don't create new blocks if recycling an old packet
cachedresp.AgentData.AgentID = AgentId;
cachedresp.AgentData.SessionID = m_sessionId;
cachedresp.AgentData.SerialNum = m_cachedTextureSerial;
m_cachedTextureSerial++;
cachedresp.WearableData =
new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
try
//IAvatarFactoryModule fac = m_scene.RequestModuleInterface<IAvatarFactoryModule>();
// var item = fac.GetBakedTextureFaces(AgentId);
//WearableCacheItem[] items = fac.GetCachedItems(AgentId);
IAssetService cache = m_scene.AssetService;
IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
//bakedTextureModule = null;
int maxWearablesLoop = cachedtex.WearableData.Length;
if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES)
maxWearablesLoop = AvatarWearable.MAX_WEARABLES;
if (bakedTextureModule != null && cache != null)
{
CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
if (handlerCachedTextureRequest != null)
// We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
WearableCacheItem[] cacheItems = null;
ScenePresence p = m_scene.GetScenePresence(AgentId);
if (p.Appearance != null)
if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty)
{
try
{
cacheItems = bakedTextureModule.Get(AgentId);
p.Appearance.WearableCacheItems = cacheItems;
p.Appearance.WearableCacheItemsDirty = false;
}
/*
* The following Catch types DO NOT WORK, it jumps to the General Packet Exception Handler if you don't catch Exception!
*
catch (System.Net.Sockets.SocketException)
{
cacheItems = null;
}
catch (WebException)
{
cacheItems = null;
}
catch (InvalidOperationException)
{
cacheItems = null;
} */
catch (Exception)
{
cacheItems = null;
}
}
else if (p.Appearance.WearableCacheItems != null)
{
cacheItems = p.Appearance.WearableCacheItems;
}
if (cache != null && cacheItems != null)
{
handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
foreach (WearableCacheItem item in cacheItems)
{
if (cache.GetCached(item.TextureID.ToString()) == null)
{
item.TextureAsset.Temporary = true;
cache.Store(item.TextureAsset);
}
}
}
if (cacheItems != null)
{
for (int i = 0; i < maxWearablesLoop; i++)
{
WearableCacheItem item =
WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems);
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex;
cachedresp.WearableData[i].HostName = new byte[0];
if (item != null && cachedtex.WearableData[i].ID == item.CacheId)
{
cachedresp.WearableData[i].TextureID = item.TextureID;
}
else
{
cachedresp.WearableData[i].TextureID = UUID.Zero;
}
}
}
else
{
for (int i = 0; i < maxWearablesLoop; i++)
{
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
cachedresp.WearableData[i].TextureID = UUID.Zero;
//UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
cachedresp.WearableData[i].HostName = new byte[0];
}
}
}
catch (Exception e)
else
{
m_log.ErrorFormat("[CLIENT VIEW]: AgentTextureCached packet handler threw an exception, {0}", e);
return false;
if (cache == null)
{
for (int i = 0; i < maxWearablesLoop; i++)
{
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
cachedresp.WearableData[i].TextureID = UUID.Zero;
//UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
cachedresp.WearableData[i].HostName = new byte[0];
}
}
else
{
for (int i = 0; i < maxWearablesLoop; i++)
{
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null)
cachedresp.WearableData[i].TextureID = UUID.Zero;
//UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
else
cachedresp.WearableData[i].TextureID = UUID.Zero;
// UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
cachedresp.WearableData[i].HostName = new byte[0];
}
}
}
cachedresp.Header.Zerocoded = true;
OutPacket(cachedresp, ThrottleOutPacketType.Task);
return true;
}

View File

@@ -69,7 +69,7 @@ namespace OpenSim.Region.ClientStack
/// The name of the OpenSim scene this physics scene is serving. This will be used in log messages.
/// </param>
/// <returns></returns>
protected abstract PhysicsScene GetPhysicsScene(string osSceneIdentifier);
protected abstract PhysicsScene GetPhysicsScene(string osSceneIdentifier, Vector3 regionExtent);
protected abstract ClientStackManager CreateClientStackManager();
protected abstract Scene CreateScene(RegionInfo regionInfo, ISimulationDataService simDataService, IEstateDataService estateDataService, AgentCircuitManager circuitManager);
@@ -123,13 +123,13 @@ namespace OpenSim.Region.ClientStack
/// </param>
/// <returns></returns>
protected PhysicsScene GetPhysicsScene(
string engine, string meshEngine, IConfigSource config, string osSceneIdentifier)
string engine, string meshEngine, IConfigSource config, string osSceneIdentifier, Vector3 regionExtent)
{
PhysicsPluginManager physicsPluginManager;
physicsPluginManager = new PhysicsPluginManager();
physicsPluginManager.LoadPluginsFromAssemblies("Physics");
return physicsPluginManager.GetPhysicsScene(engine, meshEngine, config, osSceneIdentifier);
return physicsPluginManager.GetPhysicsScene(engine, meshEngine, config, osSceneIdentifier, regionExtent);
}
}
}

View File

@@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
@@ -182,6 +183,25 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
return DoJ2KDecode(assetID, j2kData, out layers, out components);
}
public Image DecodeToImage(byte[] j2kData)
{
if (m_useCSJ2K)
return J2kImage.FromBytes(j2kData);
else
{
ManagedImage mimage;
Image image;
if (OpenJPEG.DecodeToImage(j2kData, out mimage, out image))
{
mimage = null;
return image;
}
else
return null;
}
}
#endregion IJ2KDecoder
/// <summary>

View File

@@ -0,0 +1,189 @@
/*
* 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 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 OpenMetaverse;
using Nini.Config;
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using log4net;
using OpenSim.Framework;
using OpenSim.Framework.Communications;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using Mono.Addins;
namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XBakes.Module")]
public class XBakesModule : INonSharedRegionModule, IBakedTextureModule
{
protected Scene m_Scene;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private UTF8Encoding enc = new UTF8Encoding();
private string m_URL = String.Empty;
private static XmlSerializer m_serializer = new XmlSerializer(typeof(AssetBase));
public void Initialise(IConfigSource configSource)
{
IConfig config = configSource.Configs["XBakes"];
if (config == null)
return;
m_URL = config.GetString("URL", String.Empty);
}
public void AddRegion(Scene scene)
{
// m_log.InfoFormat("[XBakes]: Enabled for region {0}", scene.RegionInfo.RegionName);
m_Scene = scene;
scene.RegisterModuleInterface<IBakedTextureModule>(this);
}
public void RegionLoaded(Scene scene)
{
}
public void RemoveRegion(Scene scene)
{
}
public void Close()
{
}
public string Name
{
get { return "XBakes.Module"; }
}
public Type ReplaceableInterface
{
get { return null; }
}
public WearableCacheItem[] Get(UUID id)
{
if (m_URL == String.Empty)
return null;
int size = 0;
RestClient rc = new RestClient(m_URL);
List<WearableCacheItem> ret = new List<WearableCacheItem>();
rc.AddResourcePath("bakes");
rc.AddResourcePath(id.ToString());
rc.RequestMethod = "GET";
try
{
Stream s = rc.Request();
XmlTextReader sr = new XmlTextReader(s);
sr.ReadStartElement("BakedAppearance");
while (sr.LocalName == "BakedTexture")
{
string sTextureIndex = sr.GetAttribute("TextureIndex");
int lTextureIndex = Convert.ToInt32(sTextureIndex);
string sCacheId = sr.GetAttribute("CacheId");
UUID lCacheId = UUID.Zero;
if (!(UUID.TryParse(sCacheId, out lCacheId)))
{
// ?? Nothing here
}
++size;
sr.ReadStartElement("BakedTexture");
AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID });
sr.ReadEndElement();
}
m_log.DebugFormat("[XBakes]: Ended reading");
sr.Close();
s.Close();
return ret.ToArray();
}
catch (XmlException e)
{
return null;
}
}
public void Store(UUID agentId, WearableCacheItem[] data)
{
MemoryStream bakeStream = new MemoryStream();
XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null);
bakeWriter.WriteStartElement(String.Empty, "BakedAppearance", String.Empty);
for (int i = 0; i < data.Length; i++)
{
if (data[i] != null)
{
bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
if (data[i].TextureAsset != null)
m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
bakeWriter.WriteEndElement();
}
}
bakeWriter.WriteEndElement();
bakeWriter.Flush();
RestClient rc = new RestClient(m_URL);
rc.AddResourcePath("bakes");
rc.AddResourcePath(agentId.ToString());
rc.RequestMethod = "POST";
MemoryStream reqStream = new MemoryStream(bakeStream.ToArray());
Util.FireAndForget(
delegate
{
rc.Request(reqStream);
}
);
}
}
}

View File

@@ -189,8 +189,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
string message = c.Message;
Scene scene = (Scene)c.Scene;
Vector3 fromPos = c.Position;
Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize,
scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
@@ -342,8 +341,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
{
Vector3 fromRegionPos = fromPos + regionPos;
Vector3 toRegionPos = presence.AbsolutePosition +
new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
new Vector3(presence.Scene.RegionInfo.WorldLocX, presence.Scene.RegionInfo.WorldLocY, 0);
int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);

View File

@@ -667,8 +667,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
Vector3 avaPos = p.AbsolutePosition;
// Getting the global position for the Avatar
Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.WorldLocX + avaPos.X,
remoteClient.Scene.RegionInfo.WorldLocY + avaPos.Y,
avaPos.Z);
string landOwnerName = string.Empty;
@@ -1290,9 +1290,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
webRequest.ContentType = "application/json-rpc";
webRequest.Method = "POST";
Stream dataStream = webRequest.GetRequestStream();
dataStream.Write(content, 0, content.Length);
dataStream.Close();
using (Stream dataStream = webRequest.GetRequestStream())
dataStream.Write(content, 0, content.Length);
WebResponse webResponse = null;
try
@@ -1306,26 +1305,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
return false;
}
Stream rstream = webResponse.GetResponseStream();
OSDMap mret = new OSDMap();
try
using (webResponse)
using (Stream rstream = webResponse.GetResponseStream())
{
mret = (OSDMap)OSDParser.DeserializeJson(rstream);
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
return false;
}
OSDMap mret = (OSDMap)OSDParser.DeserializeJson(rstream);
if (mret.ContainsKey("error"))
return false;
if (mret.ContainsKey("error"))
return false;
// get params...
OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
return true;
// get params...
OSD.DeserializeMembers(ref parameters, (OSDMap)mret["result"]);
return true;
}
}
/// <summary>
@@ -1366,9 +1357,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
webRequest.ContentType = "application/json-rpc";
webRequest.Method = "POST";
Stream dataStream = webRequest.GetRequestStream();
dataStream.Write(content, 0, content.Length);
dataStream.Close();
using (Stream dataStream = webRequest.GetRequestStream())
dataStream.Write(content, 0, content.Length);
WebResponse webResponse = null;
try
@@ -1382,29 +1372,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
return false;
}
Stream rstream = webResponse.GetResponseStream();
OSDMap response = new OSDMap();
try
using (webResponse)
using (Stream rstream = webResponse.GetResponseStream())
{
response = (OSDMap)OSDParser.DeserializeJson(rstream);
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
return false;
}
OSDMap response = new OSDMap();
try
{
response = (OSDMap)OSDParser.DeserializeJson(rstream);
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
return false;
}
if(response.ContainsKey("error"))
{
data = response["error"];
return false;
if (response.ContainsKey("error"))
{
data = response["error"];
return false;
}
data = response;
return true;
}
data = response;
return true;
}
#endregion Web Util
}
}
}

View File

@@ -269,9 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework
foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID])
{
uint x, y;
Utils.LongToUInts(kvp.Key, out x, out y);
x = x / Constants.RegionSize;
y = y / Constants.RegionSize;
Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
}
}

View File

@@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")]
public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
public const int DefaultMaxTransferDistance = 4095;
@@ -121,8 +121,53 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// </summary>
private EntityTransferStateMachine m_entityTransferStateMachine;
private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
// For performance, we keed a cached of banned regions so we don't keep going
// to the grid service.
private class BannedRegionCache
{
private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
ExpiringCache<ulong, DateTime> m_idCache;
DateTime m_banUntil;
public BannedRegionCache()
{
}
// Return 'true' if there is a valid ban entry for this agent in this region
public bool IfBanned(ulong pRegionHandle, UUID pAgentID)
{
bool ret = false;
if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
{
if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil))
{
if (DateTime.Now < m_banUntil)
{
ret = true;
}
}
}
return ret;
}
// Add this agent in this region as a banned person
public void Add(ulong pRegionHandle, UUID pAgentID)
{
if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
{
m_idCache = new ExpiringCache<ulong, DateTime>();
m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45));
}
m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
}
// Remove the agent from the region's banned list
public void Remove(ulong pRegionHandle, UUID pAgentID)
{
if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
{
m_idCache.Remove(pRegionHandle);
}
}
}
private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
private IEventQueue m_eqModule;
private IRegionCombinerModule m_regionCombinerModule;
@@ -337,6 +382,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
"[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name);
}
// Attempt to teleport the ScenePresence to the specified position in the specified region (spec'ed by its handle).
public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
{
if (sp.Scene.Permissions.IsGridGod(sp.UUID))
@@ -434,10 +480,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
float posZLimit = 22;
// TODO: Check other Scene HeightField
if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize)
{
posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
}
posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
float newPosZ = posZLimit + localAVHeight;
if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
@@ -480,9 +523,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
ScenePresence sp, ulong regionHandle, Vector3 position,
Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
{
uint x = 0, y = 0;
Utils.LongToUInts(regionHandle, out x, out y);
GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
// Get destination region taking into account that the address could be an offset
// region inside a varregion.
GridRegion reg = GetTeleportDestinationRegion(sp.Scene.GridService, sp.Scene.RegionInfo.ScopeID, regionHandle, ref position);
if (reg != null)
{
@@ -490,9 +533,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (finalDestination == null)
{
m_log.WarnFormat(
"[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport {0} {1}",
sp.Name, sp.UUID);
m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}",
LogHeader, sp.Name, sp.UUID);
sp.ControllingClient.SendTeleportFailed("Problem at destination");
return;
@@ -533,11 +575,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// and set the map-tile to '(Offline)'
uint regX, regY;
Utils.LongToUInts(regionHandle, out regX, out regY);
Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
MapBlockData block = new MapBlockData();
block.X = (ushort)(regX / Constants.RegionSize);
block.Y = (ushort)(regY / Constants.RegionSize);
block.X = (ushort)regX;
block.Y = (ushort)regY;
block.Access = 254; // == not there
List<MapBlockData> blocks = new List<MapBlockData>();
@@ -546,6 +588,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
}
// The teleport address could be an address in a subregion of a larger varregion.
// Find the real base region and adjust the teleport location to account for the
// larger region.
private GridRegion GetTeleportDestinationRegion(IGridService gridService, UUID scope, ulong regionHandle, ref Vector3 position)
{
uint x = 0, y = 0;
Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
// Compute the world location we're teleporting to
double worldX = (double)x + position.X;
double worldY = (double)y + position.Y;
// Find the region that contains the position
GridRegion reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY);
if (reg != null)
{
// modify the position for the offset into the actual region returned
position.X += x - reg.RegionLocX;
position.Y += y - reg.RegionLocY;
}
return reg;
}
// Nothing to validate here
protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
{
@@ -1349,6 +1416,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (uinfo.HomeRegionID == UUID.Zero)
{
// can't find the Home region: Tell viewer and abort
m_log.ErrorFormat("{0} No grid user info found for {1} {2}. Cannot send home.",
LogHeader, client.Name, client.AgentId);
client.SendTeleportFailed("You don't have a home position set.");
return false;
}
@@ -1382,7 +1451,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Agent Crossings
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos)
// Given a position relative to the current region (which has previously been tested to
// see that it is actually outside the current region), find the new region that the
// point is actually in.
// Returns the coordinates and information of the new region or 'null' of it doesn't exist.
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos)
{
version = String.Empty;
newpos = pos;
@@ -1390,132 +1463,55 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// m_log.DebugFormat(
// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
uint neighbourx = scene.RegionInfo.RegionLocX;
uint neighboury = scene.RegionInfo.RegionLocY;
const float boundaryDistance = 1.7f;
Vector3 northCross = new Vector3(0, boundaryDistance, 0);
Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0);
// Compute world location of the object's position
double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
// distance into new region to place avatar
const float enterDistance = 0.5f;
// Call the grid service to lookup the region containing the new position.
GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
presenceWorldX, presenceWorldY,
Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
if (scene.TestBorderCross(pos + westCross, Cardinals.W))
if (neighbourRegion != null)
{
if (scene.TestBorderCross(pos + northCross, Cardinals.N))
// Compute the entity's position relative to the new region
newpos = new Vector3( (float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
(float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
pos.Z);
if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
{
Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
}
else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
{
neighboury--;
newpos.Y = Constants.RegionSize - enterDistance;
}
neighbourx--;
newpos.X = Constants.RegionSize - enterDistance;
}
else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
{
Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E);
neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
newpos.X = enterDistance;
if (scene.TestBorderCross(pos + southCross, Cardinals.S))
{
neighboury--;
newpos.Y = Constants.RegionSize - enterDistance;
}
else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
{
Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize);
newpos.Y = enterDistance;
}
}
else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
{
Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
neighboury--;
newpos.Y = Constants.RegionSize - enterDistance;
}
else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
{
Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
newpos.Y = enterDistance;
}
/*
if (pos.X < boundaryDistance) //West
{
neighbourx--;
newpos.X = Constants.RegionSize - enterDistance;
}
else if (pos.X > Constants.RegionSize - boundaryDistance) // East
{
neighbourx++;
newpos.X = enterDistance;
}
if (pos.Y < boundaryDistance) // South
{
neighboury--;
newpos.Y = Constants.RegionSize - enterDistance;
}
else if (pos.Y > Constants.RegionSize - boundaryDistance) // North
{
neighboury++;
newpos.Y = enterDistance;
}
*/
xDest = neighbourx;
yDest = neighboury;
int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize);
ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y);
ExpiringCache<ulong, DateTime> r;
DateTime banUntil;
if (m_bannedRegions.TryGetValue(agentID, out r))
{
if (r.TryGetValue(neighbourHandle, out banUntil))
{
if (DateTime.Now < banUntil)
return null;
r.Remove(neighbourHandle);
}
}
else
{
r = null;
}
GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
string reason;
if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
{
if (r == null)
{
r = new ExpiringCache<ulong, DateTime>();
r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45));
neighbourRegion = null;
}
else
{
r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
// If not banned, make sure this agent is not in the list.
m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
}
// Check to see if we have access to the target region.
string reason;
if (neighbourRegion != null
&& !scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
{
// remember banned
m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
neighbourRegion = null;
}
return null;
}
if (neighbourRegion == null)
m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
LogHeader, scene.RegionInfo.RegionName,
scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
pos);
else
m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>",
LogHeader, neighbourRegion.RegionName,
neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
newpos.X, newpos.Y);
return neighbourRegion;
}
@@ -1526,7 +1522,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
Vector3 newpos;
string version;
GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out x, out y, out version, out newpos);
GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out version, out newpos);
if (neighbourRegion == null)
{
agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel");
@@ -1568,7 +1564,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agent.Scene.RequestTeleportLocation(
agent.ControllingClient,
Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize),
Util.RegionLocToHandle(regionX, regionY),
position,
agent.Lookat,
(uint)Constants.TeleportFlags.ViaLocation);
@@ -1578,11 +1574,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (im != null)
{
UUID gotoLocation = Util.BuildFakeParcelID(
Util.UIntsToLong(
(regionX *
(uint)Constants.RegionSize),
(regionY *
(uint)Constants.RegionSize)),
Util.RegionLocToHandle(regionX, regionY),
(uint)(int)position.X,
(uint)(int)position.Y,
(uint)(int)position.Z);
@@ -1635,17 +1627,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
/// </summary>
public ScenePresence CrossAgentToNewRegionAsync(
ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
bool isFlying, string version)
ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
bool isFlying, string version)
{
m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}",
LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos);
if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
{
m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: prep failed. Resetting transfer state", LogHeader);
m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
return agent;
}
if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying))
{
m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader);
m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
return agent;
}
@@ -2038,15 +2035,195 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
}
// Computes the difference between two region bases.
// Returns a vector of world coordinates (meters) from base of first region to the second.
// The first region is the home region of the passed scene presence.
Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
{
int rRegionX = (int)sp.Scene.RegionInfo.RegionLocX;
int rRegionY = (int)sp.Scene.RegionInfo.RegionLocY;
/*
int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
return new Vector3(shiftx, shifty, 0f);
*/
return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
0f);
}
public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
{
// Since we don't know how big the regions could be, we have to search a very large area
// to find possible regions.
return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
}
#region NotFoundLocationCache class
// A collection of not found locations to make future lookups 'not found' lookups quick.
// A simple expiring cache that keeps not found locations for some number of seconds.
// A 'not found' location is presumed to be anywhere in the minimum sized region that
// contains that point. A conservitive estimate.
private class NotFoundLocationCache
{
private struct NotFoundLocation
{
public double minX, maxX, minY, maxY;
public DateTime expireTime;
}
private List<NotFoundLocation> m_notFoundLocations = new List<NotFoundLocation>();
public NotFoundLocationCache()
{
}
// Add an area to the lost of 'not found' places. The area is the snapped region
// area around the added point.
public void Add(double pX, double pY)
{
lock (m_notFoundLocations)
{
if (!LockedContains(pX, pY))
{
NotFoundLocation nfl = new NotFoundLocation();
// A not found location is not found for at least a whole region sized area
nfl.minX = pX - (pX % (double)Constants.RegionSize);
nfl.minY = pY - (pY % (double)Constants.RegionSize);
nfl.maxX = nfl.minX + (double)Constants.RegionSize;
nfl.maxY = nfl.minY + (double)Constants.RegionSize;
nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
m_notFoundLocations.Add(nfl);
}
}
}
// Test to see of this point is in any of the 'not found' areas.
// Return 'true' if the point is found inside the 'not found' areas.
public bool Contains(double pX, double pY)
{
bool ret = false;
lock (m_notFoundLocations)
ret = LockedContains(pX, pY);
return ret;
}
private bool LockedContains(double pX, double pY)
{
bool ret = false;
this.DoExpiration();
foreach (NotFoundLocation nfl in m_notFoundLocations)
{
if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY)
{
ret = true;
break;
}
}
return ret;
}
private void DoExpiration()
{
List<NotFoundLocation> m_toRemove = null;
DateTime now = DateTime.Now;
foreach (NotFoundLocation nfl in m_notFoundLocations)
{
if (nfl.expireTime < now)
{
if (m_toRemove == null)
m_toRemove = new List<NotFoundLocation>();
m_toRemove.Add(nfl);
}
}
if (m_toRemove != null)
{
foreach (NotFoundLocation nfl in m_toRemove)
m_notFoundLocations.Remove(nfl);
m_toRemove.Clear();
}
}
}
#endregion // NotFoundLocationCache class
private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
// Given a world position (fractional meter coordinate), get the GridRegion info for
// the region containing that point.
// Someday this should be a method on GridService.
// 'pSizeHint' is the size of the source region but since the destination point can be anywhere
// the size of the target region is unknown thus the search area might have to be very large.
// Return 'null' if no such region exists.
public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
double px, double py, uint pSizeHint)
{
m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
GridRegion ret = null;
const double fudge = 2.0;
// One problem with this routine is negative results. That is, this can be called lots of times
// for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
// will be quick 'not found's next time.
// NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
// thus re-ask the GridService about the location.
if (m_notFoundLocationCache.Contains(px, py))
{
m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
return null;
}
// As an optimization, since most regions will be legacy sized regions (256x256), first try to get
// the region at the appropriate legacy region location.
uint possibleX = (uint)Math.Floor(px);
possibleX -= possibleX % Constants.RegionSize;
uint possibleY = (uint)Math.Floor(py);
possibleY -= possibleY % Constants.RegionSize;
ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
if (ret != null)
{
m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
LogHeader, possibleX, possibleY, ret.RegionName);
}
if (ret == null)
{
// If the simple lookup failed, search the larger area for a region that contains this point
double range = (double)pSizeHint + fudge;
while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
{
// Get from the grid service a list of regions that might contain this point.
// The region origin will be in the zero direction so only subtract the range.
List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID,
(int)(px - range), (int)(px),
(int)(py - range), (int)(py));
m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
LogHeader, possibleRegions.Count, range);
if (possibleRegions != null && possibleRegions.Count > 0)
{
// If we found some regions, check to see if the point is within
foreach (GridRegion gr in possibleRegions)
{
m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
&& py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
{
// Found a region that contains the point
ret = gr;
m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
break;
}
}
}
// Larger search area for next time around if not found
range *= 2;
}
}
if (ret == null)
{
// remember this location was not found so we can quickly not find it next time
m_notFoundLocationCache.Add(px, py);
m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
}
return ret;
}
private void InformClientOfNeighbourCompleted(IAsyncResult iar)
@@ -2168,16 +2345,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// view to include everything in the megaregion
if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
{
int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance;
// The area to check is as big as the current region.
// We presume all adjacent regions are the same size as this region.
uint dd = Math.Max((uint)avatar.DrawDistance,
Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
int startX = (int)pRegionLocX * (int)Constants.RegionSize - dd + (int)(Constants.RegionSize/2);
int startY = (int)pRegionLocY * (int)Constants.RegionSize - dd + (int)(Constants.RegionSize/2);
uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2;
uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2;
int endX = (int)pRegionLocX * (int)Constants.RegionSize + dd + (int)(Constants.RegionSize/2);
int endY = (int)pRegionLocY * (int)Constants.RegionSize + dd + (int)(Constants.RegionSize/2);
uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2;
uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2;
List<GridRegion> neighbours =
avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
return neighbours;
@@ -2190,10 +2370,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
List<GridRegion> neighbours
= pScene.GridService.GetRegionRange(
m_regionInfo.ScopeID,
(int)swCorner.X * (int)Constants.RegionSize,
(int)neCorner.X * (int)Constants.RegionSize,
(int)swCorner.Y * (int)Constants.RegionSize,
(int)neCorner.Y * (int)Constants.RegionSize);
(int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X),
(int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y) );
neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
@@ -2256,10 +2434,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// Move the given scene object into a new region depending on which region its absolute position has moved
/// into.
///
/// This method locates the new region handle and offsets the prim position for the new region
/// Using the objects new world location, ask the grid service for a the new region and adjust the prim
/// position to be relative to the new region.
/// </summary>
/// <param name="attemptedPosition">the attempted out of region position of the scene object</param>
/// <param name="grp">the scene object that we're crossing</param>
/// <param name="attemptedPosition">the attempted out of region position of the scene object. This position is
/// relative to the region the object currently is in.</param>
/// <param name="silent">if 'true', the deletion of the client from the region is not broadcast to the clients</param>
public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
{
if (grp == null)
@@ -2285,208 +2466,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return;
}
int thisx = (int)scene.RegionInfo.RegionLocX;
int thisy = (int)scene.RegionInfo.RegionLocY;
Vector3 EastCross = new Vector3(0.1f, 0, 0);
Vector3 WestCross = new Vector3(-0.1f, 0, 0);
Vector3 NorthCross = new Vector3(0, 0.1f, 0);
Vector3 SouthCross = new Vector3(0, -0.1f, 0);
// use this if no borders were crossed!
ulong newRegionHandle
= Util.UIntsToLong((uint)((thisx) * Constants.RegionSize),
(uint)((thisy) * Constants.RegionSize));
Vector3 pos = attemptedPosition;
int changeX = 1;
int changeY = 1;
if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W))
{
if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
{
Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
if (crossedBorderx.BorderLine.Z > 0)
{
pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
}
else
pos.X = ((pos.X + Constants.RegionSize));
Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
//(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
if (crossedBordery.BorderLine.Z > 0)
{
pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
}
else
pos.Y = ((pos.Y + Constants.RegionSize));
newRegionHandle
= Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
(uint)((thisy - changeY) * Constants.RegionSize));
// x - 1
// y - 1
}
else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
{
Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
if (crossedBorderx.BorderLine.Z > 0)
{
pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
}
else
pos.X = ((pos.X + Constants.RegionSize));
Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
//(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
if (crossedBordery.BorderLine.Z > 0)
{
pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
}
else
pos.Y = ((pos.Y + Constants.RegionSize));
newRegionHandle
= Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
(uint)((thisy + changeY) * Constants.RegionSize));
// x - 1
// y + 1
}
else
{
Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
if (crossedBorderx.BorderLine.Z > 0)
{
pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
}
else
pos.X = ((pos.X + Constants.RegionSize));
newRegionHandle
= Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
(uint)(thisy * Constants.RegionSize));
// x - 1
}
}
else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E))
{
if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
{
pos.X = ((pos.X - Constants.RegionSize));
Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
//(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
if (crossedBordery.BorderLine.Z > 0)
{
pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
}
else
pos.Y = ((pos.Y + Constants.RegionSize));
newRegionHandle
= Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
(uint)((thisy - changeY) * Constants.RegionSize));
// x + 1
// y - 1
}
else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
{
pos.X = ((pos.X - Constants.RegionSize));
pos.Y = ((pos.Y - Constants.RegionSize));
newRegionHandle
= Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
(uint)((thisy + changeY) * Constants.RegionSize));
// x + 1
// y + 1
}
else
{
pos.X = ((pos.X - Constants.RegionSize));
newRegionHandle
= Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
(uint)(thisy * Constants.RegionSize));
// x + 1
}
}
else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
{
Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
//(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
if (crossedBordery.BorderLine.Z > 0)
{
pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
}
else
pos.Y = ((pos.Y + Constants.RegionSize));
newRegionHandle
= Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize));
// y - 1
}
else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
{
pos.Y = ((pos.Y - Constants.RegionSize));
newRegionHandle
= Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize));
// y + 1
}
// Offset the positions for the new region across the border
// Remember the old group position in case the region lookup fails so position can be restored.
Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
// If we fail to cross the border, then reset the position of the scene object on that border.
uint x = 0, y = 0;
Utils.LongToUInts(newRegionHandle, out x, out y);
GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
// Compute the absolute position of the object.
double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X;
double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y;
// Ask the grid service for the region that contains the passed address
GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
objectWorldLocX, objectWorldLocY);
Vector3 pos = Vector3.Zero;
if (destination != null)
{
if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
return; // we did it
// Adjust the object's relative position from the old region (attemptedPosition)
// to be relative to the new region (pos).
pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX),
(float)(objectWorldLocY - (double)destination.RegionLocY),
attemptedPosition.Z);
}
// no one or failed lets go back and tell physics to go on
oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f);
oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 0.5f, 4096.0f);
if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
{
m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID);
grp.AbsolutePosition = oldGroupPosition;
grp.Velocity = Vector3.Zero;
// We are going to move the object back to the old position so long as the old position
// is in the region
oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1));
oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1));
oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 1.0f, Constants.RegionHeight);
if (grp.RootPart.PhysActor != null)
grp.RootPart.PhysActor.CrossingFailure();
grp.AbsolutePosition = oldGroupPosition;
grp.Velocity = Vector3.Zero;
if (grp.RootPart.PhysActor != null)
grp.RootPart.PhysActor.CrossingFailure();
if (grp.RootPart.KeyframeMotion != null)
grp.RootPart.KeyframeMotion.CrossingFailure();
if (grp.RootPart.KeyframeMotion != null)
grp.RootPart.KeyframeMotion.CrossingFailure();
grp.ScheduleGroupForFullUpdate();
grp.ScheduleGroupForFullUpdate();
}
}
/// <summary>
/// Move the given scene object into a new region
/// </summary>

View File

@@ -77,6 +77,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public class EntityTransferStateMachine
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[ENTITY TRANSFER STATE MACHINE]";
/// <summary>
/// If true then on a teleport, the source region waits for a callback from the destination region. If
@@ -100,6 +101,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// <returns>true if the agent was not already in transit, false if it was</returns>
internal bool SetInTransit(UUID id)
{
m_log.DebugFormat("{0} SetInTransit. agent={1}, newState=Preparing", LogHeader, id);
lock (m_agentsInTransit)
{
if (!m_agentsInTransit.ContainsKey(id))
@@ -121,6 +123,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
internal bool UpdateInTransit(UUID id, AgentTransferState newState)
{
m_log.DebugFormat("{0} UpdateInTransit. agent={1}, newState={2}", LogHeader, id, newState);
bool transitionOkay = false;
// We don't want to throw an exception on cancel since this can come it at any time.
@@ -193,6 +197,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
else if (failIfNotOkay)
{
m_log.DebugFormat("{0} UpdateInTransit. Throwing transition failure = {1}", LogHeader, failureMessage);
throw new Exception(failureMessage);
}
// else

View File

@@ -213,8 +213,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
if (part != null)
{
ObjectRegionName = s.RegionInfo.RegionName;
uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize);
uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize);
uint localX = s.RegionInfo.WorldLocX;
uint localY = s.RegionInfo.WorldLocY;
ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")";
return part;
}

View File

@@ -488,9 +488,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
byte[] data = Util.UTF8.GetBytes(OutboundBody);
Request.ContentLength = data.Length;
Stream bstream = Request.GetRequestStream();
bstream.Write(data, 0, data.Length);
bstream.Close();
using (Stream bstream = Request.GetRequestStream())
bstream.Write(data, 0, data.Length);
}
try
@@ -584,4 +583,4 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
Request.Abort();
}
}
}
}

View File

@@ -48,6 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]";
private IGridService m_GridService;
private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>();
@@ -56,12 +57,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
public LocalGridServicesConnector()
{
m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector no parms.");
m_log.DebugFormat("{0} LocalGridServicesConnector no parms.", LogHeader);
}
public LocalGridServicesConnector(IConfigSource source)
{
m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector instantiated directly.");
m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader);
InitialiseService(source);
}
@@ -192,6 +193,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return m_GridService.GetRegionByUUID(scopeID, regionID);
}
// Get a region given its base coordinates.
// NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
// be the base coordinate of the region.
public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
{
GridRegion region = null;
@@ -206,13 +210,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
region = rcache.GetRegionByPosition(x, y);
if (region != null)
{
return region;
// m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache. Pos=<{2},{3}>",
// LogHeader, region.RegionName, x, y);
break;
}
}
}
// Then try on this sim (may be a lookup in DB if this is using MySql).
return m_GridService.GetRegionByPosition(scopeID, x, y);
if (region == null)
{
region = m_GridService.GetRegionByPosition(scopeID, x, y);
if (region == null)
m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>",
LogHeader, x, y);
else
m_log.DebugFormat("{0} GetRegionByPosition. Requested region {1} from grid service. Pos=<{2},{3}>",
LogHeader, region.RegionName, x, y);
}
return region;
}
public GridRegion GetRegionByName(UUID scopeID, string regionName)
@@ -268,7 +284,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
List<GridRegion> regions = kvp.Value.GetNeighbours();
foreach (GridRegion r in regions)
caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize);
caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
}
}

View File

@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return;
m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}",
m_scene.RegionInfo.RegionName, otherRegion.RegionName, otherRegion.RegionLocX / Constants.RegionSize, otherRegion.RegionLocY / Constants.RegionSize);
m_scene.RegionInfo.RegionName, otherRegion.RegionName, Util.WorldToRegionLoc((uint)otherRegion.RegionLocX), Util.WorldToRegionLoc((uint)otherRegion.RegionLocY));
m_neighbours[otherRegion.RegionHandle] = otherRegion;
}
@@ -82,11 +82,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return new List<GridRegion>(m_neighbours.Values);
}
// Get a region given its base coordinates (in meters).
// NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
// be the base coordinate of the region.
// The snapping is technically unnecessary but is harmless because regions are always
// multiples of the legacy region size (256).
public GridRegion GetRegionByPosition(int x, int y)
{
uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize;
uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize;
ulong handle = Utils.UIntsToLong(xsnap, ysnap);
ulong handle = Util.RegionWorldLocToHandle(xsnap, ysnap);
if (m_neighbours.ContainsKey(handle))
return m_neighbours[handle];

View File

@@ -186,10 +186,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return rinfo;
}
// Get a region given its base world coordinates (in meters).
// NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
// be the base coordinate of the region.
// The coordinates are world coords (meters), NOT region units.
public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
{
bool inCache = false;
GridRegion rinfo = m_RegionInfoCache.Get(scopeID, Util.UIntsToLong((uint)x, (uint)y), out inCache);
GridRegion rinfo = m_RegionInfoCache.Get(scopeID, Util.RegionWorldLocToHandle((uint)x, (uint)y), out inCache);
if (inCache)
return rinfo;

View File

@@ -34,6 +34,7 @@ using log4net.Config;
using Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid;
using OpenSim.Region.Framework.Scenes;
@@ -141,7 +142,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
Assert.IsNotNull(result, "Retrieved GetRegionByUUID is null");
Assert.That(result.RegionID, Is.EqualTo(new UUID(1)), "Retrieved region's UUID does not match");
result = m_LocalConnector.GetRegionByPosition(UUID.Zero, 1000 * (int)Constants.RegionSize, 1000 * (int)Constants.RegionSize);
result = m_LocalConnector.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000));
Assert.IsNotNull(result, "Retrieved GetRegionByPosition is null");
Assert.That(result.RegionLocX, Is.EqualTo(1000 * (int)Constants.RegionSize), "Retrieved region's position does not match");

View File

@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[MAP IMAGE SERVICE MODULE]";
private bool m_enabled = false;
private IMapImageService m_MapService;
@@ -192,42 +193,85 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
///</summary>
private void UploadMapTile(IScene scene)
{
m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName);
m_log.DebugFormat("{0} Upload maptile for {1}", LogHeader, scene.RegionInfo.RegionName);
string regionName = scene.RegionInfo.RegionName;
// Create a JPG map tile and upload it to the AddMapTile API
byte[] jpgData = Utils.EmptyBytes;
IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
if (tileGenerator == null)
{
m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator");
m_log.WarnFormat("{0} Cannot upload map tile without an ImageGenerator", LogHeader);
return;
}
using (Image mapTile = tileGenerator.CreateMapTile())
using (Bitmap mapTile = tileGenerator.CreateMapTile())
{
// XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there
// is no static map tile.
if (mapTile == null)
return;
using (MemoryStream stream = new MemoryStream())
if (mapTile != null)
{
mapTile.Save(stream, ImageFormat.Jpeg);
jpgData = stream.ToArray();
// mapTile.Save( // DEBUG DEBUG
// String.Format("maptiles/raw-{0}-{1}-{2}.jpg", regionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY),
// ImageFormat.Jpeg);
// If the region/maptile is legacy sized, just upload the one tile like it has always been done
if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize)
{
ConvertAndUploadMaptile(mapTile,
scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
scene.RegionInfo.RegionName);
}
else
{
// For larger regions (varregion) we must cut the region image into legacy sized
// pieces since that is how the maptile system works.
// Note the assumption that varregions are always a multiple of legacy size.
for (uint xx = 0; xx < mapTile.Width; xx += Constants.RegionSize)
{
for (uint yy = 0; yy < mapTile.Height; yy += Constants.RegionSize)
{
// Images are addressed from the upper left corner so have to do funny
// math to pick out the sub-tile since regions are numbered from
// the lower left.
Rectangle rect = new Rectangle(
(int)xx,
mapTile.Height - (int)yy - (int)Constants.RegionSize,
(int)Constants.RegionSize, (int)Constants.RegionSize);
using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat))
{
ConvertAndUploadMaptile(subMapTile,
scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize),
scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize),
regionName);
}
}
}
}
}
else
{
m_log.WarnFormat("{0} Tile image generation failed", LogHeader);
}
}
}
if (jpgData == Utils.EmptyBytes)
private void ConvertAndUploadMaptile(Image tileImage, uint locX, uint locY, string regionName)
{
byte[] jpgData = Utils.EmptyBytes;
using (MemoryStream stream = new MemoryStream())
{
m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed");
return;
tileImage.Save(stream, ImageFormat.Jpeg);
jpgData = stream.ToArray();
}
string reason = string.Empty;
if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason))
if (jpgData != Utils.EmptyBytes)
{
m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}",
scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason);
string reason = string.Empty;
if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, out reason))
{
m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader,
regionName, locX, locY, reason);
}
}
else
{
m_log.WarnFormat("{0} Tile image generation failed for region {1}", LogHeader, regionName);
}
}
}

View File

@@ -132,7 +132,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
if (s.RegionInfo.RegionHandle == regionHandle)
{
m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}",
thisRegion.RegionName, s.Name, x / Constants.RegionSize, y / Constants.RegionSize);
thisRegion.RegionName, s.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y) );
//m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour");
return s.IncomingHelloNeighbour(thisRegion);

View File

@@ -96,14 +96,42 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// <value>
/// Should the archive being loaded be merged with what is already on the region?
/// Merging usually suppresses terrain and parcel loading
/// </value>
protected bool m_merge;
/// <value>
/// If true, force the loading of terrain from the oar file
/// </value>
protected bool m_forceTerrain;
/// <value>
/// If true, force the loading of parcels from the oar file
/// </value>
protected bool m_forceParcels;
/// <value>
/// Should we ignore any assets when reloading the archive?
/// </value>
protected bool m_skipAssets;
/// <value>
/// Displacement added to each object as it is added to the world
/// </value>
protected Vector3 m_displacement = Vector3.Zero;
/// <value>
/// Rotation (in radians) to apply to the objects as they are loaded.
/// </value>
protected float m_rotation = 0f;
/// <value>
/// Center around which to apply the rotation relative to the origional oar position
/// </value>
protected Vector3 m_rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f);
protected bool m_noObjects = false;
/// <summary>
/// Used to cache lookups for valid uuids.
/// </summary>
@@ -132,7 +160,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
private IAssetService m_assetService = null;
public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string,object>options)
{
m_rootScene = scene;
@@ -150,9 +178,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
m_errorMessage = String.Empty;
m_merge = merge;
m_skipAssets = skipAssets;
m_merge = options.ContainsKey("merge");
m_forceTerrain = options.ContainsKey("force-terrain");
m_forceParcels = options.ContainsKey("force-parcels");
m_noObjects = options.ContainsKey("no-objects");
m_skipAssets = options.ContainsKey("skipAssets");
m_requestId = requestId;
m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"]
: new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
// Zero can never be a valid user id
m_validUserUuids[UUID.Zero] = false;
@@ -161,13 +196,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_assetService = m_rootScene.AssetService;
}
public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object>options)
{
m_rootScene = scene;
m_loadPath = null;
m_loadStream = loadStream;
m_merge = merge;
m_skipAssets = skipAssets;
m_skipAssets = options.ContainsKey("skipAssets");
m_merge = options.ContainsKey("merge");
m_requestId = requestId;
// Zero can never be a valid user id
@@ -229,7 +264,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Process the file
if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH) && !m_noObjects)
{
sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
}
@@ -243,7 +278,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if ((successfulAssetRestores + failedAssetRestores) % 250 == 0)
m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets...");
}
else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH) && (!m_merge || m_forceTerrain))
{
LoadTerrain(scene, filePath, data);
}
@@ -251,7 +286,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
LoadRegionSettings(scene, filePath, data, dearchivedScenes);
}
else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
else if (filePath.StartsWith(ArchiveConstants.LANDDATA_PATH) && (!m_merge || m_forceParcels))
{
sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
}
@@ -422,6 +457,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Reload serialized prims
m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation);
UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
@@ -445,6 +482,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver
SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
// Happily this does not do much to the object since it hasn't been added to the scene yet
if (sceneObject.AttachmentPoint == 0)
{
if (m_displacement != Vector3.Zero || m_rotation != 0f)
{
Vector3 pos = sceneObject.AbsolutePosition;
if (m_rotation != 0f)
{
// Rotate the object
sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation;
// Get object position relative to rotation axis
Vector3 offset = pos - m_rotationCenter;
// Rotate the object position
offset *= rot;
// Restore the object position back to relative to the region
pos = m_rotationCenter + offset;
}
if (m_displacement != Vector3.Zero)
{
pos += m_displacement;
}
sceneObject.AbsolutePosition = pos;
}
}
bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
// For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
@@ -549,6 +612,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
foreach (string serialisedParcel in serialisedParcels)
{
LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
if (m_displacement != Vector3.Zero)
{
Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f);
parcel.AABBMin += parcelDisp;
parcel.AABBMax += parcelDisp;
}
// Validate User and Group UUID's
@@ -809,7 +879,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
MemoryStream ms = new MemoryStream(data);
terrainModule.LoadFromStream(terrainPath, ms);
if (m_displacement != Vector3.Zero || m_rotation != 0f)
{
Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y);
terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms);
}
else
{
terrainModule.LoadFromStream(terrainPath, ms);
}
ms.Close();
m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath);

View File

@@ -533,7 +533,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (isMegaregion)
size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
else
size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));

View File

@@ -33,11 +33,14 @@ using log4net;
using NDesk.Options;
using Nini.Config;
using Mono.Addins;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
namespace OpenSim.Region.CoreModules.World.Archiver
{
/// <summary>
@@ -101,9 +104,59 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
bool mergeOar = false;
bool skipAssets = false;
bool forceTerrain = false;
bool forceParcels = false;
bool noObjects = false;
Vector3 displacement = new Vector3(0f, 0f, 0f);
float rotation = 0f;
Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0);
OptionSet options = new OptionSet().Add("m|merge", delegate (string v) { mergeOar = v != null; });
options.Add("s|skip-assets", delegate (string v) { skipAssets = v != null; });
OptionSet options = new OptionSet();
options.Add("m|merge", delegate (string v) { mergeOar = (v != null); });
options.Add("s|skip-assets", delegate (string v) { skipAssets = (v != null); });
options.Add("force-terrain", delegate (string v) { forceTerrain = (v != null); });
options.Add("forceterrain", delegate (string v) { forceTerrain = (v != null); }); // downward compatibility
options.Add("force-parcels", delegate (string v) { forceParcels = (v != null); });
options.Add("forceparcels", delegate (string v) { forceParcels = (v != null); }); // downward compatibility
options.Add("no-objects", delegate (string v) { noObjects = (v != null); });
options.Add("displacement=", delegate (string v) {
try
{
displacement = v == null ? Vector3.Zero : Vector3.Parse(v);
}
catch
{
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing displacement");
m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --displacement \"<128,128,0>\"");
return;
}
});
options.Add("rotation=", delegate (string v) {
try
{
rotation = v == null ? 0f : float.Parse(v);
}
catch
{
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation");
m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45");
return;
}
// Convert to radians for internals
rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI;
});
options.Add("rotation-center=", delegate (string v) {
try
{
rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
}
catch
{
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation displacement");
m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --rotation-center \"<128,128,0>\"");
return;
}
});
// Send a message to the region ready module
/* bluewall* Disable this for the time being
@@ -122,13 +175,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// foreach (string param in mainParams)
// m_log.DebugFormat("GOT PARAM [{0}]", param);
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
if (mergeOar) archiveOptions.Add("merge", null);
if (skipAssets) archiveOptions.Add("skipAssets", null);
if (forceTerrain) archiveOptions.Add("force-terrain", null);
if (forceParcels) archiveOptions.Add("force-parcels", null);
if (noObjects) archiveOptions.Add("no-objects", null);
archiveOptions.Add("displacement", displacement);
archiveOptions.Add("rotation", rotation);
archiveOptions.Add("rotation-center", rotationCenter);
if (mainParams.Count > 2)
{
DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty);
DearchiveRegion(mainParams[2], Guid.Empty, archiveOptions);
}
else
{
DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, mergeOar, skipAssets, Guid.Empty);
DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, Guid.Empty, archiveOptions);
}
}
@@ -198,25 +261,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver
public void DearchiveRegion(string loadPath)
{
DearchiveRegion(loadPath, false, false, Guid.Empty);
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
DearchiveRegion(loadPath, Guid.Empty, archiveOptions);
}
public void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId)
public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options)
{
m_log.InfoFormat(
"[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
new ArchiveReadRequest(Scene, loadPath, merge, skipAssets, requestId).DearchiveRegion();
new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion();
}
public void DearchiveRegion(Stream loadStream)
{
DearchiveRegion(loadStream, false, false, Guid.Empty);
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
DearchiveRegion(loadStream, Guid.Empty, archiveOptions);
}
public void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId)
public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options)
{
new ArchiveReadRequest(Scene, loadStream, merge, skipAssets, requestId).DearchiveRegion();
new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion();
}
}
}

View File

@@ -224,8 +224,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
Assert.That(arr.ControlFileLoaded, Is.True);
@@ -308,8 +309,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
Assert.That(arr.ControlFileLoaded, Is.True);
@@ -577,7 +579,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
ArchiveConstants.CONTROL_FILE_PATH,
new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
LandObject lo = new LandObject(groupID, true, null);
LandObject lo = new LandObject(groupID, true, m_scene);
lo.SetLandBitmap(lo.BasicFullRegionLandBitmap());
LandData ld = lo.LandData;
ld.GlobalID = landID;
@@ -752,7 +754,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
byte[] archive = archiveWriteStream.ToArray();
MemoryStream archiveReadStream = new MemoryStream(archive);
m_archiverModule.DearchiveRegion(archiveReadStream, true, false, Guid.Empty);
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
archiveOptions.Add("merge", null);
m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions);
SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name);
Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge");
@@ -860,7 +864,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
Assert.That(arr.ControlFileLoaded, Is.True);

View File

@@ -64,6 +64,7 @@ namespace OpenSim.Region.CoreModules.World.Land
public class LandManagementModule : INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]";
private static readonly string remoteParcelRequestPath = "0009/";
@@ -74,15 +75,11 @@ namespace OpenSim.Region.CoreModules.World.Land
protected IPrimCountModule m_primCountModule;
protected IDialogModule m_Dialog;
// Minimum for parcels to work is 64m even if we don't actually use them.
#pragma warning disable 0429
private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
#pragma warning restore 0429
/// <value>
/// Local land ids at specified region co-ordinates (region size / 4)
/// </value>
private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax];
private int[,] m_landIDList;
private const int landUnit = 4;
/// <value>
/// Land objects keyed by local id
@@ -115,6 +112,8 @@ namespace OpenSim.Region.CoreModules.World.Land
public void AddRegion(Scene scene)
{
m_scene = scene;
m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
m_landIDList.Initialize();
landChannel = new LandChannel(scene, this);
@@ -297,6 +296,7 @@ namespace OpenSim.Region.CoreModules.World.Land
{
m_landList.Clear();
m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
m_landIDList.Initialize();
}
}
@@ -311,7 +311,8 @@ namespace OpenSim.Region.CoreModules.World.Land
"[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
(int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
@@ -438,8 +439,8 @@ namespace OpenSim.Region.CoreModules.World.Land
public void SendLandUpdate(ScenePresence avatar, bool force)
{
ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
(int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
(int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
if (over != null)
{
@@ -605,17 +606,29 @@ namespace OpenSim.Region.CoreModules.World.Land
new_land.LandData.LocalID = newLandLocalID;
bool[,] landBitmap = new_land.GetLandBitmap();
for (int x = 0; x < landArrayMax; x++)
// m_log.DebugFormat("{0} AddLandObject. new_land.bitmapSize=({1},{2}). newLocalID={3}",
// LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), newLandLocalID);
if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
{
for (int y = 0; y < landArrayMax; y++)
// Going to variable sized regions can cause mismatches
m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})",
LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1) );
}
else
{
for (int x = 0; x < landBitmap.GetLength(0); x++)
{
if (landBitmap[x, y])
for (int y = 0; y < landBitmap.GetLength(1); y++)
{
// m_log.DebugFormat(
// "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
// new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
m_landIDList[x, y] = newLandLocalID;
if (landBitmap[x, y])
{
// m_log.DebugFormat(
// "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
// new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
m_landIDList[x, y] = newLandLocalID;
}
}
}
}
@@ -637,9 +650,9 @@ namespace OpenSim.Region.CoreModules.World.Land
ILandObject land;
lock (m_landList)
{
for (int x = 0; x < 64; x++)
for (int x = 0; x < m_landIDList.GetLength(0); x++)
{
for (int y = 0; y < 64; y++)
for (int y = 0; y < m_landIDList.GetLength(1); y++)
{
if (m_landIDList[x, y] == local_id)
{
@@ -691,9 +704,9 @@ namespace OpenSim.Region.CoreModules.World.Land
bool[,] landBitmapSlave = slave.GetLandBitmap();
lock (m_landList)
{
for (int x = 0; x < 64; x++)
for (int x = 0; x < landBitmapSlave.GetLength(0); x++)
{
for (int y = 0; y < 64; y++)
for (int y = 0; y < landBitmapSlave.GetLength(1); y++)
{
if (landBitmapSlave[x, y])
{
@@ -727,23 +740,28 @@ namespace OpenSim.Region.CoreModules.World.Land
/// <returns>Land object at the point supplied</returns>
public ILandObject GetLandObject(float x_float, float y_float)
{
return GetLandObject((int)x_float, (int)y_float, true /* returnNullIfLandObjectNotFound */);
/*
int x;
int y;
if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0)
if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
return null;
try
{
x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0));
y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0));
x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit));
y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit));
}
catch (OverflowException)
{
return null;
}
if (x >= 64 || y >= 64 || x < 0 || y < 0)
if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit)
|| y >= (m_scene.RegionInfo.RegionSizeY / landUnit)
|| x < 0
|| y < 0)
{
return null;
}
@@ -759,38 +777,122 @@ namespace OpenSim.Region.CoreModules.World.Land
// m_log.DebugFormat(
// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}",
// x, y, m_scene.RegionInfo.RegionName);
if (m_landList.ContainsKey(m_landIDList[x, y]))
return m_landList[m_landIDList[x, y]];
try
{
if (m_landList.ContainsKey(m_landIDList[x, y]))
return m_landList[m_landIDList[x, y]];
}
catch (Exception e)
{
m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})",
LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
}
return null;
}
*/
}
// Public entry.
// Throws exception if land object is not found
public ILandObject GetLandObject(int x, int y)
{
if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0)
return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */);
}
// Given a region position, return the parcel land object for that location
private ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectNotFound)
{
ILandObject ret = null;
if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
{
// These exceptions here will cause a lot of complaints from the users specifically because
// they happen every time at border crossings
throw new Exception("Error: Parcel not found at point " + x + ", " + y);
if (returnNullIfLandObjectNotFound)
return null;
else
throw new Exception(
String.Format("{0} GetLandObject for non-existant position. Region={1}, pos=<{2},{3}",
LogHeader, m_scene.RegionInfo.RegionName, x, y)
);
}
lock (m_landIDList)
{
try
{
return m_landList[m_landIDList[x / 4, y / 4]];
int landID = m_landIDList[x / landUnit, y / landUnit];
if (landID == 0)
{
// Zero is the uninitialized value saying there is no parcel for this location.
// This sometimes happens when terrain is resized.
if (m_landList.Count == 1)
{
int onlyParcelID = 0;
ILandObject onlyLandObject = null;
foreach (KeyValuePair<int, ILandObject> kvp in m_landList)
{
onlyParcelID = kvp.Key;
onlyLandObject = kvp.Value;
break;
}
// There is only one parcel. Grow it to fill all the unallocated spaces.
for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
for (int yy = 0; yy < m_landIDList.GetLength(1); yy++)
if (m_landIDList[xx, yy] == 0)
m_landIDList[xx, yy] = onlyParcelID;
onlyLandObject.LandBitmap = CreateBitmapForID(onlyParcelID);
landID = onlyParcelID;
}
else
{
// There are several other parcels so we must create a new one for the unassigned space
ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
// Claim all the unclaimed "0" ids
newLand.SetLandBitmap(CreateBitmapForID(0));
newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
newLand.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
AddLandObject(newLand);
landID = m_lastLandLocalID;
}
}
ret = m_landList[landID];
}
catch (IndexOutOfRangeException)
{
// m_log.WarnFormat(
// "[LAND MANAGEMENT MODULE]: Tried to retrieve land object from out of bounds co-ordinate ({0},{1}) in {2}",
// x, y, m_scene.RegionInfo.RegionName);
m_log.ErrorFormat(
"{0} GetLandObject: Tried to retrieve land object from out of bounds co-ordinate ({1},{2}) in {3}. landListSize=({4},{5})",
LogHeader, x, y, m_scene.RegionInfo.RegionName, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
return null;
}
catch
{
m_log.ErrorFormat(
"{0} GetLandObject: LandID not in landlist. XY=<{1},{2}> in {3}. landID[x,y]={4}",
LogHeader, x, y, m_scene.RegionInfo.RegionName, m_landIDList[x/landUnit, y/landUnit]);
return null;
}
}
return ret;
}
// Create a 'parcel is here' bitmap for the parcel identified by the passed landID
private bool[,] CreateBitmapForID(int landID)
{
bool[,] ret = new bool[m_landIDList.GetLength(0), m_landIDList.GetLength(1)];
ret.Initialize();
for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
for (int yy = 0; yy < m_landIDList.GetLength(0); yy++)
if (m_landIDList[xx, yy] == landID)
ret[xx, yy] = true;
return ret;
}
#endregion
@@ -1053,85 +1155,93 @@ namespace OpenSim.Region.CoreModules.World.Land
byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
int byteArrayCount = 0;
int sequenceID = 0;
int blockmeters = 4 * (int) Constants.RegionSize/(int)Constants.TerrainPatchSize;
for (int y = 0; y < blockmeters; y++)
// Layer data is in landUnit (4m) chunks
for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); y++)
{
for (int x = 0; x < blockmeters; x++)
for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); x++)
{
byte tempByte = 0; //This represents the byte for the current 4x4
ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4);
if (currentParcelBlock != null)
byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * landUnit, y * landUnit), x, y, remote_client);
byteArrayCount++;
if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
{
if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
{
//Owner Flag
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
}
else if (currentParcelBlock.LandData.SalePrice > 0 &&
(currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
{
//Sale Flag
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
}
else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
{
//Public Flag
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
}
else
{
//Other Flag
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
}
//Now for border control
ILandObject westParcel = null;
ILandObject southParcel = null;
if (x > 0)
{
westParcel = GetLandObject((x - 1) * 4, y * 4);
}
if (y > 0)
{
southParcel = GetLandObject(x * 4, (y - 1) * 4);
}
if (x == 0)
{
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
}
else if (westParcel != null && westParcel != currentParcelBlock)
{
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
}
if (y == 0)
{
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
}
else if (southParcel != null && southParcel != currentParcelBlock)
{
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
}
byteArray[byteArrayCount] = tempByte;
byteArrayCount++;
if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
{
remote_client.SendLandParcelOverlay(byteArray, sequenceID);
byteArrayCount = 0;
sequenceID++;
byteArray = new byte[LAND_BLOCKS_PER_PACKET];
}
remote_client.SendLandParcelOverlay(byteArray, sequenceID);
byteArrayCount = 0;
sequenceID++;
byteArray = new byte[LAND_BLOCKS_PER_PACKET];
}
}
}
if (byteArrayCount != 0)
{
remote_client.SendLandParcelOverlay(byteArray, sequenceID);
}
}
private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client)
{
byte tempByte = 0; //This represents the byte for the current 4x4
if (currentParcelBlock != null)
{
if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
{
//Owner Flag
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
}
else if (currentParcelBlock.LandData.SalePrice > 0 &&
(currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
{
//Sale Flag
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
}
else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
{
//Public Flag
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
}
else
{
//Other Flag
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
}
//Now for border control
ILandObject westParcel = null;
ILandObject southParcel = null;
if (x > 0)
{
westParcel = GetLandObject((x - 1) * landUnit, y * landUnit);
}
if (y > 0)
{
southParcel = GetLandObject(x * landUnit, (y - 1) * landUnit);
}
if (x == 0)
{
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
}
else if (westParcel != null && westParcel != currentParcelBlock)
{
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
}
if (y == 0)
{
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
}
else if (southParcel != null && southParcel != currentParcelBlock)
{
tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
}
}
return tempByte;
}
public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
@@ -1679,7 +1789,7 @@ namespace OpenSim.Region.CoreModules.World.Land
{
// most likely still cached from building the extLandData entry
uint x = 0, y = 0;
Utils.LongToUInts(data.RegionHandle, out x, out y);
Util.RegionHandleToWorldLoc(data.RegionHandle, out x, out y);
info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
}
// we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
@@ -2007,4 +2117,4 @@ namespace OpenSim.Region.CoreModules.World.Land
cdl.AddToStringBuilder(report);
}
}
}
}

View File

@@ -45,10 +45,10 @@ namespace OpenSim.Region.CoreModules.World.Land
#region Member Variables
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
#pragma warning disable 0429
private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
#pragma warning restore 0429
private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
private static readonly string LogHeader = "[LAND OBJECT]";
private bool[,] m_landBitmap;
private readonly int landUnit = 4;
private int m_lastSeqId = 0;
@@ -93,15 +93,17 @@ namespace OpenSim.Region.CoreModules.World.Land
{
get
{
for (int y = 0; y < landArrayMax; y++)
for (int y = 0; y < LandBitmap.GetLength(1); y++)
{
for (int x = 0; x < landArrayMax; x++)
for (int x = 0; x < LandBitmap.GetLength(0); x++)
{
if (LandBitmap[x, y])
return new Vector3(x * 4, y * 4, 0);
return new Vector3(x * landUnit, y * landUnit, 0);
}
}
m_log.ErrorFormat("{0} StartPoint. No start point found. bitmapSize=<{1},{2}>",
LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
return new Vector3(-1, -1, -1);
}
}
@@ -110,17 +112,19 @@ namespace OpenSim.Region.CoreModules.World.Land
{
get
{
for (int y = landArrayMax - 1; y >= 0; y--)
for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--)
{
for (int x = landArrayMax - 1; x >= 0; x--)
for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--)
{
if (LandBitmap[x, y])
{
return new Vector3(x * 4 + 4, y * 4 + 4, 0);
return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
}
}
}
m_log.ErrorFormat("{0} EndPoint. No end point found. bitmapSize=<{1},{2}>",
LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
return new Vector3(-1, -1, -1);
}
}
@@ -130,6 +134,11 @@ namespace OpenSim.Region.CoreModules.World.Land
public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
{
m_scene = scene;
if (m_scene == null)
m_landBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
else
m_landBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
LandData.OwnerID = owner_id;
if (is_group_owned)
LandData.GroupID = owner_id;
@@ -152,9 +161,9 @@ namespace OpenSim.Region.CoreModules.World.Land
/// <returns>Returns true if the piece of land contains the specified point</returns>
public bool ContainsPoint(int x, int y)
{
if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize)
if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
{
return (LandBitmap[x / 4, y / 4] == true);
return (LandBitmap[x / landUnit, y / landUnit] == true);
}
else
{
@@ -194,7 +203,7 @@ namespace OpenSim.Region.CoreModules.World.Land
else
{
// Normal Calculations
int parcelMax = (int)(((float)LandData.Area / 65536.0f)
int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
* (float)m_scene.RegionInfo.ObjectCapacity
* (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
// TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL!
@@ -211,7 +220,7 @@ namespace OpenSim.Region.CoreModules.World.Land
else
{
//Normal Calculations
int simMax = (int)(((float)LandData.SimwideArea / 65536.0f)
int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
* (float)m_scene.RegionInfo.ObjectCapacity);
return simMax;
}
@@ -224,7 +233,12 @@ namespace OpenSim.Region.CoreModules.World.Land
public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
{
IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
// uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
uint regionFlags = (uint)(RegionFlags.PublicAllowed
| RegionFlags.AllowDirectTeleport
| RegionFlags.AllowParcelChanges
| RegionFlags.AllowVoice );
if (estateModule != null)
regionFlags = estateModule.GetRegionFlags();
@@ -559,8 +573,8 @@ namespace OpenSim.Region.CoreModules.World.Land
try
{
over =
m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)),
Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1)));
m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
}
catch (Exception)
{
@@ -707,15 +721,15 @@ namespace OpenSim.Region.CoreModules.World.Land
/// </summary>
private void UpdateAABBAndAreaValues()
{
int min_x = 64;
int min_y = 64;
int min_x = 10000;
int min_y = 10000;
int max_x = 0;
int max_y = 0;
int tempArea = 0;
int x, y;
for (x = 0; x < 64; x++)
for (x = 0; x < LandBitmap.GetLength(0); x++)
{
for (y = 0; y < 64; y++)
for (y = 0; y < LandBitmap.GetLength(1); y++)
{
if (LandBitmap[x, y] == true)
{
@@ -723,31 +737,31 @@ namespace OpenSim.Region.CoreModules.World.Land
if (min_y > y) min_y = y;
if (max_x < x) max_x = x;
if (max_y < y) max_y = y;
tempArea += 16; //16sqm peice of land
tempArea += landUnit * landUnit; //16sqm peice of land
}
}
}
int tx = min_x * 4;
if (tx > ((int)Constants.RegionSize - 1))
tx = ((int)Constants.RegionSize - 1);
int ty = min_y * 4;
if (ty > ((int)Constants.RegionSize - 1))
ty = ((int)Constants.RegionSize - 1);
int tx = min_x * landUnit;
if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
int ty = min_y * landUnit;
if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
LandData.AABBMin =
new Vector3(
(float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
(float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
tx = max_x * 4;
if (tx > ((int)Constants.RegionSize - 1))
tx = ((int)Constants.RegionSize - 1);
ty = max_y * 4;
if (ty > ((int)Constants.RegionSize - 1))
ty = ((int)Constants.RegionSize - 1);
tx = max_x * landUnit;
if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
ty = max_y * landUnit;
if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
LandData.AABBMax
= new Vector3(
(float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
(float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
LandData.Area = tempArea;
}
@@ -759,20 +773,12 @@ namespace OpenSim.Region.CoreModules.World.Land
/// <summary>
/// Sets the land's bitmap manually
/// </summary>
/// <param name="bitmap">64x64 block representing where this land is on a map</param>
/// <param name="bitmap">block representing where this land is on a map mapped in a 4x4 meter grid</param>
public void SetLandBitmap(bool[,] bitmap)
{
if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
{
//Throw an exception - The bitmap is not 64x64
//throw new Exception("Error: Invalid Parcel Bitmap");
}
else
{
//Valid: Lets set it
LandBitmap = bitmap;
ForceUpdateLandInfo();
}
LandBitmap = bitmap;
// m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
ForceUpdateLandInfo();
}
/// <summary>
@@ -786,15 +792,19 @@ namespace OpenSim.Region.CoreModules.World.Land
public bool[,] BasicFullRegionLandBitmap()
{
return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY);
}
public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
{
bool[,] tempBitmap = new bool[64,64];
// Empty bitmap for the whole region
bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
tempBitmap.Initialize();
// Fill the bitmap square area specified by state and end
tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
// m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>",
// LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1));
return tempBitmap;
}
@@ -811,24 +821,20 @@ namespace OpenSim.Region.CoreModules.World.Land
public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
bool set_value)
{
if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
{
//Throw an exception - The bitmap is not 64x64
//throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
}
int x, y;
for (y = 0; y < 64; y++)
for (y = 0; y < land_bitmap.GetLength(1); y++)
{
for (x = 0; x < 64; x++)
for (x = 0; x < land_bitmap.GetLength(0); x++)
{
if (x >= start_x / 4 && x < end_x / 4
&& y >= start_y / 4 && y < end_y / 4)
if (x >= start_x / landUnit && x < end_x / landUnit
&& y >= start_y / landUnit && y < end_y / landUnit)
{
land_bitmap[x, y] = set_value;
}
}
}
// m_log.DebugFormat("{0} ModifyLandBitmapSquare. startXY=<{1},{2}>, endXY=<{3},{4}>, val={5}, landBitmapSize=<{6},{7}>",
// LogHeader, start_x, start_y, end_x, end_y, set_value, land_bitmap.GetLength(0), land_bitmap.GetLength(1));
return land_bitmap;
}
@@ -840,21 +846,21 @@ namespace OpenSim.Region.CoreModules.World.Land
/// <returns></returns>
public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
{
if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
|| bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
|| bitmap_add.Rank != 2
|| bitmap_base.Rank != 2)
{
//Throw an exception - The bitmap is not 64x64
throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
}
if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
{
//Throw an exception - The bitmap is not 64x64
throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
throw new Exception(
String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
);
}
int x, y;
for (y = 0; y < 64; y++)
for (y = 0; y < bitmap_base.GetLength(1); y++)
{
for (x = 0; x < 64; x++)
for (x = 0; x < bitmap_add.GetLength(0); x++)
{
if (bitmap_add[x, y])
{
@@ -871,13 +877,13 @@ namespace OpenSim.Region.CoreModules.World.Land
/// <returns></returns>
private byte[] ConvertLandBitmapToBytes()
{
byte[] tempConvertArr = new byte[512];
byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
byte tempByte = 0;
int x, y, i, byteNum = 0;
i = 0;
for (y = 0; y < 64; y++)
int byteNum = 0;
int i = 0;
for (int y = 0; y < LandBitmap.GetLength(1); y++)
{
for (x = 0; x < 64; x++)
for (int x = 0; x < LandBitmap.GetLength(0); x++)
{
tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
if (i % 8 == 0)
@@ -889,30 +895,52 @@ namespace OpenSim.Region.CoreModules.World.Land
}
}
}
// m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>",
// LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
return tempConvertArr;
}
private bool[,] ConvertBytesToLandBitmap()
{
bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax];
bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
tempConvertMap.Initialize();
byte tempByte = 0;
int x = 0, y = 0, i = 0, bitNum = 0;
for (i = 0; i < 512; i++)
// Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
if (bitmapLen == 512)
{
// Legacy bitmap being passed in. Use the legacy region size
// and only set the lower area of the larger region.
xLen = (int)(Constants.RegionSize / landUnit);
}
// m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
int x = 0, y = 0;
for (int i = 0; i < bitmapLen; i++)
{
tempByte = LandData.Bitmap[i];
for (bitNum = 0; bitNum < 8; bitNum++)
for (int bitNum = 0; bitNum < 8; bitNum++)
{
bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
tempConvertMap[x, y] = bit;
try
{
tempConvertMap[x, y] = bit;
}
catch (Exception e)
{
m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
}
x++;
if (x > 63)
if (x >= xLen)
{
x = 0;
y++;
}
}
}
return tempConvertMap;
}

View File

@@ -102,7 +102,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
terrainRenderer.Initialise(m_scene, m_config);
mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
//long t = System.Environment.TickCount;
//for (int i = 0; i < 10; ++i) {
terrainRenderer.TerrainToBitmap(mapbmp);
@@ -277,7 +278,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp)
{
int tc = 0;
double[,] hm = whichScene.Heightmap.GetDoubles();
ITerrainChannel hm = whichScene.Heightmap;
tc = Environment.TickCount;
m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
EntityBase[] objs = whichScene.GetEntities();
@@ -287,8 +288,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
try
{
//SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
lock (objs)
{
foreach (EntityBase obj in objs)
@@ -298,7 +297,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
{
SceneObjectGroup mapdot = (SceneObjectGroup)obj;
Color mapdotspot = Color.Gray; // Default color when prim color is white
// Loop over prim in group
foreach (SceneObjectPart part in mapdot.Parts)
{
@@ -363,7 +361,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
Vector3 pos = part.GetWorldPosition();
// skip prim outside of retion
if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
if (!m_scene.PositionIsInCurrentRegion(pos))
continue;
// skip prim in non-finite position
@@ -388,7 +386,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
Vector3 scale = new Vector3();
Vector3 tScale = new Vector3();
Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z);
Quaternion llrot = part.GetWorldRotation();
Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
@@ -406,12 +404,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
int mapdrawendY = (int)(pos.Y + scale.Y);
// If object is beyond the edge of the map, don't draw it to avoid errors
if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
|| mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
|| mapdrawendY > ((int)Constants.RegionSize - 1))
if (mapdrawstartX < 0
|| mapdrawstartX > (hm.Width - 1)
|| mapdrawendX < 0
|| mapdrawendX > (hm.Width - 1)
|| mapdrawstartY < 0
|| mapdrawstartY > (hm.Height - 1)
|| mapdrawendY < 0
|| mapdrawendY > (hm.Height - 1))
continue;
#region obb face reconstruction part duex
#region obb face reconstruction part duex
Vector3[] vertexes = new Vector3[8];
// float[] distance = new float[6];
@@ -515,7 +518,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
FaceD[2] = vertexes[7];
FaceC[3] = vertexes[7];
FaceD[5] = vertexes[7];
#endregion
#endregion
//int wy = 0;
@@ -530,11 +533,11 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
for (int i = 0; i < FaceA.Length; i++)
{
Point[] working = new Point[5];
working[0] = project(FaceA[i], axPos);
working[1] = project(FaceB[i], axPos);
working[2] = project(FaceD[i], axPos);
working[3] = project(FaceC[i], axPos);
working[4] = project(FaceA[i], axPos);
working[0] = project(hm, FaceA[i], axPos);
working[1] = project(hm, FaceB[i], axPos);
working[2] = project(hm, FaceD[i], axPos);
working[3] = project(hm, FaceC[i], axPos);
working[4] = project(hm, FaceA[i], axPos);
face workingface = new face();
workingface.pts = working;
@@ -546,27 +549,25 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
z_localIDs.Add(part.LocalId);
z_sortheights.Add(pos.Z);
//for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
//{
//for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
//{
//m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
//try
//{
// Remember, flip the y!
// mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
//}
//catch (ArgumentException)
//{
// breakYN = true;
//}
//if (breakYN)
// break;
//}
//if (breakYN)
// break;
// for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
// {
// for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
// {
// m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
// try
// {
// // Remember, flip the y!
// mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
// }
// catch (ArgumentException)
// {
// breakYN = true;
// }
// }
// if (breakYN)
// break;
// }
// }
//}
} // Object is within 256m Z of terrain
} // object is at least a meter wide
@@ -609,17 +610,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
return mapbmp;
}
private Point project(Vector3 point3d, Vector3 originpos)
private Point project(ITerrainChannel hm, Vector3 point3d, Vector3 originpos)
{
Point returnpt = new Point();
//originpos = point3d;
//int d = (int)(256f / 1.5f);
//Vector3 topos = new Vector3(0, 0, 0);
// float z = -point3d.z - topos.z;
// float z = -point3d.z - topos.z;
returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d);
returnpt.Y = (int)(((int)Constants.RegionSize - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
returnpt.Y = (int)((hm.Width - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
return returnpt;
}

View File

@@ -31,6 +31,7 @@ using System.Reflection;
using log4net;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.World.LegacyMap
@@ -39,8 +40,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
{
private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[SHADED MAPTILE RENDERER]";
private Scene m_scene;
//private IConfigSource m_config; // not used currently
@@ -53,19 +54,26 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
public void TerrainToBitmap(Bitmap mapbmp)
{
m_log.DebugFormat("{0} Generating Maptile Step 1: Terrain", LogHeader);
int tc = Environment.TickCount;
m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
double[,] hm = m_scene.Heightmap.GetDoubles();
ITerrainChannel hm = m_scene.Heightmap;
if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
{
m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
}
bool ShadowDebugContinue = true;
bool terraincorruptedwarningsaid = false;
float low = 255;
float high = 0;
for (int x = 0; x < (int)Constants.RegionSize; x++)
for (int x = 0; x < hm.Width; x++)
{
for (int y = 0; y < (int)Constants.RegionSize; y++)
for (int y = 0; y < hm.Height; y++)
{
float hmval = (float)hm[x, y];
if (hmval < low)
@@ -77,12 +85,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
for (int x = 0; x < (int)Constants.RegionSize; x++)
for (int x = 0; x < hm.Width; x++)
{
for (int y = 0; y < (int)Constants.RegionSize; y++)
for (int y = 0; y < hm.Height; y++)
{
// Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
int yr = ((int)Constants.RegionSize - 1) - y;
int yr = ((int)hm.Height - 1) - y;
float heightvalue = (float)hm[x, y];
@@ -109,12 +117,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
// .
//
// Shade the terrain for shadows
if (x < ((int)Constants.RegionSize - 1) && yr < ((int)Constants.RegionSize - 1))
if (x < (hm.Width - 1) && yr < (hm.Height - 1))
{
float hfvalue = (float)hm[x, y];
float hfvaluecompare = 0f;
if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize))
if ((x + 1 < hm.Width) && (y + 1 < hm.Height))
{
hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there
}
@@ -179,7 +187,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
if (ShadowDebugContinue)
{
if ((x - 1 > 0) && (yr + 1 < (int)Constants.RegionSize))
if ((x - 1 > 0) && (yr + 1 < hm.Height))
{
color = mapbmp.GetPixel(x - 1, yr + 1);
int r = color.R;
@@ -233,7 +241,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
terraincorruptedwarningsaid = true;
}
Color black = Color.Black;
mapbmp.SetPixel(x, ((int)Constants.RegionSize - y) - 1, black);
mapbmp.SetPixel(x, (hm.Width - y) - 1, black);
}
}
}
@@ -242,4 +250,4 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
}
}
}
}

View File

@@ -34,6 +34,8 @@ using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.Imaging;
using OpenSim.Framework;
using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.World.LegacyMap
@@ -122,8 +124,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
{
#region Constants
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[TEXTURED MAPTILE RENDERER]";
// some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank").
// The color-values were choosen because they "look right" (at least to me) ;-)
@@ -173,7 +175,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
private Bitmap fetchTexture(UUID id)
{
AssetBase asset = m_scene.AssetService.Get(id.ToString());
m_log.DebugFormat("[TEXTURED MAP TILE RENDERER]: Fetched texture {0}, found: {1}", id, asset != null);
m_log.DebugFormat("{0} Fetched texture {1}, found: {2}", LogHeader, id, asset != null);
if (asset == null) return null;
ManagedImage managedImage;
@@ -188,18 +190,15 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
}
catch (DllNotFoundException)
{
m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id);
m_log.ErrorFormat("{0} OpenJpeg is not installed correctly on this system. Asset Data is empty for {1}", LogHeader, id);
}
catch (IndexOutOfRangeException)
{
m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
m_log.ErrorFormat("{0} OpenJpeg was unable to encode this. Asset Data is empty for {1}", LogHeader, id);
}
catch (Exception)
{
m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
m_log.ErrorFormat("{0} OpenJpeg was unable to encode this. Asset Data is empty for {1}", LogHeader, id);
}
return null;
@@ -271,8 +270,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
// the heigthfield might have some jumps in values. Rendered land is smooth, though,
// as a slope is rendered at that place. So average 4 neighbour values to emulate that.
private float getHeight(double[,] hm, int x, int y) {
if (x < ((int)Constants.RegionSize - 1) && y < ((int)Constants.RegionSize - 1))
private float getHeight(ITerrainChannel hm, int x, int y) {
if (x < (hm.Width - 1) && y < (hm.Height - 1))
return (float)(hm[x, y] * .444 + (hm[x + 1, y] + hm[x, y + 1]) * .222 + hm[x + 1, y +1] * .112);
else
return (float)hm[x, y];
@@ -282,7 +281,15 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
public void TerrainToBitmap(Bitmap mapbmp)
{
int tc = Environment.TickCount;
m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
m_log.DebugFormat("{0} Generating Maptile Step 1: Terrain", LogHeader);
ITerrainChannel hm = m_scene.Heightmap;
if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
{
m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
}
// These textures should be in the AssetCache anyway, as every client conneting to this
// region needs them. Except on start, when the map is recreated (before anyone connected),
@@ -310,19 +317,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
float waterHeight = (float)settings.WaterHeight;
double[,] hm = m_scene.Heightmap.GetDoubles();
for (int x = 0; x < (int)Constants.RegionSize; x++)
for (int x = 0; x < hm.Width; x++)
{
float columnRatio = x / ((float)Constants.RegionSize - 1); // 0 - 1, for interpolation
for (int y = 0; y < (int)Constants.RegionSize; y++)
float columnRatio = x / (hm.Width - 1); // 0 - 1, for interpolation
for (int y = 0; y < hm.Height; y++)
{
float rowRatio = y / ((float)Constants.RegionSize - 1); // 0 - 1, for interpolation
float rowRatio = y / (hm.Height - 1); // 0 - 1, for interpolation
// Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
int yr = ((int)Constants.RegionSize - 1) - y;
int yr = (hm.Height - 1) - y;
float heightvalue = getHeight(hm, x, y);
float heightvalue = getHeight(m_scene.Heightmap, x, y);
if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
heightvalue = 0;
@@ -372,9 +377,9 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
}
// Shade the terrain for shadows
if (x < ((int)Constants.RegionSize - 1) && y < ((int)Constants.RegionSize - 1))
if (x < (hm.Width - 1) && y < (hm.Height - 1))
{
float hfvaluecompare = getHeight(hm, x + 1, y + 1); // light from north-east => look at land height there
float hfvaluecompare = getHeight(m_scene.Heightmap, x + 1, y + 1); // light from north-east => look at land height there
if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare))
hfvaluecompare = 0f;
@@ -420,4 +425,4 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
}
}
}
}

View File

@@ -151,14 +151,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
break;
case 2: // Sell a copy
Vector3 inventoryStoredPosition = new Vector3
(((group.AbsolutePosition.X > (int)Constants.RegionSize)
? 250
: group.AbsolutePosition.X)
,
(group.AbsolutePosition.X > (int)Constants.RegionSize)
? 250
: group.AbsolutePosition.X,
Vector3 inventoryStoredPosition = new Vector3(
Math.Min(group.AbsolutePosition.X, m_scene.RegionInfo.RegionSizeX - 6),
Math.Min(group.AbsolutePosition.Y, m_scene.RegionInfo.RegionSizeY - 6),
group.AbsolutePosition.Z);
Vector3 originalPosition = group.AbsolutePosition;

View File

@@ -1571,10 +1571,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
float X = position.X;
float Y = position.Y;
if (X > ((int)Constants.RegionSize - 1))
X = ((int)Constants.RegionSize - 1);
if (Y > ((int)Constants.RegionSize - 1))
Y = ((int)Constants.RegionSize - 1);
if (X > ((int)m_scene.RegionInfo.RegionSizeX - 1))
X = ((int)m_scene.RegionInfo.RegionSizeX - 1);
if (Y > ((int)m_scene.RegionInfo.RegionSizeY - 1))
Y = ((int)m_scene.RegionInfo.RegionSizeY - 1);
if (X < 0)
X = 0;
if (Y < 0)

View File

@@ -68,9 +68,6 @@ namespace OpenSim.Region.CoreModules
// updating those region settings in GenSunPos()
private bool receivedEstateToolsSunUpdate = false;
// Configurable values
private string m_RegionMode = "SL";
// Sun's position information is updated and sent to clients every m_UpdateInterval frames
private int m_UpdateInterval = 0;
@@ -90,7 +87,6 @@ namespace OpenSim.Region.CoreModules
// private double m_longitude = 0;
// private double m_latitude = 0;
// Configurable defaults Defaults close to SL
private string d_mode = "SL";
private int d_frame_mod = 100; // Every 10 seconds (actually less)
private double d_day_length = 4; // A VW day is 4 RW hours long
private int d_year_length = 60; // There are 60 VW days in a VW year
@@ -134,12 +130,15 @@ namespace OpenSim.Region.CoreModules
private const int TICKS_PER_SECOND = 10000000;
private ulong m_CurrentTimeOffset = 0;
// Current time in elapsed seconds since Jan 1st 1970
private ulong CurrentTime
{
get
{
return (ulong)(((DateTime.Now.Ticks) - TicksToEpoch + TicksUTCOffset) / TICKS_PER_SECOND);
ulong ctime = (ulong)(((DateTime.Now.Ticks) - TicksToEpoch + TicksUTCOffset) / TICKS_PER_SECOND);
return ctime + m_CurrentTimeOffset;
}
}
@@ -262,10 +261,8 @@ namespace OpenSim.Region.CoreModules
private float GetCurrentTimeAsLindenSunHour()
{
if (m_SunFixed)
return m_SunFixedHour + 6;
return GetCurrentSunHour() + 6.0f;
float curtime = m_SunFixed ? m_SunFixedHour : GetCurrentSunHour();
return (curtime + 6.0f) % 24.0f;
}
#region INonSharedRegion Methods
@@ -290,8 +287,6 @@ namespace OpenSim.Region.CoreModules
// Just in case they don't have the stanzas
try
{
// Mode: determines how the sun is handled
m_RegionMode = config.Configs["Sun"].GetString("mode", d_mode);
// Mode: determines how the sun is handled
// m_latitude = config.Configs["Sun"].GetDouble("latitude", d_latitude);
// Mode: determines how the sun is handled
@@ -314,7 +309,6 @@ namespace OpenSim.Region.CoreModules
catch (Exception e)
{
m_log.Debug("[SUN]: Configuration access failed, using defaults. Reason: " + e.Message);
m_RegionMode = d_mode;
m_YearLengthDays = d_year_length;
m_DayLengthHours = d_day_length;
m_HorizonShift = d_day_night;
@@ -325,40 +319,28 @@ namespace OpenSim.Region.CoreModules
// m_longitude = d_longitude;
}
switch (m_RegionMode)
{
case "T1":
default:
case "SL":
// Time taken to complete a cycle (day and season)
SecondsPerSunCycle = (uint) (m_DayLengthHours * 60 * 60);
SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays);
SecondsPerSunCycle = (uint) (m_DayLengthHours * 60 * 60);
SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays);
// Ration of real-to-virtual time
// Ration of real-to-virtual time
// VWTimeRatio = 24/m_day_length;
// VWTimeRatio = 24/m_day_length;
// Speed of rotation needed to complete a cycle in the
// designated period (day and season)
// Speed of rotation needed to complete a cycle in the
// designated period (day and season)
SunSpeed = m_SunCycle/SecondsPerSunCycle;
SeasonSpeed = m_SeasonalCycle/SecondsPerYear;
SunSpeed = m_SunCycle/SecondsPerSunCycle;
SeasonSpeed = m_SeasonalCycle/SecondsPerYear;
// Horizon translation
// Horizon translation
HorizonShift = m_HorizonShift; // Z axis translation
// HoursToRadians = (SunCycle/24)*VWTimeRatio;
m_log.Debug("[SUN]: Mode is " + m_RegionMode);
m_log.Debug("[SUN]: Initialization completed. Day is " + SecondsPerSunCycle + " seconds, and year is " + m_YearLengthDays + " days");
m_log.Debug("[SUN]: Axis offset is " + m_HorizonShift);
m_log.Debug("[SUN]: Percentage of time for daylight " + m_DayTimeSunHourScale);
m_log.Debug("[SUN]: Positional data updated every " + m_UpdateInterval + " frames");
break;
}
HorizonShift = m_HorizonShift; // Z axis translation
// HoursToRadians = (SunCycle/24)*VWTimeRatio;
m_log.Debug("[SUN]: Initialization completed. Day is " + SecondsPerSunCycle + " seconds, and year is " + m_YearLengthDays + " days");
m_log.Debug("[SUN]: Axis offset is " + m_HorizonShift);
m_log.Debug("[SUN]: Percentage of time for daylight " + m_DayTimeSunHourScale);
m_log.Debug("[SUN]: Positional data updated every " + m_UpdateInterval + " frames");
}
public Type ReplaceableInterface
@@ -385,7 +367,8 @@ namespace OpenSim.Region.CoreModules
string sunCommand = string.Format("sun {0}", kvp.Key);
m_scene.AddCommand("Regions", this, sunCommand, string.Format("{0} [<value>]", sunCommand), kvp.Value, "", HandleSunConsoleCommand);
}
m_scene.AddCommand("Regions", this, "sun help", "sun help", "list parameters that can be changed", "", HandleSunConsoleCommand);
m_scene.AddCommand("Regions", this, "sun list", "sun list", "list parameters that can be changed", "", HandleSunConsoleCommand);
ready = true;
}
@@ -419,23 +402,22 @@ namespace OpenSim.Region.CoreModules
public void SunToClient(IClientAPI client)
{
if (m_RegionMode != "T1")
if (ready)
{
if (ready)
if (m_SunFixed)
{
if (m_SunFixed)
{
// m_log.DebugFormat("[SUN]: SunHour {0}, Position {1}, PosTime {2}, OrbitalPosition : {3} ", m_SunFixedHour, Position.ToString(), PosTime.ToString(), OrbitalPosition.ToString());
client.SendSunPos(Position, Velocity, PosTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
}
else
{
// m_log.DebugFormat("[SUN]: SunHour {0}, Position {1}, PosTime {2}, OrbitalPosition : {3} ", m_SunFixedHour, Position.ToString(), PosTime.ToString(), OrbitalPosition.ToString());
client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
}
// m_log.DebugFormat("[SUN]: Fixed SunHour {0}, Position {1}, PosTime {2}, OrbitalPosition : {3} ",
// m_SunFixedHour, Position.ToString(), PosTime.ToString(), OrbitalPosition.ToString());
client.SendSunPos(Position, Velocity, PosTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
}
else
{
// m_log.DebugFormat("[SUN]: SunHour {0}, Position {1}, PosTime {2}, OrbitalPosition : {3} ",
// m_SunFixedHour, Position.ToString(), PosTime.ToString(), OrbitalPosition.ToString());
client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
}
}
}
}
public void SunUpdate()
{
@@ -532,6 +514,9 @@ namespace OpenSim.Region.CoreModules
case "update_interval":
return m_UpdateInterval;
case "current_time":
return GetCurrentTimeAsLindenSunHour();
default:
throw new Exception("Unknown sun parameter.");
}
@@ -539,7 +524,51 @@ namespace OpenSim.Region.CoreModules
public void SetSunParameter(string param, double value)
{
HandleSunConsoleCommand("sun", new string[] {param, value.ToString() });
switch (param)
{
case "year_length":
m_YearLengthDays = (int)value;
SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays);
SeasonSpeed = m_SeasonalCycle/SecondsPerYear;
break;
case "day_length":
m_DayLengthHours = value;
SecondsPerSunCycle = (uint) (m_DayLengthHours * 60 * 60);
SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays);
SunSpeed = m_SunCycle/SecondsPerSunCycle;
SeasonSpeed = m_SeasonalCycle/SecondsPerYear;
break;
case "day_night_offset":
m_HorizonShift = value;
HorizonShift = m_HorizonShift;
break;
case "day_time_sun_hour_scale":
m_DayTimeSunHourScale = value;
break;
case "update_interval":
m_UpdateInterval = (int)value;
break;
case "current_time":
value = (value + 18.0) % 24.0;
// set the current offset so that the effective sun time is the parameter
m_CurrentTimeOffset = 0; // clear this first so we use raw time
m_CurrentTimeOffset = (ulong)(SecondsPerSunCycle * value/ 24.0) - (CurrentTime % SecondsPerSunCycle);
break;
default:
throw new Exception("Unknown sun parameter.");
// Generate shared values
GenSunPos();
// When sun settings are updated, we should update all clients with new settings.
SunUpdateToAllClients();
}
}
public float GetCurrentSunHour()
@@ -572,7 +601,7 @@ namespace OpenSim.Region.CoreModules
foreach (string output in ParseCmdParams(cmdparams))
{
m_log.Info("[SUN] " + output);
MainConsole.Instance.Output(output);
}
}
@@ -581,10 +610,11 @@ namespace OpenSim.Region.CoreModules
Dictionary<string, string> Params = new Dictionary<string, string>();
Params.Add("year_length", "number of days to a year");
Params.Add("day_length", "number of seconds to a day");
Params.Add("day_length", "number of hours to a day");
Params.Add("day_night_offset", "induces a horizon shift");
Params.Add("update_interval", "how often to update the sun's position in frames");
Params.Add("day_time_sun_hour_scale", "scales day light vs nite hours to change day/night ratio");
Params.Add("current_time", "time in seconds of the simulator");
return Params;
}
@@ -618,46 +648,15 @@ namespace OpenSim.Region.CoreModules
}
else if (args.Length == 3)
{
float value = 0.0f;
if (!float.TryParse(args[2], out value))
double value = 0.0;
if (! double.TryParse(args[2], out value))
{
Output.Add(String.Format("The parameter value {0} is not a valid number.", args[2]));
return Output;
}
switch (args[1].ToLower())
{
case "year_length":
m_YearLengthDays = (int)value;
break;
case "day_length":
m_DayLengthHours = value;
break;
case "day_night_offset":
m_HorizonShift = value;
break;
case "day_time_sun_hour_scale":
m_DayTimeSunHourScale = value;
break;
case "update_interval":
m_UpdateInterval = (int)value;
break;
default:
Output.Add(String.Format("Unknown parameter {0}.", args[1]));
return Output;
}
SetSunParameter(args[1].ToLower(), value);
Output.Add(String.Format("Parameter {0} set to {1}.", args[1], value.ToString()));
// Generate shared values
GenSunPos();
// When sun settings are updated, we should update all clients with new settings.
SunUpdateToAllClients();
}
return Output;

View File

@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
for (y = 0; y < map.Height; y++)
{
map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10;
double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01;
double spherFac = TerrainUtil.SphericalFactor(x, y, map.Width / 2, map.Height / 2, 50) * 0.01;
if (map[x, y] < spherFac)
{
map[x, y] = spherFac;

View File

@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
{
using (Bitmap bitmap = new Bitmap(filename))
{
ITerrainChannel retval = new TerrainChannel(true);
ITerrainChannel retval = new TerrainChannel(w, h);
for (int x = 0; x < retval.Width; x++)
{

View File

@@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
{
if (fillArea[x, y])
{
double noise = TerrainUtil.PerlinNoise2D((double) x / Constants.RegionSize, (double) y / Constants.RegionSize, 8, 1.0);
double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0);
map[x, y] += noise * strength;
}

View File

@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
z *= z;
z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
double noise = TerrainUtil.PerlinNoise2D(x / (double) Constants.RegionSize, y / (double) Constants.RegionSize, 8, 1.0);
double noise = TerrainUtil.PerlinNoise2D(x / (double) map.Width, y / (double) map.Height, 8, 1.0);
if (z > 0.0)
map[x, y] += noise * z * duration;

View File

@@ -30,10 +30,14 @@ using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Net;
using log4net;
using Nini.Config;
using OpenMetaverse;
using Mono.Addins;
using OpenSim.Data;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.CoreModules.World.Terrain.FileLoaders;
@@ -70,6 +74,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
#endregion
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[TERRAIN MODULE]";
private readonly Commander m_commander = new Commander("terrain");
@@ -130,15 +135,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
if (m_scene.Heightmap == null)
{
m_channel = new TerrainChannel(m_InitialTerrain);
m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX,
(int)m_scene.RegionInfo.RegionSizeY,
(int)m_scene.RegionInfo.RegionSizeZ);
m_scene.Heightmap = m_channel;
m_revert = new TerrainChannel();
UpdateRevertMap();
}
else
{
m_channel = m_scene.Heightmap;
m_revert = new TerrainChannel();
UpdateRevertMap();
}
@@ -230,11 +235,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
try
{
ITerrainChannel channel = loader.Value.LoadFile(filename);
if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize)
if (channel.Width != m_scene.RegionInfo.RegionSizeX || channel.Height != m_scene.RegionInfo.RegionSizeY)
{
// TerrainChannel expects a RegionSize x RegionSize map, currently
throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}",
Constants.RegionSize, Constants.RegionSize));
m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY));
}
m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
m_scene.Heightmap = channel;
@@ -309,12 +314,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
LoadFromStream(filename, URIFetch(pathToTerrainHeightmap));
}
public void LoadFromStream(string filename, Stream stream)
{
LoadFromStream(filename, Vector3.Zero, 0f, Vector2.Zero, stream);
}
/// <summary>
/// Loads a terrain file from a stream and installs it in the scene.
/// </summary>
/// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
/// <param name="stream"></param>
public void LoadFromStream(string filename, Stream stream)
public void LoadFromStream(string filename, Vector3 displacement,
float radianRotation, Vector2 rotationDisplacement, Stream stream)
{
foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
{
@@ -325,8 +336,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
try
{
ITerrainChannel channel = loader.Value.LoadStream(stream);
m_scene.Heightmap = channel;
m_channel = channel;
m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
UpdateRevertMap();
}
catch (NotImplementedException)
@@ -532,6 +542,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// </summary>
public void UpdateRevertMap()
{
/*
int x;
for (x = 0; x < m_channel.Width; x++)
{
@@ -541,6 +552,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_revert[x, y] = m_channel[x, y];
}
}
*/
m_revert = m_channel.MakeCopy();
}
/// <summary>
@@ -567,8 +580,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
fileWidth, fileHeight,
(int) Constants.RegionSize,
(int) Constants.RegionSize);
(int) m_scene.RegionInfo.RegionSizeX,
(int) m_scene.RegionInfo.RegionSizeY);
m_scene.Heightmap = channel;
m_channel = channel;
UpdateRevertMap();
@@ -615,8 +628,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
fileWidth, fileHeight,
(int)Constants.RegionSize,
(int)Constants.RegionSize);
(int)m_scene.RegionInfo.RegionSizeX,
(int)m_scene.RegionInfo.RegionSizeY);
MainConsole.Instance.OutputFormat(
"Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}",
@@ -705,7 +718,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private void CheckForTerrainUpdates(bool respectEstateSettings)
{
bool shouldTaint = false;
float[] serialised = m_channel.GetFloatsSerialised();
float[] terrHeights = m_channel.GetFloatsSerialised();
int x;
for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
{
@@ -714,16 +727,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
if (m_channel.Tainted(x, y))
{
// if we should respect the estate settings then
// fixup and height deltas that don't respect them
// If we should respect the estate settings then
// fixup and height deltas that don't respect them.
// Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
if (respectEstateSettings && LimitChannelChanges(x, y))
{
// this has been vetoed, so update
// what we are going to send to the client
serialised = m_channel.GetFloatsSerialised();
// Terrain heights were modified. Refetch the terrain info.
terrHeights = m_channel.GetFloatsSerialised();
}
SendToClients(serialised, x, y);
// m_log.DebugFormat("{0} Patch modified. Sending (x,y) = ({1},{2})", LogHeader, x, y);
SendToClients(terrHeights, x, y);
shouldTaint = true;
}
}
@@ -792,13 +806,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
/// <param name="x">The patch corner to send</param>
/// <param name="y">The patch corner to send</param>
private void SendToClients(float[] serialised, int x, int y)
private void SendToClients(float[] heightMap, int x, int y)
{
m_scene.ForEachClient(
delegate(IClientAPI controller)
{ controller.SendLayerData(
x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
}
{ controller.SendLayerData( x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, heightMap); }
);
}
@@ -984,28 +996,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (direction.ToLower().StartsWith("y"))
{
for (int x = 0; x < Constants.RegionSize; x++)
for (int x = 0; x < m_channel.Width; x++)
{
for (int y = 0; y < Constants.RegionSize / 2; y++)
for (int y = 0; y < m_channel.Height / 2; y++)
{
double height = m_channel[x, y];
double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y];
double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
m_channel[x, y] = flippedHeight;
m_channel[x, (int)Constants.RegionSize - 1 - y] = height;
m_channel[x, (int)m_channel.Height - 1 - y] = height;
}
}
}
else if (direction.ToLower().StartsWith("x"))
{
for (int y = 0; y < Constants.RegionSize; y++)
for (int y = 0; y < m_channel.Height; y++)
{
for (int x = 0; x < Constants.RegionSize / 2; x++)
for (int x = 0; x < m_channel.Width / 2; x++)
{
double height = m_channel[x, y];
double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y];
double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
m_channel[x, y] = flippedHeight;
m_channel[(int)Constants.RegionSize - 1 - x, y] = height;
m_channel[(int)m_channel.Width - 1 - x, y] = height;
}
}

View File

@@ -40,10 +40,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
[Test]
public void BrushTest()
{
int midRegion = (int)Constants.RegionSize / 2;
// Create a mask that covers only the left half of the region
bool[,] allowMask = new bool[(int)Constants.RegionSize, 256];
int x;
int y;
for (x = 0; x < (int)((int)Constants.RegionSize * 0.5f); x++)
for (x = 0; x < midRegion; x++)
{
for (y = 0; y < (int)Constants.RegionSize; y++)
{
@@ -57,13 +60,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
ITerrainPaintableEffect effect = new RaiseSphere();
effect.PaintEffect(map, allowMask, (int)Constants.RegionSize * 0.5f, (int)Constants.RegionSize * 0.5f, -1.0, 2, 0.1);
Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (127,128).");
Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (124,128).");
Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (123,128).");
Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (128,128).");
Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (0,128).");
effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0);
Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128).");
Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128).");
Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128).");
Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128).");
Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128).");
//
// Test LowerSphere
//
@@ -77,13 +79,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
}
effect = new LowerSphere();
effect.PaintEffect(map, allowMask, ((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), -1.0, 2, 6.0);
Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] < 1.0, "Lower brush should lowering value at this point (124,128).");
Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (123,128).");
Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (128,128).");
Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (0,128).");
effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0);
Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128).");
Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128).");
Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128).");
Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128).");
}
[Test]
@@ -100,10 +102,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
x[0, 0] -= 1.0;
Assert.That(x[0, 0] == 4.0, "Terrain addition/subtraction error.");
x[0, 0] = Math.PI;
double[,] doublesExport = x.GetDoubles();
Assert.That(doublesExport[0, 0] == Math.PI, "Export to double[,] array not working correctly.");
x[0, 0] = 1.0;
float[] floatsExport = x.GetFloatsSerialised();
Assert.That(floatsExport[0] == 1.0f, "Export to float[] not working correctly.");

View File

@@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@@ -32,6 +32,7 @@ using System.Drawing.Imaging;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.World.Warp3DMap
@@ -66,261 +67,271 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
#endregion Constants
private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private static string LogHeader = "[WARP3D TERRAIN SPLAT]";
/// <summary>
/// Builds a composited terrain texture given the region texture
/// and heightmap settings
/// </summary>
/// <param name="heightmap">Terrain heightmap</param>
/// <param name="terrain">Terrain heightmap</param>
/// <param name="regionInfo">Region information including terrain texture parameters</param>
/// <returns>A composited 256x256 RGB texture ready for rendering</returns>
/// <returns>A 256x256 square RGB texture ready for rendering</returns>
/// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting
/// Note we create a 256x256 dimension texture even if the actual terrain is larger.
/// </remarks>
public static Bitmap Splat(float[] heightmap, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetService assetService, bool textureTerrain)
public static Bitmap Splat(ITerrainChannel terrain,
UUID[] textureIDs, float[] startHeights, float[] heightRanges,
Vector3d regionPosition, IAssetService assetService, bool textureTerrain)
{
Debug.Assert(heightmap.Length == 256 * 256);
Debug.Assert(textureIDs.Length == 4);
Debug.Assert(startHeights.Length == 4);
Debug.Assert(heightRanges.Length == 4);
Bitmap[] detailTexture = new Bitmap[4];
Bitmap output = null;
BitmapData outputData = null;
try
if (textureTerrain)
{
if (textureTerrain)
// Swap empty terrain textureIDs with default IDs
for (int i = 0; i < textureIDs.Length; i++)
{
// Swap empty terrain textureIDs with default IDs
for (int i = 0; i < textureIDs.Length; i++)
if (textureIDs[i] == UUID.Zero)
textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
}
#region Texture Fetching
if (assetService != null)
{
for (int i = 0; i < 4; i++)
{
if (textureIDs[i] == UUID.Zero)
textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
}
#region Texture Fetching
if (assetService != null)
{
for (int i = 0; i < 4; i++)
AssetBase asset;
UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
// Try to fetch a cached copy of the decoded/resized version of this texture
asset = assetService.GetCached(cacheID.ToString());
if (asset != null)
{
AssetBase asset;
UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
// Try to fetch a cached copy of the decoded/resized version of this texture
asset = assetService.GetCached(cacheID.ToString());
try
{
using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
detailTexture[i] = (Bitmap)Image.FromStream(stream);
}
catch (Exception ex)
{
m_log.Warn("Failed to decode cached terrain texture " + cacheID +
" (textureID: " + textureIDs[i] + "): " + ex.Message);
}
}
if (detailTexture[i] == null)
{
// Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
asset = assetService.Get(textureIDs[i].ToString());
if (asset != null)
{
// m_log.DebugFormat(
// "[TERRAIN SPLAT]: Got asset service cached terrain texture {0} {1}", i, asset.ID);
try
{
using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
detailTexture[i] = (Bitmap)Image.FromStream(stream);
}
catch (Exception ex)
{
m_log.Warn("Failed to decode cached terrain texture " + cacheID +
" (textureID: " + textureIDs[i] + "): " + ex.Message);
}
}
if (detailTexture[i] == null)
{
// Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
asset = assetService.Get(textureIDs[i].ToString());
if (asset != null)
{
// m_log.DebugFormat(
// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
catch (Exception ex)
try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
catch (Exception ex)
{
m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
}
}
if (detailTexture[i] != null)
{
// Make sure this texture is the correct size, otherwise resize
if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
{
using (Bitmap origBitmap = detailTexture[i])
{
m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
}
}
if (detailTexture[i] != null)
{
// Make sure this texture is the correct size, otherwise resize
if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
{
using (Bitmap origBitmap = detailTexture[i])
{
detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
}
}
// Save the decoded and resized texture to the cache
byte[] data;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
detailTexture[i].Save(stream, ImageFormat.Png);
data = stream.ToArray();
}
// Cache a PNG copy of this terrain texture
AssetBase newAsset = new AssetBase
{
Data = data,
Description = "PNG",
Flags = AssetFlags.Collectable,
FullID = cacheID,
ID = cacheID.ToString(),
Local = true,
Name = String.Empty,
Temporary = true,
Type = (sbyte)AssetType.Unknown
};
newAsset.Metadata.ContentType = "image/png";
assetService.Store(newAsset);
// Save the decoded and resized texture to the cache
byte[] data;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
detailTexture[i].Save(stream, ImageFormat.Png);
data = stream.ToArray();
}
// Cache a PNG copy of this terrain texture
AssetBase newAsset = new AssetBase
{
Data = data,
Description = "PNG",
Flags = AssetFlags.Collectable,
FullID = cacheID,
ID = cacheID.ToString(),
Local = true,
Name = String.Empty,
Temporary = true,
Type = (sbyte)AssetType.Unknown
};
newAsset.Metadata.ContentType = "image/png";
assetService.Store(newAsset);
}
}
}
#endregion Texture Fetching
}
// Fill in any missing textures with a solid color
for (int i = 0; i < 4; i++)
{
if (detailTexture[i] == null)
{
// m_log.DebugFormat(
// "[TERRAIN SPLAT]: Generating solid colour for missing texture {0}", i);
// Create a solid color texture for this layer
detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
{
using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
gfx.FillRectangle(brush, 0, 0, 256, 256);
}
#endregion Texture Fetching
}
// Fill in any missing textures with a solid color
for (int i = 0; i < 4; i++)
{
if (detailTexture[i] == null)
{
m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color",
LogHeader, i);
// Create a solid color texture for this layer
detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
{
using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
gfx.FillRectangle(brush, 0, 0, 256, 256);
}
}
#region Layer Map
float[] layermap = new float[256 * 256];
else
{
if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
{
detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256);
}
}
}
#region Layer Map
float[,] layermap = new float[256, 256];
// Scale difference between actual region size and the 256 texture being created
int xFactor = terrain.Width / 256;
int yFactor = terrain.Height / 256;
// Create 'layermap' where each value is the fractional layer number to place
// at that point. For instance, a value of 1.345 gives the blending of
// layer 1 and layer 2 for that point.
for (int y = 0; y < 256; y++)
{
for (int x = 0; x < 256; x++)
{
float height = (float)terrain[x * xFactor, y * yFactor];
float pctX = (float)x / 255f;
float pctY = (float)y / 255f;
// Use bilinear interpolation between the four corners of start height and
// height range to select the current values at this position
float startHeight = ImageUtils.Bilinear(
startHeights[0],
startHeights[2],
startHeights[1],
startHeights[3],
pctX, pctY);
startHeight = Utils.Clamp(startHeight, 0f, 255f);
float heightRange = ImageUtils.Bilinear(
heightRanges[0],
heightRanges[2],
heightRanges[1],
heightRanges[3],
pctX, pctY);
heightRange = Utils.Clamp(heightRange, 0f, 255f);
// Generate two frequencies of perlin noise based on our global position
// The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
Vector3 vec = new Vector3
(
((float)regionPosition.X + (x * xFactor)) * 0.20319f,
((float)regionPosition.Y + (y * yFactor)) * 0.20319f,
height * 0.25f
);
float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
float noise = (lowFreq + highFreq) * 2f;
// Combine the current height, generated noise, start height, and height range parameters, then scale all of it
float layer = ((height + noise - startHeight) / heightRange) * 4f;
if (Single.IsNaN(layer))
layer = 0f;
layermap[x, y] = Utils.Clamp(layer, 0f, 3f);
}
}
#endregion Layer Map
#region Texture Compositing
Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
// Unsafe work as we lock down the source textures for quicker access and access the
// pixel data directly
unsafe
{
// Get handles to all of the texture data arrays
BitmapData[] datas = new BitmapData[]
{
detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
};
// Compute size of each pixel data (used to address into the pixel data array)
int[] comps = new int[]
{
(datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
(datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
(datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
(datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
};
for (int y = 0; y < 256; y++)
{
for (int x = 0; x < 256; x++)
{
float height = heightmap[y * 256 + x];
float pctX = (float)x / 255f;
float pctY = (float)y / 255f;
// Use bilinear interpolation between the four corners of start height and
// height range to select the current values at this position
float startHeight = ImageUtils.Bilinear(
startHeights[0],
startHeights[2],
startHeights[1],
startHeights[3],
pctX, pctY);
startHeight = Utils.Clamp(startHeight, 0f, 255f);
float heightRange = ImageUtils.Bilinear(
heightRanges[0],
heightRanges[2],
heightRanges[1],
heightRanges[3],
pctX, pctY);
heightRange = Utils.Clamp(heightRange, 0f, 255f);
// Generate two frequencies of perlin noise based on our global position
// The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
Vector3 vec = new Vector3
(
((float)regionPosition.X + x) * 0.20319f,
((float)regionPosition.Y + y) * 0.20319f,
height * 0.25f
);
float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
float noise = (lowFreq + highFreq) * 2f;
// Combine the current height, generated noise, start height, and height range parameters, then scale all of it
float layer = ((height + noise - startHeight) / heightRange) * 4f;
if (Single.IsNaN(layer)) layer = 0f;
layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f);
float layer = layermap[x, y];
// Select two textures
int l0 = (int)Math.Floor(layer);
int l1 = Math.Min(l0 + 1, 3);
byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0];
byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1];
byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
float aB = *(ptrA + 0);
float aG = *(ptrA + 1);
float aR = *(ptrA + 2);
float bB = *(ptrB + 0);
float bG = *(ptrB + 1);
float bR = *(ptrB + 2);
float layerDiff = layer - l0;
// Interpolate between the two selected textures
*(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB));
*(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG));
*(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR));
}
}
#endregion Layer Map
#region Texture Compositing
output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
// Get handles to all of the texture data arrays
BitmapData[] datas = new BitmapData[]
{
detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
};
int[] comps = new int[]
{
(datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
(datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
(datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
(datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
};
for (int y = 0; y < 256; y++)
{
for (int x = 0; x < 256; x++)
{
float layer = layermap[y * 256 + x];
// Select two textures
int l0 = (int)Math.Floor(layer);
int l1 = Math.Min(l0 + 1, 3);
byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0];
byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1];
byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
float aB = *(ptrA + 0);
float aG = *(ptrA + 1);
float aR = *(ptrA + 2);
float bB = *(ptrB + 0);
float bG = *(ptrB + 1);
float bR = *(ptrB + 2);
float layerDiff = layer - l0;
// Interpolate between the two selected textures
*(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB));
*(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG));
*(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR));
}
}
for (int i = 0; i < 4; i++)
detailTexture[i].UnlockBits(datas[i]);
}
}
finally
{
for (int i = 0; i < 4; i++)
if (detailTexture[i] != null)
detailTexture[i].Dispose();
for (int i = 0; i < detailTexture.Length; i++)
detailTexture[i].UnlockBits(datas[i]);
}
for (int i = 0; i < detailTexture.Length; i++)
if (detailTexture[i] != null)
detailTexture[i].Dispose();
output.UnlockBits(outputData);
// We generated the texture upside down, so flip it
@@ -331,6 +342,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
return output;
}
public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
{
m_log.DebugFormat("{0} ResizeBitmap. From <{1},{2}> to <{3},{4}>",
LogHeader, b.Width, b.Height, nWidth, nHeight);
Bitmap result = new Bitmap(nWidth, nHeight);
using (Graphics g = Graphics.FromImage(result))
g.DrawImage(b, 0, 0, nWidth, nHeight);
b.Dispose();
return result;
}
public static Bitmap SplatSimple(float[] heightmap)
{
const float BASE_HSV_H = 93f / 360f;

View File

@@ -31,21 +31,25 @@ using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using CSJ2K;
using Nini.Config;
using log4net;
using Rednettle.Warp3D;
using Mono.Addins;
using OpenMetaverse;
using OpenMetaverse.Imaging;
using OpenMetaverse.Rendering;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Physics.Manager;
using OpenSim.Services.Interfaces;
using OpenMetaverse;
using OpenMetaverse.Assets;
using OpenMetaverse.Imaging;
using OpenMetaverse.Rendering;
using OpenMetaverse.StructuredData;
using WarpRenderer = global::Warp3D.Warp3D;
namespace OpenSim.Region.CoreModules.World.Warp3DMap
@@ -57,12 +61,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[WARP 3D IMAGE MODULE]";
private Scene m_scene;
private IRendering m_primMesher;
private IConfigSource m_config;
private Dictionary<UUID, Color4> m_colors = new Dictionary<UUID, Color4>();
private bool m_useAntiAliasing = false; // TODO: Make this a config option
private IConfigSource m_config;
private bool m_drawPrimVolume = true; // true if should render the prims on the tile
private bool m_textureTerrain = true; // true if to create terrain splatting texture
private bool m_texturePrims = true; // true if should texture the rendered prims
private float m_texturePrimSize = 48f; // size of prim before we consider texturing it
private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes
private bool m_useAntiAliasing = false; // true if to anti-alias the rendered image
private bool m_Enabled = false;
#region Region Module interface
@@ -71,11 +83,27 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
{
m_config = source;
string[] configSections = new string[] { "Map", "Startup" };
if (Util.GetConfigVarFromSections<string>(
m_config, "MapImageModule", new string[] { "Startup", "Map" }, "MapImageModule") != "Warp3DImageModule")
m_config, "MapImageModule", configSections, "MapImageModule") != "Warp3DImageModule")
return;
m_Enabled = true;
m_drawPrimVolume
= Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume);
m_textureTerrain
= Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain);
m_texturePrims
= Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims);
m_texturePrimSize
= Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize);
m_renderMeshes
= Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes);
m_useAntiAliasing
= Util.GetConfigVarFromSections<bool>(m_config, "UseAntiAliasing", configSections, m_useAntiAliasing);
}
public void AddRegion(Scene scene)
@@ -127,29 +155,28 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
public Bitmap CreateMapTile()
{
Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f);
Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, (int)Constants.RegionSize, (int)Constants.RegionSize, (float)Constants.RegionSize, (float)Constants.RegionSize);
// Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f);
// Camera above the middle of the region
Vector3 camPos = new Vector3(
m_scene.RegionInfo.RegionSizeX/2 - 0.5f,
m_scene.RegionInfo.RegionSizeY/2 - 0.5f,
221.7025033688163f);
// Viewport viewing down onto the region
Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
(int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
(float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY );
// Fill the viewport and return the image
return CreateMapTile(viewport, false);
}
public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
{
Viewport viewport = new Viewport(camPos, camDir, fov, (float)Constants.RegionSize, 0.1f, width, height);
Viewport viewport = new Viewport(camPos, camDir, fov, Constants.RegionSize, 0.1f, width, height);
return CreateMapTile(viewport, useTextures);
}
public Bitmap CreateMapTile(Viewport viewport, bool useTextures)
{
bool drawPrimVolume = true;
bool textureTerrain = true;
string[] configSections = new string[] { "Map", "Startup" };
drawPrimVolume
= Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume);
textureTerrain
= Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain);
m_colors.Clear();
int width = viewport.Width;
@@ -193,8 +220,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40));
CreateWater(renderer);
CreateTerrain(renderer, textureTerrain);
if (drawPrimVolume)
CreateTerrain(renderer, m_textureTerrain);
if (m_drawPrimVolume)
CreateAllPrims(renderer, useTextures);
renderer.Render();
@@ -210,6 +237,16 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
// afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
// then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
// this map tile simply takes a lot of memory.
foreach (var o in renderer.Scene.objectData.Values)
{
warp_Object obj = (warp_Object)o;
obj.vertexData = null;
obj.triangleData = null;
}
renderer.Scene.removeAllObjects();
renderer = null;
viewport = null;
m_colors.Clear();
GC.Collect();
m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
@@ -236,61 +273,74 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
#region Rendering Methods
// Add a water plane to the renderer.
private void CreateWater(WarpRenderer renderer)
{
float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
renderer.AddPlane("Water", 256f * 0.5f);
renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f);
renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f);
renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX/2 - 0.5f,
waterHeight,
m_scene.RegionInfo.RegionSizeY/2 - 0.5f );
renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR));
renderer.Scene.material("WaterColor").setReflectivity(0); // match water color with standard map module thanks lkalif
renderer.Scene.material("WaterColor").setTransparency((byte)((1f - WATER_COLOR.A) * 255f));
warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR));
waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif
waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f));
renderer.Scene.addMaterial("WaterColor", waterColorMaterial);
renderer.SetObjectMaterial("Water", "WaterColor");
}
// Add a terrain to the renderer.
// Note that we create a 'low resolution' 256x256 vertex terrain rather than trying for
// full resolution. This saves a lot of memory especially for very large regions.
private void CreateTerrain(WarpRenderer renderer, bool textureTerrain)
{
ITerrainChannel terrain = m_scene.Heightmap;
float[] heightmap = terrain.GetFloatsSerialised();
// 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
float diff = (float)m_scene.RegionInfo.RegionSizeX / 256f;
warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2);
for (int y = 0; y < 256; y++)
// Create all the vertices for the terrain
for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
{
for (int x = 0; x < 256; x++)
for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
{
int v = y * 256 + x;
float height = heightmap[v];
warp_Vector pos = ConvertVector(new Vector3(x, y, height));
obj.addVertex(new warp_Vertex(pos, (float)x / 255f, (float)(255 - y) / 255f));
warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]);
obj.addVertex(new warp_Vertex(pos,
x / (float)m_scene.RegionInfo.RegionSizeX,
(((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY) );
}
}
for (int y = 0; y < 256; y++)
// Now that we have all the vertices, make another pass and create
// the normals for each of the surface triangles and
// create the list of triangle indices.
for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
{
for (int x = 0; x < 256; x++)
for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
{
if (x < 255 && y < 255)
float newX = x / diff;
float newY = y / diff;
if (newX < 255 && newY < 255)
{
int v = y * 256 + x;
int v = (int)newY * 256 + (int)newX;
// Normal
Vector3 v1 = new Vector3(x, y, heightmap[y * 256 + x]);
Vector3 v2 = new Vector3(x + 1, y, heightmap[y * 256 + x + 1]);
Vector3 v3 = new Vector3(x, y + 1, heightmap[(y + 1) * 256 + x]);
// Normal for a triangle made up of three adjacent vertices
Vector3 v1 = new Vector3(newX, newY, (float)terrain[(int)x, (int)y]);
Vector3 v2 = new Vector3(newX + 1, newY, (float)terrain[(int)(x + 1), (int)y]);
Vector3 v3 = new Vector3(newX, newY + 1, (float)terrain[(int)x, ((int)(y + 1))]);
warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
norm = norm.reverse();
obj.vertex(v).n = norm;
// Triangle 1
// Make two triangles for each of the squares in the grid of vertices
obj.addTriangle(
v,
v + 1,
v + 256);
// Triangle 2
obj.addTriangle(
v + 256 + 1,
v + 256,
@@ -305,7 +355,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
float[] startHeights = new float[4];
float[] heightRanges = new float[4];
RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;
OpenSim.Framework.RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;
textureIDs[0] = regionInfo.TerrainTexture1;
textureIDs[1] = regionInfo.TerrainTexture2;
@@ -323,14 +373,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
heightRanges[3] = (float)regionInfo.Elevation2NE;
uint globalX, globalY;
Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
warp_Texture texture;
using (
Bitmap image
= TerrainSplat.Splat(
heightmap, textureIDs, startHeights, heightRanges,
= TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges,
new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
{
texture = new warp_Texture(image);
@@ -368,8 +416,48 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE)
return;
FacetedMesh renderMesh = null;
Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset);
FacetedMesh renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium);
if (m_renderMeshes)
{
if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero)
{
// Try fetchinng the asset
byte[] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
if (sculptAsset != null)
{
// Is it a mesh?
if (omvPrim.Sculpt.Type == SculptType.Mesh)
{
AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh);
meshAsset = null;
}
else // It's sculptie
{
IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>();
if (imgDecoder != null)
{
Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
if (sculpt != null)
{
renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt,
DetailLevel.Medium);
sculpt.Dispose();
}
}
}
}
}
}
// If not a mesh or sculptie, try the regular mesher
if (renderMesh == null)
{
renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium);
}
if (renderMesh == null)
return;
@@ -428,7 +516,11 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
Color4 faceColor = GetFaceColor(teFace);
string materialName = GetOrCreateMaterial(renderer, faceColor);
string materialName = String.Empty;
if (m_texturePrims && prim.Scale.LengthSquared() > m_texturePrimSize*m_texturePrimSize)
materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
else
materialName = GetOrCreateMaterial(renderer, faceColor);
faceObj.transform(m);
faceObj.setPos(primPos);
@@ -517,10 +609,51 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
return name;
}
public string GetOrCreateMaterial(WarpRenderer renderer, Color4 faceColor, UUID textureID)
{
string materialName = "Color-" + faceColor.ToString() + "-Texture-" + textureID.ToString();
if (renderer.Scene.material(materialName) == null)
{
renderer.AddMaterial(materialName, ConvertColor(faceColor));
if (faceColor.A < 1f)
{
renderer.Scene.material(materialName).setTransparency((byte) ((1f - faceColor.A)*255f));
}
warp_Texture texture = GetTexture(textureID);
if (texture != null)
renderer.Scene.material(materialName).setTexture(texture);
}
return materialName;
}
private warp_Texture GetTexture(UUID id)
{
warp_Texture ret = null;
byte[] asset = m_scene.AssetService.GetData(id.ToString());
if (asset != null)
{
IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>();
Bitmap img = (Bitmap) imgDecoder.DecodeToImage(asset);
if (img != null)
{
return new warp_Texture(img);
}
}
return ret;
}
#endregion Rendering Methods
#region Static Helpers
// Note: axis change.
private static warp_Vector ConvertVector(float x, float y, float z)
{
return new warp_Vector(x, z, y);
}
private static warp_Vector ConvertVector(Vector3 vector)
{
return new warp_Vector(vector.X, vector.Z, vector.Y);

View File

@@ -184,8 +184,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
data.Name = info.RegionName;
data.RegionFlags = 0; // TODO not used?
data.WaterHeight = 0; // not used
data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
data.X = (ushort)Util.WorldToRegionLoc((uint)info.RegionLocX);
data.Y = (ushort)Util.WorldToRegionLoc((uint)info.RegionLocY);
blocks.Add(data);
}
}

View File

@@ -59,8 +59,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WorldMapModule")]
public class WorldMapModule : INonSharedRegionModule, IWorldMapModule
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[WORLD MAP]";
private static readonly string DEFAULT_WORLD_MAP_EXPORT_PATH = "exportmap.jpg";
private static readonly UUID STOP_UUID = UUID.Random();
@@ -282,15 +282,15 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
{
List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
// Get regions that are within 8 regions of here
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
(int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
(int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX - 8),
(int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX + 8),
(int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY - 8),
(int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 8) );
foreach (GridRegion r in regions)
{
MapBlockData block = new MapBlockData();
MapBlockFromGridRegion(block, r, 0);
MapBlockData block = MapBlockFromGridRegion(r, 0);
mapBlocks.Add(block);
}
avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
@@ -410,24 +410,23 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
}
uint xstart = 0;
uint ystart = 0;
Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
if (itemtype == 6) // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
if (itemtype == (int)GridItemType.AgentLocations)
{
if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
{
// Local Map Item Request
// Just requesting map info about the current, local region
int tc = Environment.TickCount;
List<mapItemReply> mapitems = new List<mapItemReply>();
mapItemReply mapitem = new mapItemReply();
if (m_scene.GetRootAgentCount() <= 1)
{
mapitem = new mapItemReply();
mapitem.x = (uint)(xstart + 1);
mapitem.y = (uint)(ystart + 1);
mapitem.id = UUID.Zero;
mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString());
mapitem.Extra = 0;
mapitem.Extra2 = 0;
mapitem = new mapItemReply(
xstart + 1,
ystart + 1,
UUID.Zero,
Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
0, 0);
mapitems.Add(mapitem);
}
else
@@ -437,13 +436,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
// Don't send a green dot for yourself
if (sp.UUID != remoteClient.AgentId)
{
mapitem = new mapItemReply();
mapitem.x = (uint)(xstart + sp.AbsolutePosition.X);
mapitem.y = (uint)(ystart + sp.AbsolutePosition.Y);
mapitem.id = UUID.Zero;
mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString());
mapitem.Extra = 1;
mapitem.Extra2 = 0;
mapitem = new mapItemReply(
xstart + (uint)sp.AbsolutePosition.X,
ystart + (uint)sp.AbsolutePosition.Y,
UUID.Zero,
Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
1, 0);
mapitems.Add(mapitem);
}
});
@@ -458,7 +456,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle);
}
}
else if (itemtype == 7) // Service 7 (MAP_ITEM_LAND_FOR_SALE)
else if (itemtype == (int)GridItemType.LandForSale) // Service 7 (MAP_ITEM_LAND_FOR_SALE)
{
if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
{
@@ -488,14 +486,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
float x = (min.X+max.X)/2;
float y = (min.Y+max.Y)/2;
mapitem = new mapItemReply();
mapitem.x = (uint)(xstart + x);
mapitem.y = (uint)(ystart + y);
// mapitem.z = (uint)m_scene.GetGroundHeight(x,y);
mapitem.id = parcel.GlobalID;
mapitem.name = parcel.Name;
mapitem.Extra = parcel.Area;
mapitem.Extra2 = parcel.SalePrice;
mapitem = new mapItemReply(
xstart + (uint)x,
ystart + (uint)y,
parcel.GlobalID,
parcel.Name,
parcel.Area,
parcel.SalePrice
);
mapitems.Add(mapitem);
}
}
@@ -510,7 +508,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle);
}
}
else if (itemtype == 1) // Service 1 (MAP_ITEM_TELEHUB)
else if (itemtype == (int)GridItemType.Telehub) // Service 1 (MAP_ITEM_TELEHUB)
{
if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
{
@@ -520,13 +518,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
if (sog != null)
{
mapitem = new mapItemReply();
mapitem.x = (uint)(xstart + sog.AbsolutePosition.X);
mapitem.y = (uint)(ystart + sog.AbsolutePosition.Y);
mapitem.id = UUID.Zero;
mapitem.name = sog.Name;
mapitem.Extra = 0; // color (not used)
mapitem.Extra2 = 0; // 0 = telehub / 1 = infohub
mapitem = new mapItemReply(
xstart + (uint)sog.AbsolutePosition.X,
ystart + (uint)sog.AbsolutePosition.Y,
UUID.Zero,
sog.Name,
0, // color (not used)
0 // 0 = telehub / 1 = infohub
);
mapitems.Add(mapitem);
remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
@@ -676,19 +675,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
{
OSDMap mapitem = (OSDMap)itemarray[i];
mapItemReply mi = new mapItemReply();
mi.x = (uint)mapitem["X"].AsInteger();
mi.y = (uint)mapitem["Y"].AsInteger();
mi.id = mapitem["ID"].AsUUID();
mi.Extra = mapitem["Extra"].AsInteger();
mi.Extra2 = mapitem["Extra2"].AsInteger();
mi.name = mapitem["Name"].AsString();
mi.FromOSD(mapitem);
returnitems.Add(mi);
}
av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
}
// Service 7 (MAP_ITEM_LAND_FOR_SALE)
uint itemtype = 7;
uint itemtype = (uint)GridItemType.LandForSale;
if (response.ContainsKey(itemtype.ToString()))
{
@@ -698,19 +692,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
{
OSDMap mapitem = (OSDMap)itemarray[i];
mapItemReply mi = new mapItemReply();
mi.x = (uint)mapitem["X"].AsInteger();
mi.y = (uint)mapitem["Y"].AsInteger();
mi.id = mapitem["ID"].AsUUID();
mi.Extra = mapitem["Extra"].AsInteger();
mi.Extra2 = mapitem["Extra2"].AsInteger();
mi.name = mapitem["Name"].AsString();
mi.FromOSD(mapitem);
returnitems.Add(mi);
}
av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
}
// Service 1 (MAP_ITEM_TELEHUB)
itemtype = 1;
itemtype = (uint)GridItemType.Telehub;
if (response.ContainsKey(itemtype.ToString()))
{
@@ -720,12 +709,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
{
OSDMap mapitem = (OSDMap)itemarray[i];
mapItemReply mi = new mapItemReply();
mi.x = (uint)mapitem["X"].AsInteger();
mi.y = (uint)mapitem["Y"].AsInteger();
mi.id = mapitem["ID"].AsUUID();
mi.Extra = mapitem["Extra"].AsInteger();
mi.Extra2 = mapitem["Extra2"].AsInteger();
mi.name = mapitem["Name"].AsString();
mi.FromOSD(mapitem);
returnitems.Add(mi);
}
av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
@@ -808,7 +792,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
if (httpserver.Length == 0)
{
uint x = 0, y = 0;
Utils.LongToUInts(regionhandle, out x, out y);
Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
if (mreg != null)
@@ -915,7 +899,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
finally
{
if (os != null)
os.Close();
os.Dispose();
}
string response_mapItems_reply = null;
@@ -1007,7 +991,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
/// <param name="maxY"></param>
public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
{
//m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible
{
List<MapBlockData> response = new List<MapBlockData>();
@@ -1016,22 +999,24 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
// on an unloaded square.
// But make sure: Look whether the one we requested is in there
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
minX * (int)Constants.RegionSize,
maxX * (int)Constants.RegionSize,
minY * (int)Constants.RegionSize,
maxY * (int)Constants.RegionSize);
(int)Util.RegionToWorldLoc((uint)minX), (int)Util.RegionToWorldLoc((uint)maxX),
(int)Util.RegionToWorldLoc((uint)minY), (int)Util.RegionToWorldLoc((uint)maxY) );
m_log.DebugFormat("[WORLD MAP MODULE] RequestMapBlocks min=<{0},{1}>, max=<{2},{3}>, flag={4}, cntFound={5}",
minX, minY, maxX, maxY, flag.ToString("X"), regions.Count);
if (regions != null)
{
foreach (GridRegion r in regions)
{
if ((r.RegionLocX == minX * (int)Constants.RegionSize) &&
(r.RegionLocY == minY * (int)Constants.RegionSize))
if (r.RegionLocX == Util.RegionToWorldLoc((uint)minX)
&& r.RegionLocY == Util.RegionToWorldLoc((uint)minY) )
{
// found it => add it to response
MapBlockData block = new MapBlockData();
MapBlockFromGridRegion(block, r, flag);
response.Add(block);
// Version 2 viewers can handle the larger regions
if ((flag & 2) == 2)
response.AddRange(Map2BlockFromGridRegion(r, flag));
else
response.Add(MapBlockFromGridRegion(r, flag));
break;
}
}
@@ -1043,7 +1028,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
MapBlockData block = new MapBlockData();
block.X = (ushort)minX;
block.Y = (ushort)minY;
block.Access = 254; // means 'simulator is offline'
block.Access = (byte)SimAccess.Down; // means 'simulator is offline'
// block.Access = (byte)SimAccess.NonExistant;
response.Add(block);
}
// The lower 16 bits are an unsigned int16
@@ -1060,41 +1046,112 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
{
List<MapBlockData> mapBlocks = new List<MapBlockData>();
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
(minX - 4) * (int)Constants.RegionSize,
(maxX + 4) * (int)Constants.RegionSize,
(minY - 4) * (int)Constants.RegionSize,
(maxY + 4) * (int)Constants.RegionSize);
(int)Util.RegionToWorldLoc((uint)(minX - 4)), (int)Util.RegionToWorldLoc((uint)(maxX + 4)),
(int)Util.RegionToWorldLoc((uint)(minY - 4)), (int)Util.RegionToWorldLoc((uint)(maxY + 4)) );
m_log.DebugFormat("{0} GetAndSendBlocks. min=<{1},{2}>, max=<{3},{4}>, cntFound={5}",
LogHeader, minX, minY, maxX, maxY, regions.Count);
foreach (GridRegion r in regions)
{
MapBlockData block = new MapBlockData();
MapBlockFromGridRegion(block, r, flag);
mapBlocks.Add(block);
// Version 2 viewers can handle the larger regions
if ((flag & 2) == 2)
mapBlocks.AddRange(Map2BlockFromGridRegion(r, flag));
else
mapBlocks.Add(MapBlockFromGridRegion(r, flag));
}
remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
return mapBlocks;
}
protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
// Fill a passed MapBlockData from a GridRegion
protected MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag)
{
MapBlockData block = new MapBlockData();
block.Access = r.Access;
switch (flag & 0xffff)
{
case 0:
block.MapImageId = r.TerrainImage;
break;
case 2:
block.MapImageId = r.ParcelImage;
break;
default:
block.MapImageId = UUID.Zero;
break;
case 0:
block.MapImageId = r.TerrainImage;
break;
case 2:
block.MapImageId = r.ParcelImage;
break;
default:
block.MapImageId = UUID.Zero;
break;
}
block.Name = r.RegionName;
block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
block.X = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocX);
block.Y = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocY);
block.SizeX = (ushort) r.RegionSizeX;
block.SizeY = (ushort) r.RegionSizeY;
return block;
}
protected List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag)
{
List<MapBlockData> blocks = new List<MapBlockData>();
MapBlockData block = new MapBlockData();
if (r == null)
{
block.Access = (byte)SimAccess.Down;
block.MapImageId = UUID.Zero;
blocks.Add(block);
}
else
{
block.Access = r.Access;
switch (flag & 0xffff)
{
case 0:
block.MapImageId = r.TerrainImage;
break;
case 2:
block.MapImageId = r.ParcelImage;
break;
default:
block.MapImageId = UUID.Zero;
break;
}
block.Name = r.RegionName;
block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
block.SizeX = (ushort)r.RegionSizeX;
block.SizeY = (ushort)r.RegionSizeY;
blocks.Add(block);
// If these are larger than legacy regions, create fake map entries for the covered
// regions. The map system only does legacy sized regions so we have to fake map
// entries for all the covered regions.
if (r.RegionSizeX > Constants.RegionSize || r.RegionSizeY > Constants.RegionSize)
{
for (int x = 0; x < r.RegionSizeX / Constants.RegionSize; x++)
{
for (int y = 0; y < r.RegionSizeY / Constants.RegionSize; y++)
{
if (x == 0 && y == 0)
continue;
block = new MapBlockData
{
Access = r.Access,
MapImageId = r.TerrainImage,
Name = r.RegionName,
X = (ushort)((r.RegionLocX / Constants.RegionSize) + x),
Y = (ushort)((r.RegionLocY / Constants.RegionSize) + y),
SizeX = (ushort)r.RegionSizeX,
SizeY = (ushort)r.RegionSizeY
};
//Child piece, so ignore it
blocks.Add(block);
}
}
}
}
return blocks;
}
public Hashtable OnHTTPThrottled(Hashtable keysvals)
{
Hashtable reply = new Hashtable();
@@ -1223,17 +1280,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
List<MapBlockData> mapBlocks = new List<MapBlockData>();
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
(int)(m_scene.RegionInfo.RegionLocX - 9) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocX + 9) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocY - 9) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocY + 9) * (int)Constants.RegionSize);
(int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX - 9),
(int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX + 9),
(int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY - 9),
(int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 9));
List<AssetBase> textures = new List<AssetBase>();
List<Image> bitImages = new List<Image>();
foreach (GridRegion r in regions)
{
MapBlockData mapBlock = new MapBlockData();
MapBlockFromGridRegion(mapBlock, r, 0);
MapBlockData mapBlock = MapBlockFromGridRegion(r, 0);
AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
if (texAsset != null)
@@ -1294,7 +1350,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
uint xstart = 0;
uint ystart = 0;
Utils.LongToUInts(m_scene.RegionInfo.RegionHandle,out xstart,out ystart);
Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle,out xstart,out ystart);
// m_log.DebugFormat("{0} HandleRemoteMapItemRequest. loc=<{1},{2}>",
// LogHeader, Util.WorldToRegionLoc(xstart), Util.WorldToRegionLoc(ystart));
// Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots)

View File

@@ -92,12 +92,11 @@ namespace OpenSim.Region.Framework.Interfaces
void EnableChildAgent(ScenePresence agent, GridRegion region);
GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos);
GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos);
void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
}
public interface IUserAgentVerificationModule

View File

@@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@@ -25,6 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.Drawing;
using OpenMetaverse;
using OpenMetaverse.Imaging;
@@ -53,5 +54,12 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="components">number of components</param>
/// <returns>true if decode was successful. false otherwise.</returns>
bool Decode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components);
/// <summary>
/// Provides a synchronous decode direct to an image object
/// </summary>
/// <param name="j2kData"></param>
/// <returns>decoded image or 'null' of unsuccessful</returns>
Image DecodeToImage(byte[] j2kData);
}
}

View File

@@ -71,6 +71,32 @@ namespace OpenSim.Region.Framework.Interfaces
UUID owner, bool senseAsAgent, Scene scene,
AvatarAppearance appearance);
/// <summary>
/// Create an NPC with a user-supplied agentID
/// </summary>
/// <param name="firstname"></param>
/// <param name="lastname"></param>
/// <param name="position"></param>
/// <param name="agentID"></param>
/// The desired agent ID
/// <param name="owner"></param>
/// <param name="senseAsAgent">
/// Make the NPC show up as an agent on LSL sensors. The default is
/// that they show up as the NPC type instead, but this is currently
/// an OpenSim-only extension.
/// </param>
/// <param name="scene"></param>
/// <param name="appearance">
/// The avatar appearance to use for the new NPC.
/// </param>
/// <returns>
/// The UUID of the ScenePresence created. UUID.Zero if there was a
/// failure.
/// </returns>
UUID CreateNPC(string firstname, string lastname,
Vector3 position, UUID agentID, UUID owner, bool senseAsAgent, Scene scene,
AvatarAppearance appearance);
/// <summary>
/// Check if the agent is an NPC.
/// </summary>

View File

@@ -29,6 +29,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces
{
/// <summary>
@@ -100,16 +102,11 @@ namespace OpenSim.Region.Framework.Interfaces
/// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
///
/// <param name="loadPath"></param>
/// <param name="merge">
/// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region
/// settings in the archive will be ignored.
/// </param>
/// <param name="skipAssets">
/// If true, the archive is loaded without loading any assets contained within it. This is useful if the
/// assets are already known to be present in the grid's asset service.
/// </param>
/// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId);
/// <param name="options">
/// Dictionary of options.
/// </param>
void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options);
/// <summary>
/// Dearchive a region from a stream. This replaces the existing scene.
@@ -127,15 +124,10 @@ namespace OpenSim.Region.Framework.Interfaces
/// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
///
/// <param name="loadStream"></param>
/// <param name="merge">
/// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region
/// settings in the archive will be ignored.
/// </param>
/// <param name="skipAssets">
/// If true, the archive is loaded without loading any assets contained within it. This is useful if the
/// assets are already known to be present in the grid's asset service.
/// </param
/// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId);
/// <param name="options">
/// Dictionary of options.
/// </param>
void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string,object> options);
}
}

View File

@@ -68,13 +68,22 @@ namespace OpenSim.Region.Framework.Interfaces
/// </summary>
/// <param name="ter">HeightField data</param>
/// <param name="regionID">region UUID</param>
void StoreTerrain(TerrainData terrain, UUID regionID);
// Legacy version kept for downward compabibility
void StoreTerrain(double[,] terrain, UUID regionID);
/// <summary>
/// Load the latest terrain revision from region storage
/// </summary>
/// <param name="regionID">the region UUID</param>
/// <param name="sizeX">the X dimension of the region being filled</param>
/// <param name="sizeY">the Y dimension of the region being filled</param>
/// <param name="sizeZ">the Z dimension of the region being filled</param>
/// <returns>Heightfield data</returns>
TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
// Legacy version kept for downward compabibility
double[,] LoadTerrain(UUID regionID);
void StoreLandObject(ILandObject Parcel);

View File

@@ -79,13 +79,22 @@ namespace OpenSim.Region.Framework.Interfaces
/// </summary>
/// <param name="ter">HeightField data</param>
/// <param name="regionID">region UUID</param>
void StoreTerrain(TerrainData terrain, UUID regionID);
// Legacy version kept for downward compabibility
void StoreTerrain(double[,] terrain, UUID regionID);
/// <summary>
/// Load the latest terrain revision from region storage
/// </summary>
/// <param name="regionID">the region UUID</param>
/// <param name="pSizeX">the X dimension of the terrain being filled</param>
/// <param name="pSizeY">the Y dimension of the terrain being filled</param>
/// <param name="pSizeZ">the Z dimension of the terrain being filled</param>
/// <returns>Heightfield data</returns>
TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
// Legacy version kept for downward compabibility
double[,] LoadTerrain(UUID regionID);
void StoreLandObject(ILandObject Parcel);
@@ -135,4 +144,5 @@ namespace OpenSim.Region.Framework.Interfaces
void Shutdown();
}
}

View File

@@ -25,13 +25,23 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenSim.Framework;
using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces
{
public interface ITerrainChannel
{
int Height { get; }
int Width { get;} // X dimension
int Height { get;} // Y dimension
int Altitude { get;} // Z dimension
double this[int x, int y] { get; set; }
int Width { get; }
float GetHeightAtXYZ(float x, float y, float z);
// Return the packaged terrain data for passing into lower levels of communication
TerrainData GetTerrainData();
/// <summary>
/// Squash the entire heightmap into a single dimensioned array
@@ -40,9 +50,14 @@ namespace OpenSim.Region.Framework.Interfaces
float[] GetFloatsSerialised();
double[,] GetDoubles();
// Check if a location has been updated. Clears the taint flag as a side effect.
bool Tainted(int x, int y);
ITerrainChannel MakeCopy();
string SaveToXmlString();
void LoadFromXmlString(string data);
// Merge some terrain into this channel
void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement);
}
}

View File

@@ -51,6 +51,7 @@ namespace OpenSim.Region.Framework.Interfaces
/// </param>
/// <param name="stream"></param>
void LoadFromStream(string filename, Stream stream);
void LoadFromStream(string filename, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement, Stream stream);
void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
/// <summary>
/// Save a terrain to a stream.

View File

@@ -46,8 +46,8 @@ namespace OpenSim.Region.Framework.Scenes
{
public partial class Scene
{
private static readonly ILog m_log
= LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[SCENE INVENTORY]";
/// <summary>
/// Allows asynchronous derezzing of objects from the scene into a client's inventory.

View File

@@ -1033,7 +1033,7 @@ namespace OpenSim.Region.Framework.Scenes
BordersLocked = true;
Border northBorder = new Border();
northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<---
northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)RegionInfo.RegionSizeY); //<---
northBorder.CrossDirection = Cardinals.N;
NorthBorders.Add(northBorder);
@@ -1043,7 +1043,7 @@ namespace OpenSim.Region.Framework.Scenes
SouthBorders.Add(southBorder);
Border eastBorder = new Border();
eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<---
eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)RegionInfo.RegionSizeY); //<---
eastBorder.CrossDirection = Cardinals.E;
EastBorders.Add(eastBorder);
@@ -1099,8 +1099,9 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns>True after all operations complete, throws exceptions otherwise.</returns>
public override void OtherRegionUp(GridRegion otherRegion)
{
uint xcell = (uint)((int)otherRegion.RegionLocX / (int)Constants.RegionSize);
uint ycell = (uint)((int)otherRegion.RegionLocY / (int)Constants.RegionSize);
uint xcell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocX);
uint ycell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocY);
//m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
// RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell);
@@ -1172,46 +1173,6 @@ namespace OpenSim.Region.Framework.Scenes
return found;
}
/// <summary>
/// Checks whether this region has a neighbour in the given direction.
/// </summary>
/// <param name="car"></param>
/// <param name="fix"></param>
/// <returns>
/// An integer which represents a compass point. N == 1, going clockwise until we reach NW == 8.
/// Returns a positive integer if there is a region in that direction, a negative integer if not.
/// </returns>
public int HaveNeighbor(Cardinals car, ref int[] fix)
{
uint neighbourx = RegionInfo.RegionLocX;
uint neighboury = RegionInfo.RegionLocY;
int dir = (int)car;
if (dir > 1 && dir < 5) //Heading East
neighbourx++;
else if (dir > 5) // Heading West
neighbourx--;
if (dir < 3 || dir == 8) // Heading North
neighboury++;
else if (dir > 3 && dir < 7) // Heading Sout
neighboury--;
int x = (int)(neighbourx * Constants.RegionSize);
int y = (int)(neighboury * Constants.RegionSize);
GridRegion neighbourRegion = GridService.GetRegionByPosition(RegionInfo.ScopeID, x, y);
if (neighbourRegion == null)
{
fix[0] = (int)(RegionInfo.RegionLocX - neighbourx);
fix[1] = (int)(RegionInfo.RegionLocY - neighboury);
return dir * (-1);
}
else
return dir;
}
// Alias IncomingHelloNeighbour OtherRegionUp, for now
public GridRegion IncomingHelloNeighbour(RegionInfo neighbour)
{
@@ -1894,7 +1855,7 @@ namespace OpenSim.Region.Framework.Scenes
{
try
{
double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID);
TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
if (map == null)
{
// This should be in the Terrain module, but it isn't because
@@ -1905,7 +1866,7 @@ namespace OpenSim.Region.Framework.Scenes
m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
Heightmap = new TerrainChannel(m_InitialTerrain);
Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
}
@@ -2483,6 +2444,23 @@ namespace OpenSim.Region.Framework.Scenes
EntityTransferModule.Cross(grp, attemptedPosition, silent);
}
// Simple test to see if a position is in the current region.
// Resuming the position is relative to the region so anything outside its bounds.
// Return 'true' if position inside region.
public bool PositionIsInCurrentRegion(Vector3 pos)
{
bool ret = true;
int xx = (int)Math.Floor(pos.X);
int yy = (int)Math.Floor(pos.Y);
if (xx < 0
|| xx >= RegionInfo.RegionSizeX
|| yy < 0
|| yy >= RegionInfo.RegionSizeY)
ret = false;
return ret;
}
public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
{
if (BordersLocked)
@@ -3900,6 +3878,7 @@ namespace OpenSim.Region.Framework.Scenes
{
Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
acd.startpos.X = crossedBorder.BorderLine.Z - 1;
m_log.DebugFormat("{0} NewUserConnection Adjusted border E. startpos={1}", LogHeader, acd.startpos);
}
if (TestBorderCross(acd.startpos, Cardinals.N))
@@ -4019,12 +3998,12 @@ namespace OpenSim.Region.Framework.Scenes
{
if (posX < 0)
posX = 0;
else if (posX >= 256)
posX = 255.999f;
else if (posX >= (float)RegionInfo.RegionSizeX)
posX = (float)RegionInfo.RegionSizeX - 0.001f;
if (posY < 0)
posY = 0;
else if (posY >= 256)
posY = 255.999f;
else if (posY >= (float)RegionInfo.RegionSizeY)
posY = (float)RegionInfo.RegionSizeY - 0.001f;
reason = String.Empty;
if (Permissions.IsGod(agentID))
@@ -4318,7 +4297,7 @@ namespace OpenSim.Region.Framework.Scenes
"[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
// TODO: This check should probably be in QueryAccess().
ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
if (nearestParcel == null)
{
m_log.InfoFormat(
@@ -4613,44 +4592,6 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence sp = GetScenePresence(remoteClient.AgentId);
if (sp != null)
{
uint regionX = RegionInfo.RegionLocX;
uint regionY = RegionInfo.RegionLocY;
Utils.LongToUInts(regionHandle, out regionX, out regionY);
int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
position.X += shiftx;
position.Y += shifty;
bool result = false;
if (TestBorderCross(position,Cardinals.N))
result = true;
if (TestBorderCross(position, Cardinals.S))
result = true;
if (TestBorderCross(position, Cardinals.E))
result = true;
if (TestBorderCross(position, Cardinals.W))
result = true;
// bordercross if position is outside of region
if (!result)
{
regionHandle = RegionInfo.RegionHandle;
}
else
{
// not in this region, undo the shift!
position.X -= shiftx;
position.Y -= shifty;
}
if (EntityTransferModule != null)
{
EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
@@ -4830,7 +4771,7 @@ namespace OpenSim.Region.Framework.Scenes
else
{
if (pos.X > 0f && pos.X < Constants.RegionSize && pos.Y > 0f && pos.Y < Constants.RegionSize)
if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
{
// The only time parcel != null when an object is inside a region is when
// there is nothing behind the landchannel. IE, no land plugin loaded.
@@ -5491,7 +5432,7 @@ namespace OpenSim.Region.Framework.Scenes
{
Vector3 unitDirection = Vector3.Normalize(direction);
//Making distance to search go through some sane limit of distance
for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f)
for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
{
Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
@@ -5545,9 +5486,9 @@ namespace OpenSim.Region.Framework.Scenes
int count = 0;
int avgx = 0;
int avgy = 0;
for (int x = 0; x < Constants.RegionSize; x++)
for (int x = 0; x < RegionInfo.RegionSizeX; x++)
{
for (int y = 0; y < Constants.RegionSize; y++)
for (int y = 0; y < RegionInfo.RegionSizeY; y++)
{
//Just keep a running average as we check if all the points are inside or not
if (parcel.ContainsPoint(x, y))
@@ -5571,31 +5512,33 @@ namespace OpenSim.Region.Framework.Scenes
private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
{
float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X;
float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y;
float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2
? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X;
float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2
? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y;
//find out what vertical edge to go to
if (xdistance < ydistance)
{
if (avatar.AbsolutePosition.X < Constants.RegionSize / 2)
if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2)
{
return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
}
else
{
return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y);
return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
}
}
//find out what horizontal edge to go to
else
{
if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2)
if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2)
{
return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
}
else
{
return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize);
return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
}
}
}

View File

@@ -42,8 +42,8 @@ namespace OpenSim.Region.Framework.Scenes
{
public abstract class SceneBase : IScene
{
protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static readonly string LogHeader = "[SCENE]";
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[SCENE]";
#region Events

View File

@@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Scenes
{
m_log.DebugFormat(
"[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up",
m_scene.Name, neighbour.RegionName, x / Constants.RegionSize, y / Constants.RegionSize);
m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
m_scene.EventManager.TriggerOnRegionUp(neighbour);
}
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Framework.Scenes
{
m_log.WarnFormat(
"[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.",
m_scene.Name, x / Constants.RegionSize, y / Constants.RegionSize);
m_scene.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
}
}
@@ -166,7 +166,7 @@ namespace OpenSim.Region.Framework.Scenes
// we only want to send one update to each simulator; the simulator will
// hand it off to the regions where a child agent exists, this does assume
// that the region position is cached or performance will degrade
Utils.LongToUInts(regionHandle, out x, out y);
Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
if (dest == null)
continue;
@@ -203,7 +203,7 @@ namespace OpenSim.Region.Framework.Scenes
//m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
uint x = 0, y = 0;
Utils.LongToUInts(regionHandle, out x, out y);
Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);

View File

@@ -334,7 +334,7 @@ namespace OpenSim.Region.Framework.Scenes
{
get
{
Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
Vector3 minScale = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize);
Vector3 maxScale = Vector3.Zero;
Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
@@ -466,8 +466,6 @@ namespace OpenSim.Region.Framework.Scenes
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
{
IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
uint x = 0;
uint y = 0;
string version = String.Empty;
Vector3 newpos = Vector3.Zero;
OpenSim.Services.Interfaces.GridRegion destination = null;
@@ -487,7 +485,7 @@ namespace OpenSim.Region.Framework.Scenes
// We set the avatar position as being the object
// position to get the region to send to
if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out version, out newpos)) == null)
{
canCross = false;
break;
@@ -522,14 +520,14 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
// Normalize
if (val.X >= Constants.RegionSize)
val.X -= Constants.RegionSize;
if (val.Y >= Constants.RegionSize)
val.Y -= Constants.RegionSize;
if (val.X >= m_scene.RegionInfo.RegionSizeX)
val.X -= m_scene.RegionInfo.RegionSizeX;
if (val.Y >= m_scene.RegionInfo.RegionSizeY)
val.Y -= m_scene.RegionInfo.RegionSizeY;
if (val.X < 0)
val.X += Constants.RegionSize;
val.X += m_scene.RegionInfo.RegionSizeX;
if (val.Y < 0)
val.Y += Constants.RegionSize;
val.Y += m_scene.RegionInfo.RegionSizeY;
// If it's deleted, crossing was successful
if (IsDeleted)
@@ -577,9 +575,9 @@ namespace OpenSim.Region.Framework.Scenes
}
}
Vector3 oldp = AbsolutePosition;
val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f);
val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f);
val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight);
}
}
@@ -996,9 +994,9 @@ namespace OpenSim.Region.Framework.Scenes
maxX = -256f;
maxY = -256f;
maxZ = -256f;
minX = 256f;
minY = 256f;
minZ = 8192f;
minX = 10000f;
minY = 10000f;
minZ = 10000f;
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)

View File

@@ -76,6 +76,7 @@ namespace OpenSim.Region.Framework.Scenes
public class ScenePresence : EntityBase, IScenePresence
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly String LogHeader = "[SCENE PRESENCE]";
// ~ScenePresence()
// {
@@ -759,9 +760,8 @@ namespace OpenSim.Region.Framework.Scenes
foreach (ulong handle in seeds.Keys)
{
uint x, y;
Utils.LongToUInts(handle, out x, out y);
x = x / Constants.RegionSize;
y = y / Constants.RegionSize;
Util.RegionHandleToRegionLoc(handle, out x, out y);
if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
{
old.Add(handle);
@@ -783,9 +783,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
{
uint x, y;
Utils.LongToUInts(kvp.Key, out x, out y);
x = x / Constants.RegionSize;
y = y / Constants.RegionSize;
Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
}
}
@@ -1092,6 +1090,10 @@ namespace OpenSim.Region.Framework.Scenes
// before the inventory is processed in MakeRootAgent. This fixes a race condition
// related to the handling of attachments
//m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
/* RA 20140111: Commented out these TestBorderCross's.
* Not sure why this code is here. It is not checking all the borders
* and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below.
if (m_scene.TestBorderCross(pos, Cardinals.E))
{
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
@@ -1103,6 +1105,7 @@ namespace OpenSim.Region.Framework.Scenes
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
pos.Y = crossedBorder.BorderLine.Z - 1;
}
*/
CheckAndAdjustLandingPoint(ref pos);
@@ -1123,7 +1126,7 @@ namespace OpenSim.Region.Framework.Scenes
float posZLimit = 0;
if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
float newPosZ = posZLimit + localAVHeight / 2;
@@ -2400,7 +2403,7 @@ namespace OpenSim.Region.Framework.Scenes
if (regionCombinerModule != null)
regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
else
regionSize = new Vector2(Constants.RegionSize);
regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
if (pos.X < 0 || pos.X >= regionSize.X
|| pos.Y < 0 || pos.Y >= regionSize.Y
@@ -2418,8 +2421,8 @@ namespace OpenSim.Region.Framework.Scenes
// }
// Get terrain height for sub-region in a megaregion if necessary
int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
// If X and Y is NaN, target_region will be null
if (target_region == null)
@@ -2430,7 +2433,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
targetScene = m_scene;
float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
pos.Z = Math.Max(terrainHeight, pos.Z);
// Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -3466,10 +3469,14 @@ namespace OpenSim.Region.Framework.Scenes
if (!IsInTransit)
{
Vector3 pos2 = AbsolutePosition;
Vector3 origPosition = pos2;
Vector3 vel = Velocity;
int neighbor = 0;
int[] fix = new int[2];
// Compute the avatar position in the next physics tick.
// If the avatar will be crossing, we force the crossing to happen now
// in the hope that this will make the avatar movement smoother when crossing.
float timeStep = 0.1f;
pos2.X = pos2.X + (vel.X * timeStep);
pos2.Y = pos2.Y + (vel.Y * timeStep);
@@ -3477,111 +3484,44 @@ namespace OpenSim.Region.Framework.Scenes
if (!IsInTransit)
{
// m_log.DebugFormat(
// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
// pos2, Name, Scene.Name);
// Checks if where it's headed exists a region
bool needsTransit = false;
if (m_scene.TestBorderCross(pos2, Cardinals.W))
if (!m_scene.PositionIsInCurrentRegion(pos2))
{
if (m_scene.TestBorderCross(pos2, Cardinals.S))
m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}",
LogHeader, Name, Scene.Name, pos2);
// Disconnect from the current region
bool isFlying = Flying;
RemoveFromPhysicalScene();
// pos2 is the forcasted position so make that the 'current' position so the crossing
// code will move us into the newly addressed region.
m_pos = pos2;
if (CrossToNewRegion())
{
needsTransit = true;
neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
}
else if (m_scene.TestBorderCross(pos2, Cardinals.N))
{
needsTransit = true;
neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
AddToPhysicalScene(isFlying);
}
else
{
needsTransit = true;
neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
}
}
else if (m_scene.TestBorderCross(pos2, Cardinals.E))
{
if (m_scene.TestBorderCross(pos2, Cardinals.S))
{
needsTransit = true;
neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
}
else if (m_scene.TestBorderCross(pos2, Cardinals.N))
{
needsTransit = true;
neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
}
else
{
needsTransit = true;
neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
}
}
else if (m_scene.TestBorderCross(pos2, Cardinals.S))
{
needsTransit = true;
neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
}
else if (m_scene.TestBorderCross(pos2, Cardinals.N))
{
needsTransit = true;
neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
}
// Makes sure avatar does not end up outside region
if (neighbor <= 0)
{
if (needsTransit)
{
// Tried to make crossing happen but it failed.
if (m_requestedSitTargetUUID == UUID.Zero)
{
bool isFlying = Flying;
RemoveFromPhysicalScene();
m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader);
const float borderFudge = 0.1f;
Vector3 pos = AbsolutePosition;
if (AbsolutePosition.X < 0)
pos.X += Velocity.X * 2;
else if (AbsolutePosition.X > Constants.RegionSize)
pos.X -= Velocity.X * 2;
if (AbsolutePosition.Y < 0)
pos.Y += Velocity.Y * 2;
else if (AbsolutePosition.Y > Constants.RegionSize)
pos.Y -= Velocity.Y * 2;
if (origPosition.X < 0)
origPosition.X = borderFudge;
else if (origPosition.X > (float)m_scene.RegionInfo.RegionSizeX)
origPosition.X = (float)m_scene.RegionInfo.RegionSizeX - borderFudge;
if (origPosition.Y < 0)
origPosition.Y = borderFudge;
else if (origPosition.Y > (float)m_scene.RegionInfo.RegionSizeY)
origPosition.Y = (float)m_scene.RegionInfo.RegionSizeY - borderFudge;
Velocity = Vector3.Zero;
AbsolutePosition = pos;
// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
AddToPhysicalScene(isFlying);
}
}
}
else if (neighbor > 0)
{
if (!CrossToNewRegion())
{
if (m_requestedSitTargetUUID == UUID.Zero)
{
bool isFlying = Flying;
RemoveFromPhysicalScene();
Vector3 pos = AbsolutePosition;
if (AbsolutePosition.X < 0)
pos.X += Velocity.X * 2;
else if (AbsolutePosition.X > Constants.RegionSize)
pos.X -= Velocity.X * 2;
if (AbsolutePosition.Y < 0)
pos.Y += Velocity.Y * 2;
else if (AbsolutePosition.Y > Constants.RegionSize)
pos.Y -= Velocity.Y * 2;
Velocity = Vector3.Zero;
AbsolutePosition = pos;
AbsolutePosition = origPosition;
AddToPhysicalScene(isFlying);
}
}
}
}
else
@@ -3623,7 +3563,7 @@ namespace OpenSim.Region.Framework.Scenes
// Put the child agent back at the center
AbsolutePosition
= new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
= new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
Animator.ResetAnimations();
}
@@ -3650,9 +3590,7 @@ namespace OpenSim.Region.Framework.Scenes
if (handle != Scene.RegionInfo.RegionHandle)
{
uint x, y;
Utils.LongToUInts(handle, out x, out y);
x = x / Constants.RegionSize;
y = y / Constants.RegionSize;
Util.RegionHandleToRegionLoc(handle, out x, out y);
// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
@@ -3733,8 +3671,9 @@ namespace OpenSim.Region.Framework.Scenes
return;
//m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
// Find the distance (in meters) between the two regions
uint shiftx = Util.RegionToWorldLoc(rRegionX - tRegionX);
uint shifty = Util.RegionToWorldLoc(rRegionY - tRegionY);
Vector3 offset = new Vector3(shiftx, shifty, 0f);
@@ -4770,6 +4709,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
// Modify landing point based on possible banning, telehubs or parcel restrictions.
private void CheckAndAdjustLandingPoint(ref Vector3 pos)
{
string reason;

View File

@@ -25,13 +25,20 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Text;
using System.Reflection;
using System.Xml;
using System.Xml.Serialization;
using OpenSim.Data;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using System;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using OpenMetaverse;
using log4net;
namespace OpenSim.Region.Framework.Scenes
{
@@ -40,132 +47,146 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public class TerrainChannel : ITerrainChannel
{
private readonly bool[,] taint;
private double[,] map;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[TERRAIN CHANNEL]";
protected TerrainData m_terrainData;
public int Width { get { return m_terrainData.SizeX; } } // X dimension
// Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y
public int Height { get { return m_terrainData.SizeY; } } // Y dimension
public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
// Default, not-often-used builder
public TerrainChannel()
{
map = new double[Constants.RegionSize, Constants.RegionSize];
taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16];
PinHeadIsland();
m_terrainData = new HeightmapTerrainData((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
FlatLand();
// PinHeadIsland();
}
public TerrainChannel(String type)
// Create terrain of given size
public TerrainChannel(int pX, int pY)
{
map = new double[Constants.RegionSize, Constants.RegionSize];
taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16];
m_terrainData = new HeightmapTerrainData(pX, pY, (int)Constants.RegionHeight);
}
// Create terrain of specified size and initialize with specified terrain.
// TODO: join this with the terrain initializers.
public TerrainChannel(String type, int pX, int pY, int pZ)
{
m_terrainData = new HeightmapTerrainData(pX, pY, pZ);
if (type.Equals("flat"))
FlatLand();
else
PinHeadIsland();
}
public TerrainChannel(double[,] import)
// Create channel passed a heightmap and expected dimensions of the region.
// The heightmap might not fit the passed size so accomodations must be made.
public TerrainChannel(double[,] pM, int pSizeX, int pSizeY, int pAltitude)
{
map = import;
taint = new bool[import.GetLength(0),import.GetLength(1)];
int hmSizeX = pM.GetLength(0);
int hmSizeY = pM.GetLength(1);
m_terrainData = new HeightmapTerrainData(pSizeX, pSizeY, pAltitude);
for (int xx = 0; xx < pSizeX; xx++)
for (int yy = 0; yy < pSizeY; yy++)
if (xx > hmSizeX || yy > hmSizeY)
m_terrainData[xx, yy] = TerrainData.DefaultTerrainHeight;
else
m_terrainData[xx, yy] = (float)pM[xx, yy];
}
public TerrainChannel(bool createMap)
public TerrainChannel(TerrainData pTerrData)
{
if (createMap)
{
map = new double[Constants.RegionSize,Constants.RegionSize];
taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16];
}
}
public TerrainChannel(int w, int h)
{
map = new double[w,h];
taint = new bool[w / 16,h / 16];
m_terrainData = pTerrData;
}
#region ITerrainChannel Members
public int Width
{
get { return map.GetLength(0); }
}
public int Height
{
get { return map.GetLength(1); }
}
// ITerrainChannel.MakeCopy()
public ITerrainChannel MakeCopy()
{
TerrainChannel copy = new TerrainChannel(false);
copy.map = (double[,]) map.Clone();
return copy;
return this.Copy();
}
// ITerrainChannel.GetTerrainData()
public TerrainData GetTerrainData()
{
return m_terrainData;
}
// ITerrainChannel.GetFloatsSerialized()
// This one dimensional version is ordered so height = map[y*sizeX+x];
// DEPRECATED: don't use this function as it does not retain the dimensions of the terrain
// and the caller will probably do the wrong thing if the terrain is not the legacy 256x256.
public float[] GetFloatsSerialised()
{
// Move the member variables into local variables, calling
// member variables 256*256 times gets expensive
int w = Width;
int h = Height;
float[] heights = new float[w * h];
int points = Width * Height;
float[] heights = new float[points];
int i, j; // map coordinates
int idx = 0; // index into serialized array
for (i = 0; i < h; i++)
{
for (j = 0; j < w; j++)
int idx = 0;
for (int jj = 0; jj < Height; jj++)
for (int ii = 0; ii < Width; ii++)
{
heights[idx++] = (float)map[j, i];
heights[idx++] = m_terrainData[ii, jj];
}
return heights;
}
// ITerrainChannel.GetDoubles()
public double[,] GetDoubles()
{
double[,] heights = new double[Width, Height];
int idx = 0; // index into serialized array
for (int ii = 0; ii < Width; ii++)
{
for (int jj = 0; jj < Height; jj++)
{
heights[ii, jj] = (double)m_terrainData[ii, jj];
idx++;
}
}
return heights;
}
public double[,] GetDoubles()
{
return map;
}
// ITerrainChannel.this[x,y]
public double this[int x, int y]
{
get { return map[x, y]; }
get {
if (x < 0 || x >= Width || y < 0 || y >= Height)
return 0;
return (double)m_terrainData[x, y];
}
set
{
// Will "fix" terrain hole problems. Although not fantastically.
if (Double.IsNaN(value) || Double.IsInfinity(value))
return;
if (map[x, y] != value)
{
taint[x / 16, y / 16] = true;
map[x, y] = value;
}
m_terrainData[x, y] = (float)value;
}
}
// ITerrainChannel.GetHieghtAtXYZ(x, y, z)
public float GetHeightAtXYZ(float x, float y, float z)
{
if (x < 0 || x >= Width || y < 0 || y >= Height)
return 0;
return m_terrainData[(int)x, (int)y];
}
// ITerrainChannel.Tainted()
public bool Tainted(int x, int y)
{
if (taint[x / 16, y / 16])
{
taint[x / 16, y / 16] = false;
return true;
}
return false;
}
#endregion
public TerrainChannel Copy()
{
TerrainChannel copy = new TerrainChannel(false);
copy.map = (double[,]) map.Clone();
return copy;
return m_terrainData.IsTaintedAt(x, y);
}
// ITerrainChannel.SaveToXmlString()
public string SaveToXmlString()
{
XmlWriterSettings settings = new XmlWriterSettings();
@@ -181,13 +202,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
private void WriteXml(XmlWriter writer)
{
writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
ToXml(writer);
writer.WriteEndElement();
}
// ITerrainChannel.LoadFromXmlString()
public void LoadFromXmlString(string data)
{
StringReader sr = new StringReader(data);
@@ -199,12 +214,120 @@ namespace OpenSim.Region.Framework.Scenes
sr.Close();
}
private void ReadXml(XmlReader reader)
// ITerrainChannel.Merge
public void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement)
{
reader.ReadStartElement("TerrainMap");
FromXml(reader);
for (int xx = 0; xx < newTerrain.Width; xx++)
{
for (int yy = 0; yy < newTerrain.Height; yy++)
{
int dispX = (int)displacement.X;
int dispY = (int)displacement.Y;
float newHeight = (float)newTerrain[xx, yy] + displacement.Z;
if (radianRotation == 0)
{
// If no rotation, place the new height in the specified location
dispX += xx;
dispY += yy;
if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
{
m_terrainData[dispX, dispY] = newHeight;
}
}
else
{
// If rotating, we have to smooth the result because the conversion
// to ints will mean heightmap entries will not get changed
// First compute the rotation location for the new height.
dispX += (int)(rotationDisplacement.X
+ ((float)xx - rotationDisplacement.X) * Math.Cos(radianRotation)
- ((float)yy - rotationDisplacement.Y) * Math.Sin(radianRotation) );
dispY += (int)(rotationDisplacement.Y
+ ((float)xx - rotationDisplacement.X) * Math.Sin(radianRotation)
+ ((float)yy - rotationDisplacement.Y) * Math.Cos(radianRotation) );
if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
{
float oldHeight = m_terrainData[dispX, dispY];
// Smooth the heights around this location if the old height is far from this one
for (int sxx = dispX - 2; sxx < dispX + 2; sxx++)
{
for (int syy = dispY - 2; syy < dispY + 2; syy++)
{
if (sxx >= 0 && sxx < m_terrainData.SizeX && syy >= 0 && syy < m_terrainData.SizeY)
{
if (sxx == dispX && syy == dispY)
{
// Set height for the exact rotated point
m_terrainData[dispX, dispY] = newHeight;
}
else
{
if (Math.Abs(m_terrainData[sxx, syy] - newHeight) > 1f)
{
// If the adjacent height is far off, force it to this height
m_terrainData[sxx, syy] = newHeight;
}
}
}
}
}
}
if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
{
m_terrainData[dispX, dispY] = (float)newTerrain[xx, yy];
}
}
}
}
}
#endregion
public TerrainChannel Copy()
{
TerrainChannel copy = new TerrainChannel();
copy.m_terrainData = m_terrainData.Clone();
return copy;
}
private void WriteXml(XmlWriter writer)
{
if (Width == Constants.RegionSize && Height == Constants.RegionSize)
{
// Downward compatibility for legacy region terrain maps.
// If region is exactly legacy size, return the old format XML.
writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
ToXml(writer);
writer.WriteEndElement();
}
else
{
// New format XML that includes width and length.
writer.WriteStartElement(String.Empty, "TerrainMap2", String.Empty);
ToXml2(writer);
writer.WriteEndElement();
}
}
private void ReadXml(XmlReader reader)
{
// Check the first element. If legacy element, use the legacy reader.
if (reader.IsStartElement("TerrainMap"))
{
reader.ReadStartElement("TerrainMap");
FromXml(reader);
}
else
{
reader.ReadStartElement("TerrainMap2");
FromXml2(reader);
}
}
// Write legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
private void ToXml(XmlWriter xmlWriter)
{
float[] mapData = GetFloatsSerialised();
@@ -218,12 +341,15 @@ namespace OpenSim.Region.Framework.Scenes
serializer.Serialize(xmlWriter, buffer);
}
// Read legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
private void FromXml(XmlReader xmlReader)
{
XmlSerializer serializer = new XmlSerializer(typeof(byte[]));
byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
int index = 0;
m_terrainData = new HeightmapTerrainData(Height, Width, (int)Constants.RegionHeight);
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
@@ -236,35 +362,63 @@ namespace OpenSim.Region.Framework.Scenes
}
}
private class TerrainChannelXMLPackage
{
public int Version;
public int SizeX;
public int SizeY;
public int SizeZ;
public float CompressionFactor;
public short[] Map;
public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, short[] pMap)
{
Version = 1;
SizeX = pX;
SizeY = pY;
SizeZ = pZ;
CompressionFactor = pCompressionFactor;
Map = pMap;
}
}
// New terrain serialization format that includes the width and length.
private void ToXml2(XmlWriter xmlWriter)
{
TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
m_terrainData.GetCompressedMap());
XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
serializer.Serialize(xmlWriter, package);
}
// New terrain serialization format that includes the width and length.
private void FromXml2(XmlReader xmlReader)
{
XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
m_terrainData = new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
}
// Fill the heightmap with the center bump terrain
private void PinHeadIsland()
{
int x;
for (x = 0; x < Constants.RegionSize; x++)
for (int x = 0; x < Width; x++)
{
int y;
for (y = 0; y < Constants.RegionSize; y++)
for (int y = 0; y < Height; y++)
{
map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
double spherFacA = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 50) * 0.01;
double spherFacB = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 100) * 0.001;
if (map[x, y] < spherFacA)
map[x, y] = spherFacA;
if (map[x, y] < spherFacB)
map[x, y] = spherFacB;
m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d);
float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d);
if (m_terrainData[x, y]< spherFacA)
m_terrainData[x, y]= spherFacA;
if (m_terrainData[x, y]< spherFacB)
m_terrainData[x, y] = spherFacB;
}
}
}
private void FlatLand()
{
int x;
for (x = 0; x < Constants.RegionSize; x++)
{
int y;
for (y = 0; y < Constants.RegionSize; y++)
map[x, y] = 21;
}
m_terrainData.ClearLand();
}
}
}

View File

@@ -0,0 +1,944 @@
/*
* 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 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.
*/
/* Freely adapted from the Aurora version of the terrain compressor.
* Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
*/
using System;
using System.Reflection;
using log4net;
using OpenSim.Framework;
using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
using OpenMetaverse.Packets;
namespace OpenSim.Region.ClientStack.LindenUDP
{
public static class OpenSimTerrainCompressor
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[TERRAIN COMPRESSOR]";
public const int END_OF_PATCHES = 97;
private const float OO_SQRT2 = 0.7071067811865475244008443621049f;
private const int STRIDE = 264;
private const int ZERO_CODE = 0x0;
private const int ZERO_EOB = 0x2;
private const int POSITIVE_VALUE = 0x6;
private const int NEGATIVE_VALUE = 0x7;
private static readonly float[] DequantizeTable16 =
new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
private static readonly float[] DequantizeTable32 =
new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
//private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
private static readonly float[] QuantizeTable16 =
new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
static OpenSimTerrainCompressor()
{
// Initialize the decompression tables
BuildDequantizeTable16();
SetupCosines16();
BuildCopyMatrix16();
BuildQuantizeTable16();
}
// Unused: left for historical reference.
public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX,
int pRegionSizeY)
{
LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
{Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
// Should be enough to fit even the most poorly packed data
byte[] data = new byte[patches.Length*Constants.TerrainPatchSize*Constants.TerrainPatchSize*2];
BitPack bitpack = new BitPack(data, 0);
bitpack.PackBits(header.Stride, 16);
bitpack.PackBits(header.PatchSize, 8);
bitpack.PackBits(type, 8);
foreach (TerrainPatch t in patches)
CreatePatch(bitpack, t.Data, t.X, t.Y, pRegionSizeX, pRegionSizeY);
bitpack.PackBits(END_OF_PATCHES, 8);
layer.LayerData.Data = new byte[bitpack.BytePos + 1];
Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
return layer;
}
// Create a land packet for a single patch.
public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
{
int[] xPieces = new int[1];
int[] yPieces = new int[1];
xPieces[0] = patchX; // patch X dimension
yPieces[0] = patchY;
byte landPacketType = (byte)TerrainPatch.LayerType.Land;
if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
{
// libOMV does not have a packet type defined for the extended parcel format.
// We just happen to know the extended parcel format code is one more than the usual code.
landPacketType++;
}
return CreateLandPacket(terrData, xPieces, yPieces, landPacketType);
}
/// <summary>
/// Creates a LayerData packet for compressed land data given a full
/// simulator heightmap and an array of indices of patches to compress
/// </summary>
/// <param name="terrData">
/// Terrain data that can result in a meter square heightmap.
/// </param>
/// <param name="x">
/// Array of indexes in the grid of patches
/// for this simulator.
/// If creating a packet for multiple patches, there will be entries in
/// both the X and Y arrays for each of the patches.
/// For example if patches 1 and 17 are to be sent,
/// x[] = {1,1} and y[] = {0,1} which specifies the patches at
/// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
/// </param>
/// <param name="y">
/// Array of indexes in the grid of patches.
/// </param>
/// <param name="type"></param>
/// <param name="pRegionSizeX"></param>
/// <param name="pRegionSizeY"></param>
/// <returns></returns>
public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
{
LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
{Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
BitPack bitpack = new BitPack(data, 0);
bitpack.PackBits(header.Stride, 16);
bitpack.PackBits(header.PatchSize, 8);
bitpack.PackBits(type, 8);
for (int i = 0; i < x.Length; i++)
CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]);
bitpack.PackBits(END_OF_PATCHES, 8);
layer.LayerData.Data = new byte[bitpack.BytePos + 1];
Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
return layer;
}
// Unused: left for historical reference.
public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY)
{
TerrainPatch.Header header = PrescanPatch(patchData);
header.QuantWBits = 136;
if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
{
header.PatchIDs = (y & 0xFFFF);
header.PatchIDs += (x << 16);
}
else
{
header.PatchIDs = (y & 0x1F);
header.PatchIDs += (x << 5);
}
// NOTE: No idea what prequant and postquant should be or what they do
int wbits;
int[] patch = CompressPatch(patchData, header, 10, out wbits);
wbits = EncodePatchHeader(output, header, patch, (uint)pRegionSizeX, (uint)pRegionSizeY, wbits);
EncodePatch(output, patch, 0, wbits);
}
/// <summary>
/// Add a patch of terrain to a BitPacker
/// </summary>
/// <param name="output">BitPacker to write the patch to</param>
/// <param name="heightmap">
/// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
/// </param>
/// <param name="patchX">
/// X offset of the patch to create.
/// </param>
/// <param name="patchY">
/// Y offset of the patch to create.
/// </param>
/// <param name="pRegionSizeX"></param>
/// <param name="pRegionSizeY"></param>
public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
{
TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY);
header.QuantWBits = 136;
// If larger than legacy region size, pack patch X and Y info differently.
if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
{
header.PatchIDs = (patchY & 0xFFFF);
header.PatchIDs += (patchX << 16);
}
else
{
header.PatchIDs = (patchY & 0x1F);
header.PatchIDs += (patchX << 5);
}
// m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}",
// LogHeader, patchX, patchY, header.DCOffset, header.Range);
// NOTE: No idea what prequant and postquant should be or what they do
int wbits;
int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
EncodePatch(output, patch, 0, wbits);
}
private static TerrainPatch.Header PrescanPatch(float[] patch)
{
TerrainPatch.Header header = new TerrainPatch.Header();
float zmax = -99999999.0f;
float zmin = 99999999.0f;
for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
{
float val = patch[i];
if (val > zmax) zmax = val;
if (val < zmin) zmin = val;
}
header.DCOffset = zmin;
header.Range = (int) ((zmax - zmin) + 1.0f);
return header;
}
// Scan the height info we're returning and return a patch packet header for this patch.
private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY)
{
TerrainPatch.Header header = new TerrainPatch.Header();
float zmax = -99999999.0f;
float zmin = 99999999.0f;
for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++)
{
for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++)
{
float val = terrData[i, j];
if (val > zmax) zmax = val;
if (val < zmin) zmin = val;
}
}
header.DCOffset = zmin;
header.Range = (int)(zmax - zmin + 1.0f);
return header;
}
public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
{
TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
// Quantized word bits
if (header.QuantWBits == END_OF_PATCHES)
return header;
// DC offset
header.DCOffset = bitpack.UnpackFloat();
// Range
header.Range = bitpack.UnpackBits(16);
// Patch IDs (10 bits)
header.PatchIDs = bitpack.UnpackBits(10);
// Word bits
header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
return header;
}
private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX,
uint pRegionSizeY, int wbits)
{
/*
int temp;
int wbits = (header.QuantWBits & 0x0f) + 2;
uint maxWbits = (uint)wbits + 5;
uint minWbits = ((uint)wbits >> 1);
int wbitsMaxValue;
*/
// goal is to determ minimum number of bits to use so all data fits
/*
wbits = (int)minWbits;
wbitsMaxValue = (1 << wbits);
for (int i = 0; i < patch.Length; i++)
{
temp = patch[i];
if (temp != 0)
{
// Get the absolute value
if (temp < 0) temp *= -1;
no coments..
for (int j = (int)maxWbits; j > (int)minWbits; j--)
{
if ((temp & (1 << j)) != 0)
{
if (j > wbits) wbits = j;
break;
}
}
while (temp > wbitsMaxValue)
{
wbits++;
if (wbits == maxWbits)
goto Done;
wbitsMaxValue = 1 << wbits;
}
}
}
Done:
// wbits += 1;
*/
// better check
if (wbits > 17)
wbits = 16;
else if (wbits < 3)
wbits = 3;
header.QuantWBits &= 0xf0;
header.QuantWBits |= (wbits - 2);
output.PackBits(header.QuantWBits, 8);
output.PackFloat(header.DCOffset);
output.PackBits(header.Range, 16);
if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
output.PackBits(header.PatchIDs, 32);
else
output.PackBits(header.PatchIDs, 10);
return wbits;
}
private static void IDCTColumn16(float[] linein, float[] lineout, int column)
{
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
float total = OO_SQRT2*linein[column];
for (int u = 1; u < Constants.TerrainPatchSize; u++)
{
int usize = u*Constants.TerrainPatchSize;
total += linein[usize + column]*CosineTable16[usize + n];
}
lineout[Constants.TerrainPatchSize*n + column] = total;
}
}
private static void IDCTLine16(float[] linein, float[] lineout, int line)
{
const float oosob = 2.0f/Constants.TerrainPatchSize;
int lineSize = line*Constants.TerrainPatchSize;
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
float total = OO_SQRT2*linein[lineSize];
for (int u = 1; u < Constants.TerrainPatchSize; u++)
{
total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n];
}
lineout[lineSize + n] = total*oosob;
}
}
/*
private static void DCTLine16(float[] linein, float[] lineout, int line)
{
float total = 0.0f;
int lineSize = line * Constants.TerrainPatchSize;
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
total += linein[lineSize + n];
}
lineout[lineSize] = OO_SQRT2 * total;
int uptr = 0;
for (int u = 1; u < Constants.TerrainPatchSize; u++)
{
total = 0.0f;
uptr += Constants.TerrainPatchSize;
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
total += linein[lineSize + n] * CosineTable16[uptr + n];
}
lineout[lineSize + u] = total;
}
}
*/
private static void DCTLine16(float[] linein, float[] lineout, int line)
{
// outputs transpose data (lines exchanged with coluns )
// so to save a bit of cpu when doing coluns
float total = 0.0f;
int lineSize = line*Constants.TerrainPatchSize;
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
total += linein[lineSize + n];
}
lineout[line] = OO_SQRT2*total;
for (int u = Constants.TerrainPatchSize;
u < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
u += Constants.TerrainPatchSize)
{
total = 0.0f;
for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
{
total += linein[ptrn]*CosineTable16[ptru];
}
lineout[line + u] = total;
}
}
/*
private static void DCTColumn16(float[] linein, int[] lineout, int column)
{
float total = 0.0f;
// const float oosob = 2.0f / Constants.TerrainPatchSize;
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
total += linein[Constants.TerrainPatchSize * n + column];
}
// lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize)
{
total = 0.0f;
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
}
// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]);
}
}
*/
private static void DCTColumn16(float[] linein, int[] lineout, int column)
{
// input columns are in fact stored in lines now
float total = 0.0f;
// const float oosob = 2.0f / Constants.TerrainPatchSize;
int inlinesptr = Constants.TerrainPatchSize*column;
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
total += linein[inlinesptr + n];
}
// lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
for (int uptr = Constants.TerrainPatchSize;
uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
uptr += Constants.TerrainPatchSize)
{
total = 0.0f;
for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
{
total += linein[n]*CosineTable16[ptru];
}
// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]);
}
}
private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits)
{
// input columns are in fact stored in lines now
bool dowbits = wbits != maxwbits;
int wbitsMaxValue = 1 << wbits;
float total = 0.0f;
// const float oosob = 2.0f / Constants.TerrainPatchSize;
int inlinesptr = Constants.TerrainPatchSize*column;
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
total += linein[inlinesptr + n];
}
// lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
lineout[CopyMatrix16[column]] = tmp;
if (dowbits)
{
if (tmp < 0) tmp *= -1;
while (tmp > wbitsMaxValue)
{
wbits++;
wbitsMaxValue = 1 << wbits;
if (wbits == maxwbits)
{
dowbits = false;
break;
}
}
}
for (int uptr = Constants.TerrainPatchSize;
uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
uptr += Constants.TerrainPatchSize)
{
total = 0.0f;
for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
{
total += linein[n]*CosineTable16[ptru];
}
tmp = (int) (total*QuantizeTable16[uptr + column]);
lineout[CopyMatrix16[uptr + column]] = tmp;
if (dowbits)
{
if (tmp < 0) tmp *= -1;
while (tmp > wbitsMaxValue)
{
wbits++;
wbitsMaxValue = 1 << wbits;
if (wbits == maxwbits)
{
dowbits = false;
break;
}
}
}
}
return wbits;
}
public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
{
for (int n = 0; n < size*size; n++)
{
// ?
int temp = bitpack.UnpackBits(1);
if (temp != 0)
{
// Value or EOB
temp = bitpack.UnpackBits(1);
if (temp != 0)
{
// Value
temp = bitpack.UnpackBits(1);
if (temp != 0)
{
// Negative
temp = bitpack.UnpackBits((int) header.WordBits);
patches[n] = temp*-1;
}
else
{
// Positive
temp = bitpack.UnpackBits((int) header.WordBits);
patches[n] = temp;
}
}
else
{
// Set the rest to zero
// TODO: This might not be necessary
for (int o = n; o < size*size; o++)
{
patches[o] = 0;
}
break;
}
}
else
{
patches[n] = 0;
}
}
}
private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
{
int maxwbitssize = (1 << wbits) - 1;
if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0)
{
Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
return;
}
if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0;
for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
{
int temp = patch[i];
if (temp == 0)
{
bool eob = true;
for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
{
if (patch[j] != 0)
{
eob = false;
break;
}
}
if (eob)
{
output.PackBits(ZERO_EOB, 2);
return;
}
output.PackBits(ZERO_CODE, 1);
}
else
{
if (temp < 0)
{
temp *= -1;
if (temp > maxwbitssize) temp = maxwbitssize;
output.PackBits(NEGATIVE_VALUE, 3);
output.PackBits(temp, wbits);
}
else
{
if (temp > maxwbitssize) temp = maxwbitssize;
output.PackBits(POSITIVE_VALUE, 3);
output.PackBits(temp, wbits);
}
}
}
}
public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group)
{
float[] block = new float[group.PatchSize*group.PatchSize];
float[] output = new float[group.PatchSize*group.PatchSize];
int prequant = (header.QuantWBits >> 4) + 2;
int quantize = 1 << prequant;
float ooq = 1.0f/quantize;
float mult = ooq*header.Range;
float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
if (group.PatchSize == Constants.TerrainPatchSize)
{
for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
{
block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n];
}
float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
for (int o = 0; o < Constants.TerrainPatchSize; o++)
IDCTColumn16(block, ftemp, o);
for (int o = 0; o < Constants.TerrainPatchSize; o++)
IDCTLine16(ftemp, block, o);
}
else
{
for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
{
block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n];
}
Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error);
}
for (int j = 0; j < block.Length; j++)
{
output[j] = block[j]*mult + addval;
}
return output;
}
private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
{
float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
int wordsize = (prequant - 2) & 0x0f;
float oozrange = 1.0f/header.Range;
float range = (1 << prequant);
float premult = oozrange*range;
float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
header.QuantWBits = wordsize;
header.QuantWBits |= wordsize << 4;
int k = 0;
for (int j = 0; j < Constants.TerrainPatchSize; j++)
{
for (int i = 0; i < Constants.TerrainPatchSize; i++)
block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub;
}
float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
int maxWbits = prequant + 5;
wbits = (prequant >> 1);
for (int o = 0; o < Constants.TerrainPatchSize; o++)
DCTLine16(block, ftemp, o);
for (int o = 0; o < Constants.TerrainPatchSize; o++)
wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
return itemp;
}
private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits)
{
float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
float oozrange = 1.0f/header.Range;
float range = (1 << prequant);
float premult = oozrange*range;
float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
int wordsize = (prequant - 2) & 0x0f;
header.QuantWBits = wordsize;
header.QuantWBits |= wordsize << 4;
int k = 0;
for (int j = 0; j < Constants.TerrainPatchSize; j++)
{
for (int i = 0; i < Constants.TerrainPatchSize; i++)
block[k++] = patchData[j, i]*premult - sub;
}
float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
int maxWbits = prequant + 5;
wbits = (prequant >> 1);
for (int o = 0; o < Constants.TerrainPatchSize; o++)
DCTLine16(block, ftemp, o);
for (int o = 0; o < Constants.TerrainPatchSize; o++)
wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
return itemp;
}
private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
int prequant, out int wbits)
{
float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
int wordsize = prequant;
float oozrange = 1.0f/header.Range;
float range = (1 << prequant);
float premult = oozrange*range;
float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
header.QuantWBits = wordsize - 2;
header.QuantWBits |= (prequant - 2) << 4;
int k = 0;
int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ?
(terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY;
yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ?
(terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX;
xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize;
for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++)
{
for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
{
block[k++] = terrData[xx, yy] * premult - sub;
}
}
float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
int maxWbits = prequant + 5;
wbits = (prequant >> 1);
for (int o = 0; o < Constants.TerrainPatchSize; o++)
DCTLine16(block, ftemp, o);
for (int o = 0; o < Constants.TerrainPatchSize; o++)
wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
return itemp;
}
#region Initialization
private static void BuildDequantizeTable16()
{
for (int j = 0; j < Constants.TerrainPatchSize; j++)
{
for (int i = 0; i < Constants.TerrainPatchSize; i++)
{
DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j);
}
}
}
private static void BuildQuantizeTable16()
{
const float oosob = 2.0f/Constants.TerrainPatchSize;
for (int j = 0; j < Constants.TerrainPatchSize; j++)
{
for (int i = 0; i < Constants.TerrainPatchSize; i++)
{
// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j));
QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
}
}
}
private static void SetupCosines16()
{
const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize;
for (int u = 0; u < Constants.TerrainPatchSize; u++)
{
for (int n = 0; n < Constants.TerrainPatchSize; n++)
{
CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz);
}
}
}
private static void BuildCopyMatrix16()
{
bool diag = false;
bool right = true;
int i = 0;
int j = 0;
int count = 0;
while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
{
CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
if (!diag)
{
if (right)
{
if (i < Constants.TerrainPatchSize - 1) i++;
else j++;
right = false;
diag = true;
}
else
{
if (j < Constants.TerrainPatchSize - 1) j++;
else i++;
right = true;
diag = true;
}
}
else
{
if (right)
{
i++;
j--;
if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
}
else
{
i--;
j++;
if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
}
}
}
}
#endregion Initialization
}
}

View File

@@ -161,7 +161,7 @@ namespace OpenSim.Region.Framework.Scenes
{
// Get the prim's default texture. This will be used for faces which don't have their own texture
if (textureEntry.DefaultTexture != null)
assetUuids[textureEntry.DefaultTexture.TextureID] = (sbyte)AssetType.Texture;
GatherTextureEntryAssets(textureEntry.DefaultTexture, assetUuids);
if (textureEntry.FaceTextures != null)
{
@@ -169,7 +169,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
{
if (texture != null)
assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
GatherTextureEntryAssets(texture, assetUuids);
}
}
}
@@ -233,6 +233,19 @@ namespace OpenSim.Region.Framework.Scenes
}
}
/// <summary>
/// Gather all the asset uuids found in one face of a Texture Entry.
/// </summary>
private void GatherTextureEntryAssets(Primitive.TextureEntryFace texture, IDictionary<UUID, sbyte> assetUuids)
{
assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
if (texture.MaterialID != UUID.Zero)
{
GatherAssetUuids(texture.MaterialID, (sbyte)OpenSimAssetType.Material, assetUuids);
}
}
// /// <summary>
// /// The callback made when we request the asset for an object from the asset service.
// /// </summary>

View File

@@ -516,7 +516,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public Vector3 StartPos
{
get { return new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 50); }
get { return new Vector3(m_scene.RegionInfo.RegionSizeX * 0.5f, m_scene.RegionInfo.RegionSizeY * 0.5f, 50f); }
set { }
}

View File

@@ -52,6 +52,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
// Local constants
// This computation is not the real region center if the region is larger than 256.
// This computation isn't fixed because there is not a handle back to the region.
private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
private static readonly char[] CS_SPACE = { ' ' };

View File

@@ -44,6 +44,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// This computation is not the real region center if the region is larger than 256.
// This computation isn't fixed because there is not a handle back to the region.
private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
private const int DEBUG_CHANNEL = 2147483647;

View File

@@ -170,7 +170,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
c.Channel = m_channelNotify;
c.Message += numScriptsFailed.ToString() + "," + message;
c.Type = ChatTypeEnum.Region;
c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
if (m_scene != null)
c.Position = new Vector3((m_scene.RegionInfo.RegionSizeX * 0.5f), (m_scene.RegionInfo.RegionSizeY * 0.5f), 30);
else
c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
c.Sender = null;
c.SenderUUID = UUID.Zero;
c.Scene = m_scene;
@@ -301,7 +304,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
finally
{
if (os != null)
os.Close();
os.Dispose();
}
}
}

View File

@@ -61,7 +61,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
private readonly string m_firstname;
private readonly string m_lastname;
private readonly Vector3 m_startPos;
private readonly UUID m_uuid = UUID.Random();
private readonly UUID m_uuid;
private readonly Scene m_scene;
private readonly UUID m_ownerID;
@@ -71,6 +71,19 @@ namespace OpenSim.Region.OptionalModules.World.NPC
m_firstname = firstname;
m_lastname = lastname;
m_startPos = position;
m_uuid = UUID.Random();
m_scene = scene;
m_ownerID = ownerID;
SenseAsAgent = senseAsAgent;
}
public NPCAvatar(
string firstname, string lastname, UUID agentID, Vector3 position, UUID ownerID, bool senseAsAgent, Scene scene)
{
m_firstname = firstname;
m_lastname = lastname;
m_startPos = position;
m_uuid = agentID;
m_scene = scene;
m_ownerID = ownerID;
SenseAsAgent = senseAsAgent;

View File

@@ -140,8 +140,30 @@ namespace OpenSim.Region.OptionalModules.World.NPC
Vector3 position, UUID owner, bool senseAsAgent, Scene scene,
AvatarAppearance appearance)
{
NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position,
owner, senseAsAgent, scene);
return CreateNPC(firstname, lastname, position, UUID.Zero, owner, senseAsAgent, scene, appearance);
}
public UUID CreateNPC(string firstname, string lastname,
Vector3 position, UUID agentID, UUID owner, bool senseAsAgent, Scene scene,
AvatarAppearance appearance)
{
NPCAvatar npcAvatar = null;
try
{
if (agentID == UUID.Zero)
npcAvatar = new NPCAvatar(firstname, lastname, position,
owner, senseAsAgent, scene);
else
npcAvatar = new NPCAvatar(firstname, lastname, agentID, position,
owner, senseAsAgent, scene);
}
catch (Exception e)
{
m_log.Info("[NPC MODULE]: exception creating NPC avatar: " + e.ToString());
return UUID.Zero;
}
npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0,
int.MaxValue);

View File

@@ -748,8 +748,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
position.X = s_tree.AbsolutePosition.X + (float)randX;
position.Y = s_tree.AbsolutePosition.Y + (float)randY;
if (position.X <= ((int)Constants.RegionSize - 1) && position.X >= 0 &&
position.Y <= ((int)Constants.RegionSize - 1) && position.Y >= 0 &&
if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 &&
position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 &&
Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range)
{
UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;

View File

@@ -1311,7 +1311,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
/* TODO */
ConfigurationParameters[] configparms = new ConfigurationParameters[1];
configparms[0] = parms;
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
Vector3 worldExtent = maxPosition;
m_maxCollisions = maxCollisions;
m_maxUpdatesPerFrame = maxUpdates;
specialCollisionObjects = new Dictionary<uint, GhostObject>();

View File

@@ -538,7 +538,7 @@ public static class BSParam
(s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ),
new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
(float)BSTerrainPhys.TerrainImplementation.Mesh ),
(float)BSTerrainPhys.TerrainImplementation.Heightmap ),
new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
2 ),
new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,

View File

@@ -376,18 +376,19 @@ public class BSPrim : BSPhysObject
{
bool ret = false;
uint wayOutThere = Constants.RegionSize * Constants.RegionSize;
int wayOverThere = -1000;
int wayOutThere = 10000;
// There have been instances of objects getting thrown way out of bounds and crashing
// the border crossing code.
if ( RawPosition.X < -Constants.RegionSize || RawPosition.X > wayOutThere
|| RawPosition.Y < -Constants.RegionSize || RawPosition.Y > wayOutThere
|| RawPosition.Z < -Constants.RegionSize || RawPosition.Z > wayOutThere)
if ( RawPosition.X < wayOverThere || RawPosition.X > wayOutThere
|| RawPosition.Y < wayOverThere || RawPosition.X > wayOutThere
|| RawPosition.Z < wayOverThere || RawPosition.X > wayOutThere)
{
RawPosition = new OMV.Vector3(10, 10, 50);
ZeroMotion(inTaintTime);
ret = true;
}
if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity)
if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocitySquared)
{
RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity);
ret = true;

View File

@@ -208,7 +208,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
Name = EngineType + "/" + RegionName;
}
// Old version of initialization that assumes legacy sized regions (256x256)
public override void Initialise(IMesher meshmerizer, IConfigSource config)
{
m_log.ErrorFormat("{0} WARNING WARNING WARNING! BulletSim initialized without region extent specification. Terrain will be messed up.");
Vector3 regionExtent = new Vector3( Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
Initialise(meshmerizer, config, regionExtent);
}
public override void Initialise(IMesher meshmerizer, IConfigSource config, Vector3 regionExtent)
{
mesher = meshmerizer;
_taintOperations = new List<TaintCallbackEntry>();
@@ -226,6 +235,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Set default values for physics parameters plus any overrides from the ini file
GetInitialParameterValues(config);
// Force some parameters to values depending on other configurations
// Only use heightmap terrain implementation if terrain larger than legacy size
if ((uint)regionExtent.X > Constants.RegionSize || (uint)regionExtent.Y > Constants.RegionSize)
{
m_log.WarnFormat("{0} Forcing terrain implementation to heightmap for large region", LogHeader);
BSParam.TerrainImplementation = (float)BSTerrainPhys.TerrainImplementation.Heightmap;
}
// Get the connection to the physics engine (could be native or one of many DLLs)
PE = SelectUnderlyingBulletEngine(BulletEngineName);
@@ -250,13 +267,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// a child in a mega-region.
// Bullet actually doesn't care about the extents of the simulated
// area. It tracks active objects no matter where they are.
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
Vector3 worldExtent = regionExtent;
World = PE.Initialize(worldExtent, Params, m_maxCollisionsPerFrame, ref m_collisionArray, m_maxUpdatesPerFrame, ref m_updateArray);
Constraints = new BSConstraintCollection(World);
TerrainManager = new BSTerrainManager(this);
TerrainManager = new BSTerrainManager(this, worldExtent);
TerrainManager.CreateInitialGroundPlaneAndTerrain();
// Put some informational messages into the log file.

View File

@@ -58,7 +58,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
{
initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
}
m_mapInfo = new BulletHMapInfo(id, initialMap);
m_mapInfo = new BulletHMapInfo(id, initialMap, regionSize.X, regionSize.Y);
m_mapInfo.minCoords = minTerrainCoords;
m_mapInfo.maxCoords = maxTerrainCoords;
m_mapInfo.terrainRegionBase = TerrainBase;
@@ -72,7 +72,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
Vector3 minCoords, Vector3 maxCoords)
: base(physicsScene, regionBase, id)
{
m_mapInfo = new BulletHMapInfo(id, initialMap);
m_mapInfo = new BulletHMapInfo(id, initialMap, maxCoords.X - minCoords.X, maxCoords.Y - minCoords.Y);
m_mapInfo.minCoords = minCoords;
m_mapInfo.maxCoords = maxCoords;
m_mapInfo.minZ = minCoords.Z;

View File

@@ -111,9 +111,11 @@ public sealed class BSTerrainManager : IDisposable
private Vector3 m_worldMax;
private PhysicsScene MegaRegionParentPhysicsScene { get; set; }
public BSTerrainManager(BSScene physicsScene)
public BSTerrainManager(BSScene physicsScene, Vector3 regionSize)
{
m_physicsScene = physicsScene;
DefaultRegionSize = regionSize;
m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
// Assume one region of default size
@@ -268,7 +270,7 @@ public sealed class BSTerrainManager : IDisposable
{
// There is already a terrain in this spot. Free the old and build the new.
DetailLog("{0},BSTErrainManager.UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
BSScene.DetailLogZero, id, terrainRegionBase, minCoords, maxCoords);
// Remove old terrain from the collection
m_terrains.Remove(terrainRegionBase);

View File

@@ -165,14 +165,15 @@ public class BulletConstraint
// than making copies.
public class BulletHMapInfo
{
public BulletHMapInfo(uint id, float[] hm) {
public BulletHMapInfo(uint id, float[] hm, float pSizeX, float pSizeY) {
ID = id;
heightMap = hm;
terrainRegionBase = OMV.Vector3.Zero;
minCoords = new OMV.Vector3(100f, 100f, 25f);
maxCoords = new OMV.Vector3(101f, 101f, 26f);
minZ = maxZ = 0f;
sizeX = sizeY = 256f;
sizeX = pSizeX;
sizeY = pSizeY;
}
public uint ID;
public float[] heightMap;

View File

@@ -32,6 +32,7 @@ using System.Reflection;
using Nini.Config;
using log4net;
using OpenSim.Framework;
using OpenMetaverse;
namespace OpenSim.Region.Physics.Manager
{
@@ -66,7 +67,8 @@ namespace OpenSim.Region.Physics.Manager
/// <param name="meshEngineName"></param>
/// <param name="config"></param>
/// <returns></returns>
public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName, IConfigSource config, string regionName)
public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName,
IConfigSource config, string regionName, Vector3 regionExtent)
{
if (String.IsNullOrEmpty(physEngineName))
{
@@ -94,7 +96,7 @@ namespace OpenSim.Region.Physics.Manager
{
m_log.Info("[PHYSICS]: creating " + physEngineName);
PhysicsScene result = _PhysPlugins[physEngineName].GetScene(regionName);
result.Initialise(meshEngine, config);
result.Initialise(meshEngine, config, regionExtent);
return result;
}
else

View File

@@ -126,8 +126,17 @@ namespace OpenSim.Region.Physics.Manager
}
}
// Deprecated. Do not use this for new physics engines.
public abstract void Initialise(IMesher meshmerizer, IConfigSource config);
// For older physics engines that do not implement non-legacy region sizes.
// If the physics engine handles the region extent feature, it overrides this function.
public virtual void Initialise(IMesher meshmerizer, IConfigSource config, Vector3 regionExtent)
{
// If not overridden, call the old initialization entry.
Initialise(meshmerizer, config);
}
/// <summary>
/// Add an avatar
/// </summary>

View File

@@ -64,12 +64,12 @@ namespace OpenSim.Region.RegionCombinerModule
/// <summary>
/// The X meters position of this connection.
/// </summary>
public uint PosX { get { return X * Constants.RegionSize; } }
public uint PosX { get { return Util.RegionToWorldLoc(X); } }
/// <summary>
/// The Y meters co-ordinate of this connection.
/// </summary>
public uint PosY { get { return Y * Constants.RegionSize; } }
public uint PosY { get { return Util.RegionToWorldLoc(Y); } }
/// <summary>
/// The size of the megaregion in meters.

View File

@@ -101,7 +101,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// </summary>
protected TaskInventoryItem m_item;
protected bool throwErrorOnNotImplemented = true;
protected bool throwErrorOnNotImplemented = false;
protected AsyncCommandManager AsyncCommands = null;
protected float m_ScriptDelayFactor = 1.0f;
protected float m_ScriptDistanceFactor = 1.0f;
@@ -261,7 +261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((item = GetScriptByName(name)) != UUID.Zero)
m_ScriptEngine.ResetScript(item);
else
ShoutError("llResetOtherScript: script "+name+" not found");
Error("llResetOtherScript", "Can't find script '" + name + "'");
}
public LSL_Integer llGetScriptState(string name)
@@ -275,7 +275,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return m_ScriptEngine.GetScriptState(item) ?1:0;
}
ShoutError("llGetScriptState: script "+name+" not found");
Error("llGetScriptState", "Can't find script '" + name + "'");
// If we didn't find it, then it's safe to
// assume it is not running.
@@ -298,7 +298,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else
{
ShoutError("llSetScriptState: script "+name+" not found");
Error("llSetScriptState", "Can't find script '" + name + "'");
}
}
@@ -890,7 +890,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
if (channelID == 0)
{
LSLError("Cannot use llRegionSay() on channel 0");
Error("llRegionSay", "Cannot use on channel 0");
return;
}
@@ -2107,7 +2107,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
//
// This workaround is to prevent silent failure of this function.
// According to the specification on the SL Wiki, providing a position outside of the
if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize)
if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
{
return 0;
}
@@ -2117,9 +2117,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.ParentGroup.IsAttachment || // return FALSE if attachment
(
pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
)
)
@@ -2553,9 +2553,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llSound(string sound, double volume, int queue, int loop)
{
m_host.AddScriptLPS(1);
// This function has been deprecated
// see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
Deprecated("llSound");
Deprecated("llSound", "Use llPlaySound instead");
}
// Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
@@ -2886,7 +2884,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
{
LSLError("No permissions to give money");
Error("llGiveMoney", "No permissions to give money");
return;
}
@@ -2894,7 +2892,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!UUID.TryParse(destination, out toID))
{
LSLError("Bad key in llGiveMoney");
Error("llGiveMoney", "Bad key in llGiveMoney");
return;
}
@@ -2914,28 +2912,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
{
m_host.AddScriptLPS(1);
Deprecated("llMakeExplosion");
Deprecated("llMakeExplosion", "Use llParticleSystem instead");
ScriptSleep(100);
}
public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
{
m_host.AddScriptLPS(1);
Deprecated("llMakeFountain");
Deprecated("llMakeFountain", "Use llParticleSystem instead");
ScriptSleep(100);
}
public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
{
m_host.AddScriptLPS(1);
Deprecated("llMakeSmoke");
Deprecated("llMakeSmoke", "Use llParticleSystem instead");
ScriptSleep(100);
}
public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
{
m_host.AddScriptLPS(1);
Deprecated("llMakeFire");
Deprecated("llMakeFire", "Use llParticleSystem instead");
ScriptSleep(100);
}
@@ -2957,13 +2955,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (item == null)
{
llSay(0, "Could not find object " + inventory);
Error("llRezAtRoot", "Can't find object '" + inventory + "'");
return;
}
if (item.InvType != (int)InventoryType.Object)
{
llSay(0, "Unable to create requested object. Object is missing from database.");
Error("llRezAtRoot", "Can't create requested object; object is missing from database");
return;
}
@@ -3053,7 +3051,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llStopLookAt()
{
m_host.AddScriptLPS(1);
// NotImplemented("llStopLookAt");
m_host.StopLookAt();
}
@@ -3237,13 +3234,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llTakeCamera(string avatar)
{
m_host.AddScriptLPS(1);
Deprecated("llTakeCamera");
Deprecated("llTakeCamera", "Use llSetCameraParams instead");
}
public void llReleaseCamera(string avatar)
{
m_host.AddScriptLPS(1);
Deprecated("llReleaseCamera");
Deprecated("llReleaseCamera", "Use llClearCameraParams instead");
}
public LSL_String llGetOwner()
@@ -3320,7 +3317,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
if (emailModule == null)
{
ShoutError("llEmail: email module not configured");
Error("llEmail", "Email module not configured");
return;
}
@@ -3334,7 +3331,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
if (emailModule == null)
{
ShoutError("llGetNextEmail: email module not configured");
Error("llGetNextEmail", "Email module not configured");
return;
}
Email email;
@@ -3419,17 +3416,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
catch (NotImplementedException)
{
// Currently not implemented in DotNetEngine only XEngine
NotImplemented("llMinEventDelay in DotNetEngine");
NotImplemented("llMinEventDelay", "In DotNetEngine");
}
}
/// <summary>
/// llSoundPreload is deprecated. In SL this appears to do absolutely nothing
/// and is documented to have no delay.
/// </summary>
public void llSoundPreload(string sound)
{
m_host.AddScriptLPS(1);
Deprecated("llSoundPreload", "Use llPreloadSound instead");
}
public void llRotLookAt(LSL_Rotation target, double strength, double damping)
@@ -3734,7 +3728,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
&& !m_automaticLinkPermission)
{
ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set");
return;
}
@@ -3789,7 +3783,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
&& !m_automaticLinkPermission)
{
ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set");
return;
}
@@ -4009,7 +4003,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!UUID.TryParse(destination, out destId))
{
llSay(0, "Could not parse key " + destination);
Error("llGiveInventory", "Can't parse destination key '" + destination + "'");
return;
}
@@ -4017,8 +4011,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (item == null)
{
llSay(0, String.Format("Could not find object '{0}'", inventory));
throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
Error("llGiveInventory", "Can't find inventory object '" + inventory + "'");
}
UUID objId = item.ItemID;
@@ -4042,7 +4035,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (account == null)
{
llSay(0, "Can't find destination "+destId.ToString());
Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'");
return;
}
}
@@ -4244,10 +4237,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
DataserverPlugin.RegisterRequest(m_host.LocalId,
m_item.ItemID, item.AssetID.ToString());
Vector3 region = new Vector3(
World.RegionInfo.RegionLocX * Constants.RegionSize,
World.RegionInfo.RegionLocY * Constants.RegionSize,
0);
Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
World.AssetService.Get(item.AssetID.ToString(), this,
delegate(string i, object sender, AssetBase a)
@@ -4336,7 +4326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
UUID agentId = new UUID();
ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y);
ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y);
if (UUID.TryParse(agent, out agentId))
{
@@ -4397,17 +4387,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID av = new UUID();
if (!UUID.TryParse(agent,out av))
{
LSLError("First parameter to llTextBox needs to be a key");
Error("llTextBox", "First parameter must be a key");
return;
}
if (message == string.Empty)
{
ShoutError("Trying to use llTextBox with empty message.");
Error("llTextBox", "Empty message");
}
else if (message.Length > 512)
{
ShoutError("Trying to use llTextBox with message over 512 characters.");
Error("llTextBox", "Message more than 512 characters");
}
else
{
@@ -5481,7 +5471,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Vector llGetRegionCorner()
{
m_host.AddScriptLPS(1);
return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
}
/// <summary>
@@ -5628,7 +5618,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSL_Float mag;
if (dir.x > 0)
{
mag = (Constants.RegionSize - pos.x) / dir.x;
mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
}
else
{
@@ -5639,7 +5629,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
edge.y = pos.y + (dir.y * mag);
if (edge.y > Constants.RegionSize || edge.y < 0)
if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
{
// Y goes out of bounds first
edge.y = dir.y / Math.Abs(dir.y);
@@ -6817,17 +6807,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID av = new UUID();
if (!UUID.TryParse(avatar,out av))
{
LSLError("First parameter to llDialog needs to be a key");
Error("llDialog", "First parameter must be a key");
return;
}
if (buttons.Length < 1)
{
LSLError("No less than 1 button can be shown");
Error("llDialog", "At least 1 button must be shown");
return;
}
if (buttons.Length > 12)
{
LSLError("No more than 12 buttons can be shown");
Error("llDialog", "No more than 12 buttons can be shown");
return;
}
string[] buts = new string[buttons.Length];
@@ -6835,12 +6825,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
if (buttons.Data[i].ToString() == String.Empty)
{
LSLError("button label cannot be blank");
Error("llDialog", "Button label cannot be blank");
return;
}
if (buttons.Data[i].ToString().Length > 24)
{
LSLError("button label cannot be longer than 24 characters");
Error("llDialog", "Button label cannot be longer than 24 characters");
return;
}
buts[i] = buttons.Data[i].ToString();
@@ -6861,15 +6851,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0);
}
/// <summary>
/// This is a depecated function so this just replicates the result of
/// invoking it in SL
/// </summary>
public void llRemoteLoadScript(string target, string name, int running, int start_param)
{
m_host.AddScriptLPS(1);
// Report an error as it does in SL
ShoutError("Deprecated. Please use llRemoteLoadScriptPin instead.");
Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead");
ScriptSleep(3000);
}
@@ -6887,7 +6872,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!UUID.TryParse(target, out destId))
{
llSay(0, "Could not parse key " + target);
Error("llRemoteLoadScriptPin", "Can't parse key '" + target + "'");
return;
}
@@ -6903,7 +6888,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// make sure the object is a script
if (item == null || item.Type != 10)
{
llSay(0, "Could not find script " + name);
Error("llRemoteLoadScriptPin", "Can't find script '" + name + "'");
return;
}
@@ -7951,9 +7936,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
catch (InvalidCastException e)
{
ShoutError(string.Format(
"{0} error running rule #{1}: arg #{2} ",
originFunc, rulesParsed, idx - idxStart) + e.Message);
Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message);
}
finally
{
@@ -7986,9 +7969,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
catch (Exception e)
catch
{
throw new Exception("Error in base64Encode" + e.Message);
Error("llBase64ToString", "Error encoding string");
return String.Empty;
}
}
@@ -7999,16 +7983,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
return Util.Base64ToString(str);
}
catch (Exception e)
catch
{
throw new Exception("Error in base64Decode" + e.Message);
Error("llBase64ToString", "Error decoding string");
return String.Empty;
}
}
public LSL_String llXorBase64Strings(string str1, string str2)
{
m_host.AddScriptLPS(1);
Deprecated("llXorBase64Strings");
Deprecated("llXorBase64Strings", "Use llXorBase64 instead");
ScriptSleep(300);
return String.Empty;
}
@@ -8016,7 +8001,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llRemoteDataSetRegion()
{
m_host.AddScriptLPS(1);
Deprecated("llRemoteDataSetRegion");
Deprecated("llRemoteDataSetRegion", "Use llOpenRemoteDataChannel instead");
}
public LSL_Float llLog10(double val)
@@ -9731,7 +9716,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (item == null)
{
llSay(0, "No item name '" + item + "'");
Error("llGetInventoryCreator", "Can't find item '" + item + "'");
return String.Empty;
}
@@ -10050,7 +10035,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
presence = World.GetScenePresence(agentID);
}
}
else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
++i;
}
break;
@@ -10081,7 +10066,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
url = (LSL_String)commandList.Data[i + 1];
update = true;
}
else ShoutError("The argument of PARCEL_MEDIA_COMMAND_URL must be a string.");
else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string");
++i;
}
break;
@@ -10094,7 +10079,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
texture = (LSL_String)commandList.Data[i + 1];
update = true;
}
else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key.");
else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or a key");
++i;
}
break;
@@ -10106,7 +10091,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
time = (float)(LSL_Float)commandList.Data[i + 1];
}
else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TIME must be a float.");
else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float");
++i;
}
break;
@@ -10120,7 +10105,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
update = true;
}
else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer.");
else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer");
++i;
}
break;
@@ -10133,7 +10118,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
mediaType = (LSL_String)commandList.Data[i + 1];
update = true;
}
else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string.");
else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string");
++i;
}
break;
@@ -10146,7 +10131,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
description = (LSL_String)commandList.Data[i + 1];
update = true;
}
else ShoutError("The argument of PARCEL_MEDIA_COMMAND_DESC must be a string.");
else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string");
++i;
}
break;
@@ -10162,15 +10147,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
height = (LSL_Integer)commandList.Data[i + 2];
update = true;
}
else ShoutError("The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
else Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer");
}
else ShoutError("The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
else Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer");
i += 2;
}
break;
default:
NotImplemented("llParcelMediaCommandList parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString());
NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString());
break;
}//end switch
}//end for
@@ -10278,7 +10263,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break;
default:
ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
break;
}
@@ -10315,7 +10300,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (quick_pay_buttons.Data.Length < 4)
{
LSLError("List must have at least 4 elements");
Error("llSetPayPrice", "List must have at least 4 elements");
return;
}
m_host.ParentGroup.RootPart.PayPrice[0]=price;
@@ -10336,7 +10321,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
{
ShoutError("No permissions to track the camera");
Error("llGetCameraPos", "No permissions to track the camera");
return Vector3.Zero;
}
@@ -10359,7 +10344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
{
ShoutError("No permissions to track the camera");
Error("llGetCameraRot", "No permissions to track the camera");
return Quaternion.Identity;
}
@@ -10372,24 +10357,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return Quaternion.Identity;
}
/// <summary>
/// The SL implementation does nothing, it is deprecated
/// This duplicates SL
/// </summary>
public void llSetPrimURL(string url)
{
m_host.AddScriptLPS(1);
Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead");
ScriptSleep(2000);
}
/// <summary>
/// The SL implementation shouts an error, it is deprecated
/// This duplicates SL
/// </summary>
public void llRefreshPrimURL()
{
m_host.AddScriptLPS(1);
ShoutError("llRefreshPrimURL - not yet supported");
Deprecated("llRefreshPrimURL");
ScriptSleep(20000);
}
@@ -10699,7 +10677,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!ok || flag < 0 ||
flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE)
{
throw new ScriptException("Parameter " + i.ToString() + " is an invalid flag");
Error("llHTTPRequest", "Parameter " + i.ToString() + " is an invalid flag");
}
param.Add(parameters.Data[i].ToString()); //Add parameter flag
@@ -10723,12 +10701,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
//There must be at least one name/value pair for custom header
if (count == 1)
throw new ScriptException("Missing name/value for custom header at parameter " + i.ToString());
Error("llHTTPRequest", "Missing name/value for custom header at parameter " + i.ToString());
break;
}
if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase))
throw new ScriptException("Name is invalid as a custom header at parameter " + i.ToString());
Error("llHTTPRequest", "Name is invalid as a custom header at parameter " + i.ToString());
param.Add(parameters.Data[i].ToString());
param.Add(parameters.Data[i+1].ToString());
@@ -11245,25 +11223,71 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return item.ItemID;
}
internal void ShoutError(string msg)
/// <summary>
/// Reports the script error in the viewer's Script Warning/Error dialog and shouts it on the debug channel.
/// </summary>
/// <param name="command">The name of the command that generated the error.</param>
/// <param name="message">The error message to report to the user.</param>
internal void Error(string command, string message)
{
llShout(ScriptBaseClass.DEBUG_CHANNEL, msg);
string text = command + ": " + message;
if (text.Length > 1023)
{
text = text.Substring(0, 1023);
}
World.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, ScriptBaseClass.DEBUG_CHANNEL,
m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
if (wComm != null)
{
wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, text);
}
}
internal void NotImplemented(string command)
/// <summary>
/// Reports that the command is not implemented as a script error.
/// </summary>
/// <param name="command">The name of the command that is not implemented.</param>
/// <param name="message">Additional information to report to the user. (Optional)</param>
internal void NotImplemented(string command, string message = "")
{
if (throwErrorOnNotImplemented)
throw new NotImplementedException("Command not implemented: " + command);
{
if (message != "")
{
message = " - " + message;
}
throw new NotImplementedException("Command not implemented: " + command + message);
}
else
{
string text = "Command not implemented";
if (message != "")
{
text = text + " - " + message;
}
Error(command, text);
}
}
internal void Deprecated(string command)
/// <summary>
/// Reports that the command is deprecated as a script error.
/// </summary>
/// <param name="command">The name of the command that is deprecated.</param>
/// <param name="message">Additional information to report to the user. (Optional)</param>
internal void Deprecated(string command, string message = "")
{
throw new ScriptException("Command deprecated: " + command);
}
string text = "Command deprecated";
if (message != "")
{
text = text + " - " + message;
}
internal void LSLError(string msg)
{
throw new ScriptException("LSL Runtime Error: " + msg);
Error(command, text);
}
public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
@@ -11295,7 +11319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (assetID == UUID.Zero)
{
// => complain loudly, as specified by the LSL docs
ShoutError("Notecard '" + name + "' could not be found.");
Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'");
return UUID.Zero.ToString();
}
@@ -11317,7 +11341,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
if (a == null || a.Type != 7)
{
ShoutError("Notecard '" + name + "' could not be found.");
Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'");
return;
}
@@ -11348,7 +11372,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (assetID == UUID.Zero)
{
// => complain loudly, as specified by the LSL docs
ShoutError("Notecard '" + name + "' could not be found.");
Error("llGetNotecardLine", "Can't find notecard '" + name + "'");
return UUID.Zero.ToString();
}
@@ -11371,7 +11395,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
if (a == null || a.Type != 7)
{
ShoutError("Notecard '" + name + "' could not be found.");
Error("llGetNotecardLine", "Can't find notecard '" + name + "'");
return;
}

View File

@@ -450,7 +450,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0)
if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
OSSLError("osSetTerrainHeight: Coordinate out of bounds");
if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0)))
@@ -480,7 +480,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
private LSL_Float GetTerrainHeight(int x, int y)
{
m_host.AddScriptLPS(1);
if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0)
if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
OSSLError("osGetTerrainHeight: Coordinate out of bounds");
return World.Heightmap[x, y];
@@ -814,7 +814,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
private void TeleportAgent(string agent, int regionX, int regionY,
LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
{
ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize));
// ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize));
ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY);
m_host.AddScriptLPS(1);
UUID agentId = new UUID();

View File

@@ -713,16 +713,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
}
private void Save()
{
/* Remove temporarily until we have a handle to the region size
if (Position.x > ((int)Constants.RegionSize - 1))
Position.x = ((int)Constants.RegionSize - 1);
if (Position.x < 0)
Position.x = 0;
if (Position.y > ((int)Constants.RegionSize - 1))
Position.y = ((int)Constants.RegionSize - 1);
*/
if (Position.z > Constants.RegionHeight)
Position.z = Constants.RegionHeight;
if (Position.x < 0)
Position.x = 0;
if (Position.y < 0)
Position.y = 0;
if (Position.z > 768)
Position.z = 768;
if (Position.z < 0)
Position.z = 0;
prim.OSSL.llSetPos(Position);

View File

@@ -0,0 +1,150 @@
/*
* 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 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.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Reflection;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Server.Base;
using OpenSim.Services.Base;
using OpenSim.Services.Interfaces;
using Nini.Config;
using log4net;
using OpenMetaverse;
namespace OpenSim.Server.Handlers.BakedTextures
{
public class XBakes : ServiceBase, IBakedTextureService
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
protected string m_FSBase;
private System.Text.UTF8Encoding utf8encoding =
new System.Text.UTF8Encoding();
public XBakes(IConfigSource config) : base(config)
{
MainConsole.Instance.Commands.AddCommand("fs", false,
"delete bakes", "delete bakes <ID>",
"Delete agent's baked textures from server",
HandleDeleteBakes);
IConfig assetConfig = config.Configs["BakedTextureService"];
if (assetConfig == null)
{
throw new Exception("No BakedTextureService configuration");
}
m_FSBase = assetConfig.GetString("BaseDirectory", String.Empty);
if (m_FSBase == String.Empty)
{
m_log.ErrorFormat("[BAKES]: BaseDirectory not specified");
throw new Exception("Configuration error");
}
m_log.Info("[BAKES]: XBakes service enabled");
}
public string Get(string id)
{
string file = HashToFile(id);
string diskFile = Path.Combine(m_FSBase, file);
if (File.Exists(diskFile))
{
try
{
byte[] content = File.ReadAllBytes(diskFile);
return utf8encoding.GetString(content);
}
catch
{
}
}
return String.Empty;
}
public void Store(string id, string sdata)
{
string file = HashToFile(id);
string diskFile = Path.Combine(m_FSBase, file);
Directory.CreateDirectory(Path.GetDirectoryName(diskFile));
File.Delete(diskFile);
byte[] data = utf8encoding.GetBytes(sdata);
FileStream fs = File.Create(diskFile);
fs.Write(data, 0, data.Length);
fs.Close();
}
private void HandleDeleteBakes(string module, string[] args)
{
if (args.Length < 3)
{
MainConsole.Instance.Output("Syntax: delete bakes <ID>");
return;
}
string file = HashToFile(args[2]);
string diskFile = Path.Combine(m_FSBase, file);
if (File.Exists(diskFile))
{
File.Delete(diskFile);
MainConsole.Instance.Output("Bakes deleted");
return;
}
MainConsole.Instance.Output("Bakes not found");
}
public string HashToPath(string hash)
{
return Path.Combine(hash.Substring(0, 2),
Path.Combine(hash.Substring(2, 2),
Path.Combine(hash.Substring(4, 2),
hash.Substring(6, 4))));
}
public string HashToFile(string hash)
{
return Path.Combine(HashToPath(hash), hash);
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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 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 Nini.Config;
using log4net;
using System;
using System.IO;
using System.Reflection;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.Server.Handlers.BakedTextures
{
public class BakesServerGetHandler : BaseStreamHandler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IBakedTextureService m_BakesService;
private System.Text.UTF8Encoding utf8 =
new System.Text.UTF8Encoding();
public BakesServerGetHandler(IBakedTextureService service) :
base("GET", "/bakes")
{
m_BakesService = service;
}
public override byte[] Handle(string path, Stream request,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
string[] p = SplitParams(path);
if (p.Length == 0)
return new byte[0];
return utf8.GetBytes(m_BakesService.Get(p[0]));
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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 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 Nini.Config;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base;
namespace OpenSim.Server.Handlers.BakedTextures
{
public class XBakesConnector : ServiceConnector
{
private IBakedTextureService m_BakesService;
private string m_ConfigName = "BakedTextureService";
public XBakesConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName)
{
if (configName != String.Empty)
m_ConfigName = configName;
IConfig serverConfig = config.Configs[m_ConfigName];
if (serverConfig == null)
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
string assetService = serverConfig.GetString("LocalServiceModule",
String.Empty);
if (assetService == String.Empty)
throw new Exception("No BakedTextureService in config file");
Object[] args = new Object[] { config };
m_BakesService =
ServerUtils.LoadPlugin<IBakedTextureService>(assetService, args);
server.AddStreamHandler(new BakesServerGetHandler(m_BakesService));
server.AddStreamHandler(new BakesServerPostHandler(m_BakesService));
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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 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 Nini.Config;
using log4net;
using System;
using System.Reflection;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
namespace OpenSim.Server.Handlers.BakedTextures
{
public class BakesServerPostHandler : BaseStreamHandler
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IBakedTextureService m_BakesService;
private System.Text.UTF8Encoding utf8 =
new System.Text.UTF8Encoding();
public BakesServerPostHandler(IBakedTextureService service) :
base("POST", "/bakes")
{
m_BakesService = service;
}
public override byte[] Handle(string path, Stream request,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
string[] p = SplitParams(path);
if (p.Length == 0)
{
return new byte[0];
}
StreamReader sr = new StreamReader(request);
m_BakesService.Store(p[0], sr.ReadToEnd());
sr.Close();
return new byte[0];
}
}
}

View File

@@ -48,6 +48,7 @@ namespace OpenSim.Server.Handlers.Grid
public class GridServerPostHandler : BaseStreamHandler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[GRID HANDLER]";
private IGridService m_GridService;
@@ -281,8 +282,8 @@ namespace OpenSim.Server.Handlers.Grid
else
m_log.WarnFormat("[GRID HANDLER]: no Y in request to get region by position");
// m_log.DebugFormat("{0} GetRegionByPosition: loc=<{1},{2}>", LogHeader, x, y);
GridRegion rinfo = m_GridService.GetRegionByPosition(scopeID, x, y);
//m_log.DebugFormat("[GRID HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count);
Dictionary<string, object> result = new Dictionary<string, object>();
if (rinfo == null)

View File

@@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@@ -105,6 +105,8 @@ namespace OpenSim.Server.Handlers.Hypergrid
hash["uuid"] = regInfo.RegionID.ToString();
hash["x"] = regInfo.RegionLocX.ToString();
hash["y"] = regInfo.RegionLocY.ToString();
hash["size_x"] = regInfo.RegionSizeX.ToString();
hash["size_y"] = regInfo.RegionSizeY.ToString();
hash["region_name"] = regInfo.RegionName;
hash["hostname"] = regInfo.ExternalHostName;
hash["http_port"] = regInfo.HttpPort.ToString();

View File

@@ -132,6 +132,8 @@ namespace OpenSim.Server.Handlers.Hypergrid
hash["uuid"] = regInfo.RegionID.ToString();
hash["x"] = regInfo.RegionLocX.ToString();
hash["y"] = regInfo.RegionLocY.ToString();
hash["size_x"] = regInfo.RegionSizeX.ToString();
hash["size_y"] = regInfo.RegionSizeY.ToString();
hash["region_name"] = regInfo.RegionName;
hash["hostname"] = regInfo.ExternalHostName;
hash["http_port"] = regInfo.HttpPort.ToString();

Some files were not shown because too many files have changed in this diff Show More