Иконка ресурса

FREE MapGenerator : 1.0.1 1.0.1

Нет прав для скачивания
C#:
// Reference: System.Drawing
using System.IO;
using Oxide.Core;
using UnityEngine;
using System;
using System.Collections.Generic;

using Newtonsoft.Json;
using Random = Oxide.Core.Random;

namespace Oxide.Plugins 
{
	[Info("MapGenerator", "", "1.0.1")]
	[Description("Simple map generator")]
	
	class MapGenerator : RustPlugin 
	{
		#region Config

		private ConfigData configData;

		class ConfigData {
			[JsonProperty(PropertyName = "ОСНОВНЫЕ НАСТРОЙКИ")]
			public SettingOptions OptionsSetting { get; set; }

			public class SettingOptions {
				[JsonProperty(PropertyName = "Имя генерируемого изображения карты |без расширения.jpg|")]
				public string filename;

				[JsonProperty(PropertyName = "Автоматическая генерация нового изображения карты после вайпа")]
				public bool AutoMap;

				[JsonProperty(PropertyName = "Размер изображения для генерации карты |0 - стандартный размер|")]
				public int autosize;

				[JsonProperty(PropertyName = "Расширение генерируемого изображения карты |jpg или png|")]
				public string type;
			}
		}

		private ConfigData GetBaseConfig() {
			return new ConfigData {
				OptionsSetting = new ConfigData.SettingOptions {
					filename = "Map",
					AutoMap  = false,
					autosize = 0,
					type     = "png"
				}
			};
		}

		protected override void LoadConfig() {
			base.LoadConfig();

			try {
				configData = Config.ReadObject<ConfigData>();
				if (configData == null) Regenerate();
			} catch {
				Regenerate();
			}

			UpdateConfigValues();
			Config.WriteObject(configData, true);

			SaveConfig();
		}

		protected override void LoadDefaultConfig() {
			configData = GetBaseConfig();
			PrintWarning("Создан новый файл конфигурации.");
		}

		protected override void SaveConfig() => Config.WriteObject(configData, true);

		private void Regenerate() {
			PrintWarning($"Конфигурационный файл 'oxide/config/{Name}.json' поврежден, создается новый...");
			LoadDefaultConfig();
		}

		private void UpdateConfigValues() {
			configData = GetBaseConfig();
		}

		#endregion

		#region Properties

		private Terrain terrain;
		private bool NewWipe;

		#endregion
		#region Commands

		/*[ChatCommand("xxx")]
		private void XXX(BasePlayer player) {
			RaycastHit raycastHit;

			if (!Physics.Raycast(player.eyes.HeadRay(), out raycastHit, 100f, LayerMask.GetMask("Terrain", "World", "Water"), QueryTriggerInteraction.Ignore))
				return;

			var name = raycastHit.collider.gameObject.name;

			SendReply(player, name + " | " + raycastHit.collider.tag);
		}*/

		[ConsoleCommand("savemap")]
		private void SaveMapCMD(ConsoleSystem.Arg arg) {
			if (!arg.IsAdmin) return;

			var size     = 0;
			var filetype = ".jpg";

			if (arg.HasArgs()) {
				if (!Int32.TryParse(arg.Args[0], out size))
					PrintWarning("Неправильно указан размер изображения.Установлено стандартное значение (размер карты / 2)");
				if (arg.Args.Length > 1 && arg.Args[1] == "png") filetype = ".png";
			}

			GenerateMap(size, filetype);
		}

		#endregion
		#region MapGenerator

		public class ColorRet {
			public Color color;
			public bool useHeight;

			public ColorRet(float r = 0f, float g = 0f, float b = 0f, float a = 1f, bool useHeight = false) {
				this.color     = new Color(r, g, b, a);
				this.useHeight = useHeight;
			}
		}

		Dictionary<string, ColorRet> raycastColors = new Dictionary<string, ColorRet> {
			{"train_track", new ColorRet(0.26f, 0.27f, 0.29f, 0.67f)},
			{"road_nopav", new ColorRet(0.26f, 0.27f, 0.29f, 0.67f)},
			{"road", new ColorRet(0.29f, 0.11f, 0.07f, 0.65f)},
			{"iceberg", new ColorRet(0.82f, 0.89f, 1f, 0.83f)},
			{"ice_lake", new ColorRet(0.82f, 0.89f, 1f, 0.83f)},
			{"collider_batch", new ColorRet(0.73f, 0.73f, 0.7f, 0.82f)},
			{"river", new ColorRet(0f, 0.27f, 0.65f, 0.83f)},
			{"dish_radio", new ColorRet(0.87f, 0.84f, 0.78f, 0.83f)},
			{"tunnel.single", new ColorRet(0.47f, 0.47f, 0.47f, 0.55f)},
			{"train_wagon", new ColorRet(0.65f, 0.53f, 0.53f, 0.55f)},
			{"bus_stop", new ColorRet(0.4f, 0.26f, 0.16f, 0.55f)},
			{"sewer_chim", new ColorRet(0.51f, 0.51f, 0.49f, 0.55f)},
			{"sewer_drain", new ColorRet(0.51f, 0.51f, 0.49f, 0.55f)},
			{"large_industrial", new ColorRet(0.51f, 0.51f, 0.49f, 0.55f)},
			{"loading_bay_lane", new ColorRet(0.5f, 0.42f, 0.36f, 0.73f)},
			{"harbor", new ColorRet(0.46f, 0.37f, 0.25f, 0.78f)},
			{"shipping_container", new ColorRet(0.46f, 0.37f, 0.25f, 0.78f)},
			{"crane_tower", new ColorRet(0.46f, 0.37f, 0.25f, 0.78f)},
			{"fuel_tank", new ColorRet(0.46f, 0.37f, 0.25f, 0.78f)},
			{"trailer", new ColorRet(0.46f, 0.37f, 0.25f, 0.78f)},
			{"rock_quarry", new ColorRet(0.36f, 0.33f, 0.31f, 0.95f)},
			{"water_body", new ColorRet(0.1f, 0.3f, 0.07f, 0.95f)},
			{"wooden_walkway", new ColorRet(0.69f, 0.63f, 0.54f, 0.95f)},
			{"cover", new ColorRet(0.56f, 0.51f, 0.42f, 0.95f)},
			{"windmill", new ColorRet(0.56f, 0.51f, 0.42f, 0.95f)},
			{"dredge_body", new ColorRet(0.61f, 0.48f, 0.47f, 0.78f)},
			{"launch_site_ground", new ColorRet(0.4f, 0.4f, 0.38f, 0.61f)},
			{"range_ground", new ColorRet(0.44f, 0.4f, 0.38f, 0.64f)},
			{"range_rails", new ColorRet(0.51f, 0.51f, 0.49f, 0.55f)},
			{"floodlights_", new ColorRet(0.51f, 0.51f, 0.49f, 0.55f)},
			{"warehouse_launch", new ColorRet(0.5f, 0.42f, 0.36f, 0.73f)},
			{"space_center", new ColorRet(0.5f, 0.42f, 0.36f, 0.73f)},
			{"rocket_factory", new ColorRet(0.61f, 0.48f, 0.47f, 0.78f)},
			{"runway", new ColorRet(0.51f, 0.51f, 0.49f, 0.55f)},
			{"office_bld", new ColorRet(0.5f, 0.42f, 0.36f, 0.73f)},
			{"watch_tower", new ColorRet(0.5f, 0.42f, 0.36f, 0.73f)},
			{"hangar_air", new ColorRet(0.61f, 0.48f, 0.47f, 0.78f)},
			{"perimeter_wall", new ColorRet(0.83f, 0.76f, 0.75f, 0.7f)},
			{"concrete_slabs", new ColorRet(0.47f, 0.47f, 0.47f, 0.55f)},
			{"outbuilding", new ColorRet(0.5f, 0.42f, 0.36f, 0.73f)},
			{"rowhouse", new ColorRet(0.5f, 0.42f, 0.36f, 0.73f)},
			{"sphere", new ColorRet(0.61f, 0.32f, 0.22f)},
			{"coal_pile", new ColorRet(0.16f, 0.16f, 0.16f)},
			{"water_tower", new ColorRet(0.61f, 0.48f, 0.47f, 0.78f)},
			{"pipeline", new ColorRet(0.61f, 0.33f, 0.27f, 0.78f)},
			{"train_crane", new ColorRet(0.5f, 0.42f, 0.36f, 0.73f)}
		};

		public List<string> names = new List<string>();
		public Dictionary<string, ColorRet> junkpiles = new Dictionary<string, ColorRet>();

		private ColorRet CheckRaycast(Vector3 terrainWorldPosition, float highestTerrainHeight) {
			RaycastHit raycastHit;

			var rr = new Vector3(terrainWorldPosition.x, highestTerrainHeight + 10f, terrainWorldPosition.z);

			if (!Physics.Raycast(rr,
				Vector3.down,
				out raycastHit,
				highestTerrainHeight + 10f,
				LayerMask.GetMask("Terrain", "World", "Water"),
				QueryTriggerInteraction.Ignore))
				return new ColorRet();

			var name = raycastHit.collider.gameObject.name.ToLower();
			if (name == "Terrain") return new ColorRet();

			foreach (var raycastColor in raycastColors) {
				if (name.Contains(raycastColor.Key.ToLower())) return raycastColor.Value;
			}

			if (name.Contains("junkyard_mound")) {
				if (!junkpiles.ContainsKey(name)) {
					var r = Random.Range(0f, 1.75f);
					junkpiles.Add(name, new ColorRet(0.32f + r * 0.09f, 0.16f + r * 0.08f, 0.11f + r * 0.01f, 0.6f));
				}

				return junkpiles[name];
			}

			return new ColorRet();
		}

		private void ProcessPixel(Texture2D mapTex, Vector3 terrainPosition, int height, int width, int x, int y, float heightMin, float heightMax) {
			var heightsTex = TerrainMeta.HeightMap.NormalTexture;
			var isTerrain  = false;

			var pos = new Vector3(x * TerrainMeta.Size.x / width + terrainPosition.x, 0, y * TerrainMeta.Size.z / height + terrainPosition.z);

			var waterDepth    = TerrainMeta.WaterMap.GetDepth(pos);
			var waterHeight   = TerrainMeta.WaterMap.GetHeight01(pos) * TerrainMeta.Size.y;
			var currentHeight = TerrainMeta.HeightMap.GetHeight(pos);
			var pixelColor    = TerrainMeta.Colors.GetColor(pos);

			//Над водой
			if (currentHeight - 1.5f >= waterDepth) {
				pixelColor.a =  1f;
				pixelColor.r *= 0.95f;
				pixelColor.g *= 0.95f;
				pixelColor.b *= 0.95f;
				mapTex.SetPixel(x, y, pixelColor);
				isTerrain = true;
			} else {
				var waterColor = new Color(0.24f, 0.56f, 0.71f);
				mapTex.SetPixel(x, y, waterColor);
			}

			if (ConVar.Server.level.ToLower() != "barren" && !isTerrain || isTerrain) {
				var cr = CheckRaycast(pos, heightMax); 

				if (cr.color != Color.black) {
					mapTex.SetPixel(x, y, cr.color);
					if (!cr.useHeight) return;
				}
			}

			var finalTextureColor = mapTex.GetPixel(x, y);

			if (isTerrain) {
				var alphaBlendedColor = AlphaBlend(heightsTex.GetPixel(x, y), finalTextureColor);
				mapTex.SetPixel(x, y, alphaBlendedColor);

				return;
			}

			var waterLevel = (float)(1f - Math.Round(waterDepth / (waterHeight - heightMin), 6)) + 0.05f;

			var waterAlpha = waterLevel / 2f + waterLevel * 0.4f - 0.5f;

			if (waterAlpha <= 0.2f) waterAlpha = 0.2f;
			if (waterAlpha > 0.5f) waterAlpha  = waterAlpha * 1.1f;

			var blendedColor = AlphaBlend(new Color(finalTextureColor.r, finalTextureColor.g, finalTextureColor.b, waterAlpha * 0.8f + 0.1f),
				finalTextureColor);

			mapTex.SetPixel(x, y, blendedColor);
		}

		private void SetContrast(Texture2D finalTexture, double contrastD = 10, int whiteIdx = 180, double notWhiteMod = 0.9, double whiteMod = 1.0) {
			if (contrastD < -100) contrastD = -100;
			if (contrastD > 100) contrastD  = 100;
			contrastD =  (100.0 + contrastD) / 100.0;
			contrastD *= contrastD;
			Color color;

			for (var i = 0; i < finalTexture.width; i++) {
				for (var j = 0; j < finalTexture.height; j++) {
					color = finalTexture.GetPixel(i, j);

					double pR = color.r;
					pR -= 0.5;
					pR *= contrastD;
					pR += 0.5;
					pR *= 255;

					double pG = color.g;
					pG -= 0.5;
					pG *= contrastD * 1.1f;
					pG += 0.5;
					pG *= 255;

					double pB = color.b;
					pB -= 0.5;
					pB *= contrastD;
					pB += 0.5;
					pB *= 255;

					if (pR < 0) pR   = 0;
					if (pR > 255) pR = 255;
					if (pG < 0) pG   = 0;
					if (pG > 255) pG = 255;
					if (pB < 0) pB   = 0;
					if (pB > 255) pB = 255;

					if ((pR > whiteIdx && pG > whiteIdx & pB > whiteIdx)) {
						pR *= whiteMod;
						pG *= whiteMod;
						pB *= whiteMod;
					} else {
						pR *= notWhiteMod;
						pG *= notWhiteMod;
						pB *= notWhiteMod;
					}

					finalTexture.SetPixel(i, j, new Color((float)pR / 255, (float)pG / 255, (float)pB / 255, color.a));
				}
			}
		}

		private void GenerateMap(int size = 0, string filetype = ".jpg") {
			PrintWarning("Создается изображение карты.Сервер может подвиснуть на несколько минут!");
			TerrainMeta.HeightMap.GenerateTextures();
			var width        = TerrainMeta.Terrain.terrainData.heightmapWidth  - 1;
			var height       = TerrainMeta.Terrain.terrainData.heightmapHeight - 1;
			var finalTexture = new Texture2D(width, height);
			terrain = TerrainMeta.Terrain;

			var polarHeights = GetPolarTerrainHeights();

			Puts($"Начало генерации карты ({finalTexture.height * finalTexture.width} пикcелей)");

			var progress        = 0;
			var terrainPosition = TerrainMeta.Terrain.GetPosition();

			for (var y = 0; y < finalTexture.height; y++)
			for (var x = 0; x < finalTexture.width; x++) {
				var cP = Math.Round((float)y / finalTexture.height * 1000f);

				if (cP > progress) {
					progress = progress + 100;
					Puts($"Генерация карты [{progress / 10} %]");
				}

				ProcessPixel(finalTexture, terrainPosition, height, width, x, y, polarHeights.min, polarHeights.max);
			}

			Puts("Контрастность");
			SetContrast(finalTexture);
			Puts("Сохранение");

			finalTexture.Apply();
			SaveIMG(finalTexture, size, filetype);
			UnityEngine.Object.Destroy(finalTexture);
		}

		class PolarHeights {
			public float min;
			public float max;
		}

		private PolarHeights GetPolarTerrainHeights() {
			var   lowestHeight  = TerrainMeta.Size.y;
			float highestHeight = 0;

			for (var x = 0; x < TerrainMeta.Size.x; x++)
			for (var y = 0; y < TerrainMeta.Size.z; y++) {
				var h = terrain.terrainData.GetHeight(x, y);

				if (h > highestHeight) highestHeight = h;
				if (h < lowestHeight) lowestHeight   = h;
			}

			return new PolarHeights {
				max = highestHeight,
				min = lowestHeight
			};
		}

		private static Color AlphaBlend(Color top, Color bottom) {
			return new Color(BlendSubpixel(top.r, bottom.r, top.a, bottom.a),
				BlendSubpixel(top.g, bottom.g, top.a, bottom.a),
				BlendSubpixel(top.b, bottom.b, top.a, bottom.a),
				top.a + bottom.a);
		}

		private static float BlendSubpixel(float top, float bottom, float alphaTop, float alphaBottom) {
			return top - 0.005f + (alphaTop - 0.455f) + (bottom - 0.78f) * (alphaBottom - 0.0055f);
		}

		private void SaveIMG(Texture2D texture, int size = 0, string filetype = ".jpg") {
			byte[] bytes;

			switch (filetype.ToLower()) {
				case ".jpg":
					bytes = texture.EncodeToJPG();
					break;
				case ".png":
					bytes = texture.EncodeToPNG();
					break;
				default: return;
			}

			if (bytes == null) return;

			Stream stream   = new MemoryStream(bytes);
			var    mapImage = System.Drawing.Image.FromStream(stream);

			if (size != 0 && size != mapImage.Height) {
				mapImage = mapImage.GetThumbnailImage(size, size, () => false, IntPtr.Zero);
			}

			var mapFilePath = Interface.Oxide.DataDirectory
						  + Path.DirectorySeparatorChar
						  + "RustMap"
						  + Path.DirectorySeparatorChar
						  + configData.OptionsSetting.filename
						  + filetype;

			switch (filetype.ToLower()) {
				case ".jpg":
					mapImage.Save(mapFilePath, System.Drawing.Imaging.ImageFormat.Jpeg);
					break;
				case ".png":
					mapImage.Save(mapFilePath, System.Drawing.Imaging.ImageFormat.Png);
					break;
				default: return;
			}

			PrintWarning($"Изображение карты размером {mapImage.Height}x{mapImage.Width} px \nСохранено в: {mapFilePath}");
		}

		#endregion
		#region OxideHooks

		void OnNewSave(string filename) {
			if (!configData.OptionsSetting.AutoMap) return;

			NewWipe = true;
		}

		void OnServerInitialized() {
			if (!configData.OptionsSetting.AutoMap || !NewWipe) return;

			GenerateMap(configData.OptionsSetting.autosize, configData.OptionsSetting.type);
		}

		#endregion
	}
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху