First pass at making the V2 map work. Standalones only for now. There are some issues with the zoom level -- TBD.
parent
06e254c392
commit
fd57c91b4a
|
@ -412,7 +412,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
// OpenSim.Framework.WebUtil.OSHeaderRequestID
|
// OpenSim.Framework.WebUtil.OSHeaderRequestID
|
||||||
if (request.Headers["opensim-request-id"] != null)
|
if (request.Headers["opensim-request-id"] != null)
|
||||||
reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]);
|
reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]);
|
||||||
// m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);
|
//m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);
|
||||||
|
|
||||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true);
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true);
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
string path = request.RawUrl;
|
string path = request.RawUrl;
|
||||||
string handlerKey = GetHandlerKey(request.HttpMethod, path);
|
string handlerKey = GetHandlerKey(request.HttpMethod, path);
|
||||||
|
|
||||||
// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
|
//m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
|
||||||
|
|
||||||
if (TryGetStreamHandler(handlerKey, out requestHandler))
|
if (TryGetStreamHandler(handlerKey, out requestHandler))
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using log4net;
|
||||||
|
using Mono.Addins;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using OpenSim.Server.Handlers.MapImage;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||||
|
public class MapImageServiceInConnectorModule : ISharedRegionModule
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private static bool m_Enabled = false;
|
||||||
|
|
||||||
|
private IConfigSource m_Config;
|
||||||
|
bool m_Registered = false;
|
||||||
|
|
||||||
|
#region IRegionModule interface
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
m_Config = config;
|
||||||
|
IConfig moduleConfig = config.Configs["Modules"];
|
||||||
|
if (moduleConfig != null)
|
||||||
|
{
|
||||||
|
m_Enabled = moduleConfig.GetBoolean("MapImageServiceInConnector", false);
|
||||||
|
if (m_Enabled)
|
||||||
|
{
|
||||||
|
m_log.Info("[MAP SERVICE IN CONNECTOR]: MapImage Service In Connector enabled");
|
||||||
|
new MapGetServiceConnector(m_Config, MainServer.Instance, "MapImageService");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "MapImageServiceIn"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Net;
|
||||||
|
using System.IO;
|
||||||
|
using System.Timers;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
using log4net;
|
||||||
|
using Mono.Addins;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// </remarks>
|
||||||
|
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||||
|
public class MapImageServiceModule : ISharedRegionModule
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_enabled = false;
|
||||||
|
private IMapImageService m_MapService;
|
||||||
|
|
||||||
|
private string m_serverUrl = String.Empty;
|
||||||
|
private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
|
||||||
|
|
||||||
|
private int m_refreshtime = 0;
|
||||||
|
private int m_lastrefresh = 0;
|
||||||
|
private System.Timers.Timer m_refreshTimer = new System.Timers.Timer();
|
||||||
|
|
||||||
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
public Type ReplaceableInterface { get { return null; } }
|
||||||
|
public string Name { get { return "MapImageServiceModule"; } }
|
||||||
|
public void RegionLoaded(Scene scene) { }
|
||||||
|
public void Close() { }
|
||||||
|
public void PostInitialise() { }
|
||||||
|
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///
|
||||||
|
///</summary>
|
||||||
|
public void Initialise(IConfigSource source)
|
||||||
|
{
|
||||||
|
IConfig moduleConfig = source.Configs["Modules"];
|
||||||
|
if (moduleConfig != null)
|
||||||
|
{
|
||||||
|
string name = moduleConfig.GetString("MapImageService", "");
|
||||||
|
if (name != Name)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IConfig config = source.Configs["MapImageService"];
|
||||||
|
if (config == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime"));
|
||||||
|
if (refreshminutes <= 0)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms
|
||||||
|
|
||||||
|
string service = config.GetString("LocalServiceModule", string.Empty);
|
||||||
|
if (service == string.Empty)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No service dll given in config. Unable to proceed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] args = new Object[] { source };
|
||||||
|
m_MapService = ServerUtils.LoadPlugin<IMapImageService>(service, args);
|
||||||
|
|
||||||
|
m_refreshTimer.Enabled = true;
|
||||||
|
m_refreshTimer.AutoReset = true;
|
||||||
|
m_refreshTimer.Interval = m_refreshtime;
|
||||||
|
m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
|
||||||
|
|
||||||
|
m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}",
|
||||||
|
refreshminutes, service);
|
||||||
|
|
||||||
|
m_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///
|
||||||
|
///</summary>
|
||||||
|
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///
|
||||||
|
///</summary>
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (! m_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Every shared region module has to maintain an indepedent list of
|
||||||
|
// currently running regions
|
||||||
|
lock (m_scenes)
|
||||||
|
m_scenes[scene.RegionInfo.RegionID] = scene;
|
||||||
|
|
||||||
|
scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///
|
||||||
|
///</summary>
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (! m_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (m_scenes)
|
||||||
|
m_scenes.Remove(scene.RegionInfo.RegionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion ISharedRegionModule
|
||||||
|
|
||||||
|
void EventManager_OnPrimsLoaded(Scene s)
|
||||||
|
{
|
||||||
|
UploadMapTile(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///
|
||||||
|
///</summary>
|
||||||
|
private void HandleMaptileRefresh(object sender, EventArgs ea)
|
||||||
|
{
|
||||||
|
// this approach is a bit convoluted becase we want to wait for the
|
||||||
|
// first upload to happen on startup but after all the objects are
|
||||||
|
// loaded and initialized
|
||||||
|
if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: map refresh!");
|
||||||
|
lock (m_scenes)
|
||||||
|
{
|
||||||
|
foreach (IScene scene in m_scenes.Values)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UploadMapTile(scene);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: something bad happened {0}", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastrefresh = Util.EnvironmentTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///
|
||||||
|
///</summary>
|
||||||
|
private void UploadMapTile(IScene scene)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
|
// Create a PNG 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");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (Image mapTile = tileGenerator.CreateMapTile())
|
||||||
|
{
|
||||||
|
using (MemoryStream stream = new MemoryStream())
|
||||||
|
{
|
||||||
|
mapTile.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))
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -849,10 +849,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
{
|
{
|
||||||
List<MapBlockData> mapBlocks = new List<MapBlockData>();
|
List<MapBlockData> mapBlocks = new List<MapBlockData>();
|
||||||
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
|
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
|
||||||
(minX - 4) * (int)Constants.RegionSize,
|
(minX - 8) * (int)Constants.RegionSize,
|
||||||
(maxX + 4) * (int)Constants.RegionSize,
|
(maxX + 8) * (int)Constants.RegionSize,
|
||||||
(minY - 4) * (int)Constants.RegionSize,
|
(minY - 8) * (int)Constants.RegionSize,
|
||||||
(maxY + 4) * (int)Constants.RegionSize);
|
(maxY + 8) * (int)Constants.RegionSize);
|
||||||
foreach (GridRegion r in regions)
|
foreach (GridRegion r in regions)
|
||||||
{
|
{
|
||||||
MapBlockData block = new MapBlockData();
|
MapBlockData block = new MapBlockData();
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above 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.MapImage
|
||||||
|
{
|
||||||
|
public class MapAddServiceConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private IMapImageService m_MapService;
|
||||||
|
private string m_ConfigName = "MapImageService";
|
||||||
|
|
||||||
|
public MapAddServiceConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||||
|
if (serverConfig == null)
|
||||||
|
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
|
||||||
|
|
||||||
|
string gridService = serverConfig.GetString("LocalServiceModule",
|
||||||
|
String.Empty);
|
||||||
|
|
||||||
|
if (gridService == String.Empty)
|
||||||
|
throw new Exception("No LocalServiceModule in config file");
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
m_MapService = ServerUtils.LoadPlugin<IMapImageService>(gridService, args);
|
||||||
|
|
||||||
|
//server.AddStreamHandler(new PresenceServerPostHandler(m_PresenceService));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* 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.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using Nini.Config;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
|
||||||
|
namespace OpenSim.Server.Handlers.MapImage
|
||||||
|
{
|
||||||
|
public class MapGetServiceConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private IMapImageService m_MapService;
|
||||||
|
private string m_ConfigName = "MapImageService";
|
||||||
|
|
||||||
|
public MapGetServiceConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||||
|
if (serverConfig == null)
|
||||||
|
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
|
||||||
|
|
||||||
|
string gridService = serverConfig.GetString("LocalServiceModule",
|
||||||
|
String.Empty);
|
||||||
|
|
||||||
|
if (gridService == String.Empty)
|
||||||
|
throw new Exception("No LocalServiceModule in config file");
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
m_MapService = ServerUtils.LoadPlugin<IMapImageService>(gridService, args);
|
||||||
|
|
||||||
|
server.AddStreamHandler(new MapServerGetHandler(m_MapService));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapServerGetHandler : BaseStreamHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private IMapImageService m_MapService;
|
||||||
|
|
||||||
|
public MapServerGetHandler(IMapImageService service) :
|
||||||
|
base("GET", "/map")
|
||||||
|
{
|
||||||
|
m_MapService = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: retrieving {0}", path);
|
||||||
|
byte[] result = new byte[0];
|
||||||
|
|
||||||
|
string format = string.Empty;
|
||||||
|
result = m_MapService.GetMapTile(path.Trim('/'), out format);
|
||||||
|
|
||||||
|
if (result.Length > 0)
|
||||||
|
{
|
||||||
|
httpResponse.StatusCode = (int)HttpStatusCode.OK;
|
||||||
|
if (format.Equals("png"))
|
||||||
|
httpResponse.ContentType = "image/png";
|
||||||
|
else if (format.Equals("jpg") || format.Equals("jpeg"))
|
||||||
|
httpResponse.ContentType = "image/jpeg";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
httpResponse.ContentType = "text/plain";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* 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 log4net;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Framework.Communications;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
|
namespace OpenSim.Services.Connectors
|
||||||
|
{
|
||||||
|
public class MapImageServicesConnector : IMapImageService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(
|
||||||
|
MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private string m_ServerURI = String.Empty;
|
||||||
|
private IImprovedAssetCache m_Cache = null;
|
||||||
|
|
||||||
|
public MapImageServicesConnector()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapImageServicesConnector(string serverURI)
|
||||||
|
{
|
||||||
|
m_ServerURI = serverURI.TrimEnd('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapImageServicesConnector(IConfigSource source)
|
||||||
|
{
|
||||||
|
Initialise(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Initialise(IConfigSource source)
|
||||||
|
{
|
||||||
|
IConfig config = source.Configs["MapImageService"];
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[MAP IMAGE CONNECTOR]: MapImageService missing");
|
||||||
|
throw new Exception("MapImage connector init error");
|
||||||
|
}
|
||||||
|
|
||||||
|
string serviceURI = config.GetString("MapImageServerURI",
|
||||||
|
String.Empty);
|
||||||
|
|
||||||
|
if (serviceURI == String.Empty)
|
||||||
|
{
|
||||||
|
m_log.Error("[MAP IMAGE CONNECTOR]: No Server URI named in section MapImageService");
|
||||||
|
throw new Exception("MapImage connector init error");
|
||||||
|
}
|
||||||
|
m_ServerURI = serviceURI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddMapTile(int x, int y, byte[] pngData, out string reason)
|
||||||
|
{
|
||||||
|
List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
|
||||||
|
{
|
||||||
|
new MultipartForm.Parameter("X", x.ToString()),
|
||||||
|
new MultipartForm.Parameter("Y", y.ToString()),
|
||||||
|
new MultipartForm.File("Tile", "tile.png", "image/png", pngData)
|
||||||
|
};
|
||||||
|
|
||||||
|
reason = string.Empty;
|
||||||
|
int tickstart = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
|
// Make the remote storage request
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI);
|
||||||
|
request.Timeout = 20000;
|
||||||
|
request.ReadWriteTimeout = 5000;
|
||||||
|
|
||||||
|
using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
|
||||||
|
{
|
||||||
|
using (Stream responseStream = response.GetResponseStream())
|
||||||
|
{
|
||||||
|
string responseStr = responseStream.GetStreamString();
|
||||||
|
OSD responseOSD = OSDParser.Deserialize(responseStr);
|
||||||
|
if (responseOSD.Type == OSDType.Map)
|
||||||
|
{
|
||||||
|
OSDMap responseMap = (OSDMap)responseOSD;
|
||||||
|
if (responseMap["Success"].AsBoolean())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
reason = "Upload failed: " + responseMap["Message"].AsString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "Response format was invalid:\n" + responseStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (WebException we)
|
||||||
|
{
|
||||||
|
reason = we.Message;
|
||||||
|
if (we.Status == WebExceptionStatus.ProtocolError)
|
||||||
|
{
|
||||||
|
HttpWebResponse webResponse = (HttpWebResponse)we.Response;
|
||||||
|
reason = String.Format("[{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
reason = ex.Message;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// This just dumps a warning for any operation that takes more than 100 ms
|
||||||
|
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
|
m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile uploaded in {0}ms", tickdiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetMapTile(string fileName, out string format)
|
||||||
|
{
|
||||||
|
format = string.Empty;
|
||||||
|
new Exception("GetMapTile method not Implemented");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,8 +31,10 @@ using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Services.Interfaces
|
namespace OpenSim.Services.Interfaces
|
||||||
{
|
{
|
||||||
public interface IMapService
|
public interface IMapImageService
|
||||||
{
|
{
|
||||||
List<MapBlockData> GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY);
|
//List<MapBlockData> GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY);
|
||||||
|
bool AddMapTile(int x, int y, byte[] imageData, out string reason);
|
||||||
|
byte[] GetMapTile(string fileName, out string format);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,295 @@
|
||||||
|
/*
|
||||||
|
* 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.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using Nini.Config;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
namespace OpenSim.Services.MapImageService
|
||||||
|
{
|
||||||
|
public class MapImageService : IMapImageService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(
|
||||||
|
MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private const int ZOOM_LEVELS = 8;
|
||||||
|
private const int IMAGE_WIDTH = 256;
|
||||||
|
private const int HALF_WIDTH = 128;
|
||||||
|
private const int JPEG_QUALITY = 80;
|
||||||
|
|
||||||
|
private static string m_TilesStoragePath = "maptiles";
|
||||||
|
|
||||||
|
private static object m_Sync = new object();
|
||||||
|
private static bool m_Initialized = false;
|
||||||
|
private static string m_WaterTileFile = string.Empty;
|
||||||
|
private static Color m_Watercolor = Color.FromArgb(29, 71, 95);
|
||||||
|
|
||||||
|
public MapImageService(IConfigSource config)
|
||||||
|
{
|
||||||
|
if (!m_Initialized)
|
||||||
|
{
|
||||||
|
m_Initialized = true;
|
||||||
|
m_log.Debug("[MAP IMAGE SERVICE]: Starting MapImage service");
|
||||||
|
|
||||||
|
IConfig serviceConfig = config.Configs["MapImageService"];
|
||||||
|
if (serviceConfig != null)
|
||||||
|
{
|
||||||
|
m_TilesStoragePath = serviceConfig.GetString("TilesStoragePath", m_TilesStoragePath);
|
||||||
|
if (!Directory.Exists(m_TilesStoragePath))
|
||||||
|
Directory.CreateDirectory(m_TilesStoragePath);
|
||||||
|
|
||||||
|
|
||||||
|
m_WaterTileFile = Path.Combine(m_TilesStoragePath, "water.jpg");
|
||||||
|
if (!File.Exists(m_WaterTileFile))
|
||||||
|
{
|
||||||
|
Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH);
|
||||||
|
FillImage(waterTile, m_Watercolor);
|
||||||
|
waterTile.Save(m_WaterTileFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IMapImageService
|
||||||
|
|
||||||
|
public bool AddMapTile(int x, int y, byte[] imageData, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
string fileName = GetFileName(1, x, y);
|
||||||
|
|
||||||
|
lock (m_Sync)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (FileStream f = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write))
|
||||||
|
f.Write(imageData, 0, imageData.Length);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save image file {0}: {1}", fileName, e);
|
||||||
|
reason = e.Message;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also save in png format?
|
||||||
|
|
||||||
|
// Stitch seven more aggregate tiles together
|
||||||
|
for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++)
|
||||||
|
{
|
||||||
|
// Calculate the width (in full resolution tiles) and bottom-left
|
||||||
|
// corner of the current zoom level
|
||||||
|
int width = (int)Math.Pow(2, (double)(zoomLevel - 1));
|
||||||
|
int x1 = x - (x % width);
|
||||||
|
int y1 = y - (y % width);
|
||||||
|
|
||||||
|
if (!CreateTile(zoomLevel, x1, y1))
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0} at zoom level {1}", fileName, zoomLevel);
|
||||||
|
reason = string.Format("Map tile at zoom level {0} failed", zoomLevel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetMapTile(string fileName, out string format)
|
||||||
|
{
|
||||||
|
format = "jpg";
|
||||||
|
string fullName = Path.Combine(m_TilesStoragePath, fileName);
|
||||||
|
if (File.Exists(fullName))
|
||||||
|
{
|
||||||
|
format = Path.GetExtension(fileName).ToLower();
|
||||||
|
m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format);
|
||||||
|
return File.ReadAllBytes(fullName);
|
||||||
|
}
|
||||||
|
else if (File.Exists(m_WaterTileFile))
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[MAP IMAGE SERVICE]: File not found {0}, sending water", fileName);
|
||||||
|
return File.ReadAllBytes(m_WaterTileFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[MAP IMAGE SERVICE]: unable to get file {0}", fileName);
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
private string GetFileName(uint zoomLevel, int x, int y)
|
||||||
|
{
|
||||||
|
string extension = "jpg";
|
||||||
|
return Path.Combine(m_TilesStoragePath, string.Format("map-{0}-{1}-{2}-objects.{3}", zoomLevel, x, y, extension));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap GetInputTileImage(string fileName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(fileName))
|
||||||
|
return new Bitmap(fileName);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap GetOutputTileImage(string fileName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(fileName))
|
||||||
|
return new Bitmap(fileName);
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create a new output tile with a transparent background
|
||||||
|
Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH);
|
||||||
|
bm.MakeTransparent();
|
||||||
|
return bm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CreateTile(uint zoomLevel, int x, int y)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[MAP IMAGE SERVICE]: Create tile for {0} {1}, zoom {2}", x, y, zoomLevel);
|
||||||
|
int prevWidth = (int)Math.Pow(2, (double)zoomLevel - 2);
|
||||||
|
int thisWidth = (int)Math.Pow(2, (double)zoomLevel - 1);
|
||||||
|
|
||||||
|
// Convert x and y to the bottom left tile for this zoom level
|
||||||
|
int xIn = x - (x % prevWidth);
|
||||||
|
int yIn = y - (y % prevWidth);
|
||||||
|
|
||||||
|
// Convert x and y to the bottom left tile for the next zoom level
|
||||||
|
int xOut = x - (x % thisWidth);
|
||||||
|
int yOut = y - (y % thisWidth);
|
||||||
|
|
||||||
|
// Try to open the four input tiles from the previous zoom level
|
||||||
|
Bitmap inputBL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn));
|
||||||
|
Bitmap inputBR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn));
|
||||||
|
Bitmap inputTL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn + prevWidth));
|
||||||
|
Bitmap inputTR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn + prevWidth));
|
||||||
|
|
||||||
|
// Open the output tile (current zoom level)
|
||||||
|
string outputFile = GetFileName(zoomLevel, xOut, yOut);
|
||||||
|
Bitmap output = GetOutputTileImage(outputFile);
|
||||||
|
if (output == null)
|
||||||
|
return false;
|
||||||
|
FillImage(output, m_Watercolor);
|
||||||
|
|
||||||
|
if (inputBL != null)
|
||||||
|
{
|
||||||
|
ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0);
|
||||||
|
inputBL.Dispose();
|
||||||
|
}
|
||||||
|
if (inputBR != null)
|
||||||
|
{
|
||||||
|
ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0);
|
||||||
|
inputBR.Dispose();
|
||||||
|
}
|
||||||
|
if (inputTL != null)
|
||||||
|
{
|
||||||
|
ImageCopyResampled(output, inputTL, 0, 0, 0, 0);
|
||||||
|
inputTL.Dispose();
|
||||||
|
}
|
||||||
|
if (inputTR != null)
|
||||||
|
{
|
||||||
|
ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0);
|
||||||
|
inputTR.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the modified output
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (Bitmap final = new Bitmap(output))
|
||||||
|
{
|
||||||
|
output.Dispose();
|
||||||
|
final.Save(outputFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save also as png?
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Image utilities
|
||||||
|
|
||||||
|
private void FillImage(Bitmap bm, Color c)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < bm.Width; x++)
|
||||||
|
for (int y = 0; y < bm.Height; y++)
|
||||||
|
bm.SetPixel(x, y, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ImageCopyResampled(Bitmap output, Bitmap input, int destX, int destY, int srcX, int srcY)
|
||||||
|
{
|
||||||
|
int resamplingRateX = 2; // (input.Width - srcX) / (output.Width - destX);
|
||||||
|
int resamplingRateY = 2; // (input.Height - srcY) / (output.Height - destY);
|
||||||
|
|
||||||
|
for (int x = destX; x < destX + HALF_WIDTH; x++)
|
||||||
|
for (int y = destY; y < destY + HALF_WIDTH; y++)
|
||||||
|
{
|
||||||
|
Color p = input.GetPixel(srcX + (x - destX) * resamplingRateX, srcY + (y - destY) * resamplingRateY);
|
||||||
|
output.SetPixel(x, y, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,10 +17,12 @@
|
||||||
AvatarServices = "LocalAvatarServicesConnector"
|
AvatarServices = "LocalAvatarServicesConnector"
|
||||||
EntityTransferModule = "BasicEntityTransferModule"
|
EntityTransferModule = "BasicEntityTransferModule"
|
||||||
InventoryAccessModule = "BasicInventoryAccessModule"
|
InventoryAccessModule = "BasicInventoryAccessModule"
|
||||||
|
MapImageService = "MapImageServiceModule"
|
||||||
|
|
||||||
LibraryModule = true
|
LibraryModule = true
|
||||||
LLLoginServiceInConnector = true
|
LLLoginServiceInConnector = true
|
||||||
GridInfoServiceInConnector = true
|
GridInfoServiceInConnector = true
|
||||||
|
MapImageServiceInConnector = true
|
||||||
|
|
||||||
[Profile]
|
[Profile]
|
||||||
Module = "BasicProfileModule"
|
Module = "BasicProfileModule"
|
||||||
|
@ -91,6 +93,11 @@
|
||||||
|
|
||||||
WelcomeMessage = "Welcome, Avatar!"
|
WelcomeMessage = "Welcome, Avatar!"
|
||||||
|
|
||||||
|
[MapImageService]
|
||||||
|
LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService"
|
||||||
|
; in minutes
|
||||||
|
RefreshTime = 60
|
||||||
|
|
||||||
;; This should always be the very last thing on this file
|
;; This should always be the very last thing on this file
|
||||||
[Includes]
|
[Includes]
|
||||||
Include-Common = "config-include/StandaloneCommon.ini"
|
Include-Common = "config-include/StandaloneCommon.ini"
|
||||||
|
|
|
@ -99,6 +99,9 @@
|
||||||
SRV_FriendsServerURI = "http://127.0.0.1:9000"
|
SRV_FriendsServerURI = "http://127.0.0.1:9000"
|
||||||
SRV_IMServerURI = "http://127.0.0.1:9000"
|
SRV_IMServerURI = "http://127.0.0.1:9000"
|
||||||
|
|
||||||
|
;; For Viewer 2
|
||||||
|
MapTileURL = "http://127.0.0.1:9000"
|
||||||
|
|
||||||
;; Regular expressions for controlling which client versions are accepted/denied.
|
;; Regular expressions for controlling which client versions are accepted/denied.
|
||||||
;; An empty string means nothing is checked.
|
;; An empty string means nothing is checked.
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
GridUserServices = "LocalGridUserServicesConnector"
|
GridUserServices = "LocalGridUserServicesConnector"
|
||||||
SimulationServices = "RemoteSimulationConnectorModule"
|
SimulationServices = "RemoteSimulationConnectorModule"
|
||||||
AvatarServices = "LocalAvatarServicesConnector"
|
AvatarServices = "LocalAvatarServicesConnector"
|
||||||
|
MapImageService = "MapImageServiceModule"
|
||||||
EntityTransferModule = "HGEntityTransferModule"
|
EntityTransferModule = "HGEntityTransferModule"
|
||||||
InventoryAccessModule = "HGInventoryAccessModule"
|
InventoryAccessModule = "HGInventoryAccessModule"
|
||||||
FriendsModule = "HGFriendsModule"
|
FriendsModule = "HGFriendsModule"
|
||||||
|
|
||||||
InventoryServiceInConnector = true
|
InventoryServiceInConnector = true
|
||||||
AssetServiceInConnector = true
|
AssetServiceInConnector = true
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
GridInfoServiceInConnector = true
|
GridInfoServiceInConnector = true
|
||||||
AuthenticationServiceInConnector = true
|
AuthenticationServiceInConnector = true
|
||||||
SimulationServiceInConnector = true
|
SimulationServiceInConnector = true
|
||||||
|
MapImageServiceInConnector = true
|
||||||
|
|
||||||
[Profile]
|
[Profile]
|
||||||
Module = "BasicProfileModule"
|
Module = "BasicProfileModule"
|
||||||
|
@ -116,7 +118,12 @@
|
||||||
GridService = "OpenSim.Services.GridService.dll:GridService"
|
GridService = "OpenSim.Services.GridService.dll:GridService"
|
||||||
AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
|
AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
|
||||||
FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService"
|
FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService"
|
||||||
|
|
||||||
|
[MapImageService]
|
||||||
|
LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService"
|
||||||
|
; in minutes
|
||||||
|
RefreshTime = 60
|
||||||
|
|
||||||
[GatekeeperService]
|
[GatekeeperService]
|
||||||
LocalServiceModule = "OpenSim.Services.HypergridService.dll:GatekeeperService"
|
LocalServiceModule = "OpenSim.Services.HypergridService.dll:GatekeeperService"
|
||||||
;; for the service
|
;; for the service
|
||||||
|
|
30
prebuild.xml
30
prebuild.xml
|
@ -1269,6 +1269,36 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
<Project frameworkVersion="v3_5" name="OpenSim.Services.MapImageService" path="OpenSim/Services/MapImageService" type="Library">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../../bin/</ReferencePath>
|
||||||
|
<Reference name="System"/>
|
||||||
|
<Reference name="System.Drawing"/>
|
||||||
|
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenSim.Framework"/>
|
||||||
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
|
||||||
|
<Reference name="OpenSim.Services.Interfaces"/>
|
||||||
|
<Reference name="OpenSim.Services.Base"/>
|
||||||
|
<Reference name="Nini" path="../../../bin/"/>
|
||||||
|
<Reference name="log4net" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="true"/>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.Server.Handlers" path="OpenSim/Server/Handlers" type="Library">
|
<Project frameworkVersion="v3_5" name="OpenSim.Server.Handlers" path="OpenSim/Server/Handlers" type="Library">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
<Options>
|
<Options>
|
||||||
|
|
Loading…
Reference in New Issue