diff --git a/logic/GameClass/GameObj/Map/MapStruct.cs b/logic/GameClass/GameObj/Map/MapStruct.cs index 39c96325..8c7e2d5e 100644 --- a/logic/GameClass/GameObj/Map/MapStruct.cs +++ b/logic/GameClass/GameObj/Map/MapStruct.cs @@ -1,16 +1,30 @@ using Preparation.Utility; +using System; using System.IO; namespace GameClass.MapGenerator; +#region 异常 +public class MapFileError(string filename) : Exception +{ + public override string Message => $"{filename} is illegal map file"; +} + +public class MapStreamError(Stream str) : Exception +{ + public override string Message => $"{str.ToString} is illegal stream of map"; +} +#endregion + /// /// 地图结构体 /// -public struct MapStruct +public readonly struct MapStruct { - public uint height; - public uint width; - public PlaceType[,] map; + public readonly uint height; + public readonly uint width; + public readonly PlaceType[,] map; + #region ctor public MapStruct(uint height, uint width) { @@ -34,30 +48,40 @@ public MapStruct(uint height, uint width, uint[,] map) } } #endregion + + #region 文件读写 /// /// 地图文件读取 /// - /// 地图文件 - /// + /// 待读取地图文件 + /// 读取得到的地图 + /// public static MapStruct FromFile(string filename) { using BinaryReader br = new(File.OpenRead(filename)); - var height = br.ReadUInt32(); var width = br.ReadUInt32(); - MapStruct ret = new(height, width); - for (uint i = 0; i < height; i++) + try { - for (uint j = 0; j < width; j++) + var height = br.ReadUInt32(); var width = br.ReadUInt32(); + MapStruct ret = new(height, width); + for (uint i = 0; i < height; i++) { - ret.map[i, j] = (PlaceType)br.ReadUInt32(); + for (uint j = 0; j < width; j++) + { + ret[i, j] = (PlaceType)br.ReadUInt32(); + } } + return ret; + } + catch + { + throw new MapFileError(filename); } - return ret; } /// /// 地图文件存储 /// - /// 地图文件 - /// 地图 + /// 待写入地图文件 + /// 待写入地图 public static void ToFile(string filename, MapStruct src) { using BinaryWriter bw = new(File.OpenWrite(filename)); @@ -67,18 +91,75 @@ public static void ToFile(string filename, MapStruct src) { for (uint j = 0; j < src.width; j++) { - bw.Write((uint)src.map[i, j]); + bw.Write((uint)src[i, j]); } } } - public void Clear() + #endregion + + #region 流读写 + /// + /// 字节提取 + /// + /// 字节输出流 + /// 提取得到的地图 + /// + public static MapStruct FromBytes(Stream str) + { + if (!str.CanRead) throw new MapStreamError(str); + try + { + BinaryReader br = new(str); + var height = br.ReadUInt32(); var width = br.ReadUInt32(); + MapStruct ret = new(height, width); + for (uint i = 0; i < height; i++) + { + for (uint j = 0; j < width; j++) + { + ret[i, j] = (PlaceType)br.ReadUInt32(); + } + } + return ret; + } + catch + { + throw new MapStreamError(str); + } + } + /// + /// 字节解析 + /// + /// 字节输入流 + /// 待解析地图 + /// + public static void ToBytes(Stream str, MapStruct src) + { + if (!str.CanWrite) throw new MapStreamError(str); + BinaryWriter bw = new(str); + bw.Write(src.height); + bw.Write(src.width); + for (uint i = 0; i < src.height; i++) + { + for (uint j = 0; j < src.width; j++) + { + bw.Write((uint)src[i, j]); + } + } + } + #endregion + + /// + /// 地图清空 + /// + public readonly void Clear() { for (uint i = 0; i < height; i++) { for (uint j = 0; j < width; j++) map[i, j] = PlaceType.Null; } } - public PlaceType this[uint i, uint j] + + public readonly PlaceType this[uint i, uint j] { get => map[i, j]; set => map[i, j] = value; diff --git a/dependency/MapGenerator/README.md b/map-generator/JavaScript/README.md old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator/README.md rename to map-generator/JavaScript/README.md diff --git a/dependency/MapGenerator/assets/css/map.css b/map-generator/JavaScript/assets/css/map.css old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator/assets/css/map.css rename to map-generator/JavaScript/assets/css/map.css diff --git a/dependency/MapGenerator/assets/css/style.css b/map-generator/JavaScript/assets/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator/assets/css/style.css rename to map-generator/JavaScript/assets/css/style.css diff --git a/dependency/MapGenerator-Python/favicon.ico b/map-generator/JavaScript/assets/img/favicon.ico old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator-Python/favicon.ico rename to map-generator/JavaScript/assets/img/favicon.ico diff --git a/dependency/MapGenerator/assets/js/map.js b/map-generator/JavaScript/assets/js/map.js old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator/assets/js/map.js rename to map-generator/JavaScript/assets/js/map.js diff --git a/dependency/MapGenerator/index.html b/map-generator/JavaScript/index.html old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator/index.html rename to map-generator/JavaScript/index.html diff --git a/dependency/MapGenerator-Python/.gitignore b/map-generator/Python/.gitignore old mode 100755 new mode 100644 similarity index 55% rename from dependency/MapGenerator-Python/.gitignore rename to map-generator/Python/.gitignore index e6650953..64af04a6 --- a/dependency/MapGenerator-Python/.gitignore +++ b/map-generator/Python/.gitignore @@ -1,4 +1,5 @@ .vscode/ *.map build/ -dist/ \ No newline at end of file +dist/ +*__pycache__ \ No newline at end of file diff --git a/dependency/MapGenerator-Python/CLR_IMPORT.py b/map-generator/Python/CLR_IMPORT.py similarity index 88% rename from dependency/MapGenerator-Python/CLR_IMPORT.py rename to map-generator/Python/CLR_IMPORT.py index a49493f4..48ceb735 100644 --- a/dependency/MapGenerator-Python/CLR_IMPORT.py +++ b/map-generator/Python/CLR_IMPORT.py @@ -6,13 +6,15 @@ r'../../logic/Preparation/bin/Release/net8.0/', r'../../../logic/Preparation/bin/Debug/net8.0/', r'../../../logic/Preparation/bin/Release/net8.0/', - r'_internal/'] + r'./', + r'./_internal/'] PREPARATION = 'Preparation' GAMECLASS_IMPORT = [r'../../logic/GameClass/bin/Debug/net8.0/', r'../../logic/GameClass/bin/Release/net8.0/', r'../../../logic/GameClass/bin/Debug/net8.0/', r'../../../logic/GameClass/bin/Release/net8.0/', - r'_internal/'] + r'./', + r'./_internal/'] GAMECLASS = 'GameClass' diff --git a/dependency/MapGenerator-Python/CLR_START.py b/map-generator/Python/CLR_START.py similarity index 100% rename from dependency/MapGenerator-Python/CLR_START.py rename to map-generator/Python/CLR_START.py diff --git a/dependency/MapGenerator-Python/Classes/MapRenderer.py b/map-generator/Python/Classes/MapRenderer.py old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator-Python/Classes/MapRenderer.py rename to map-generator/Python/Classes/MapRenderer.py diff --git a/dependency/MapGenerator-Python/Classes/RandomCore.py b/map-generator/Python/Classes/RandomCore.py old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator-Python/Classes/RandomCore.py rename to map-generator/Python/Classes/RandomCore.py diff --git a/dependency/MapGenerator-Python/Classes/RandomCores/PerlinRandomCore.py b/map-generator/Python/Classes/RandomCores/PerlinRandomCore.py old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator-Python/Classes/RandomCores/PerlinRandomCore.py rename to map-generator/Python/Classes/RandomCores/PerlinRandomCore.py diff --git "a/dependency/MapGenerator-Python/Classes/RandomCores/\320\241\321\216\320\271\320\247\321\215\320\275RandomCore.py" b/map-generator/Python/Classes/RandomCores/XuchengRandomCore.py old mode 100755 new mode 100644 similarity index 71% rename from "dependency/MapGenerator-Python/Classes/RandomCores/\320\241\321\216\320\271\320\247\321\215\320\275RandomCore.py" rename to map-generator/Python/Classes/RandomCores/XuchengRandomCore.py index 09401dd8..af8ef53f --- "a/dependency/MapGenerator-Python/Classes/RandomCores/\320\241\321\216\320\271\320\247\321\215\320\275RandomCore.py" +++ b/map-generator/Python/Classes/RandomCores/XuchengRandomCore.py @@ -9,7 +9,7 @@ from Classes.RandomCore import RandomCore -class DefaultСюйЧэнRandomSettings: +class DefaultXuchengRandomSettings: asteroidWidth = 2 resourceNum = 7 constructionNum = 5 @@ -19,7 +19,7 @@ class DefaultСюйЧэнRandomSettings: ruinCrossBonus = 40 -class СюйЧэнRandomCore(RandomCore): +class XuchengRandomCore(RandomCore): title: str asteroidWidth: int resourceNum: int @@ -36,7 +36,7 @@ def AsteroidWidth(self) -> int: @AsteroidWidth.setter def AsteroidWidth(self, value: int) -> None: if value < 1 or value > 4: - self.asteroidWidth = DefaultСюйЧэнRandomSettings.asteroidWidth + self.asteroidWidth = DefaultXuchengRandomSettings.asteroidWidth else: self.asteroidWidth = value @@ -47,7 +47,7 @@ def ResourceNum(self) -> int: @ResourceNum.setter def ResourceNum(self, value: int) -> None: if value < 1 or value > 10: - self.resourceNum = DefaultСюйЧэнRandomSettings.resourceNum + self.resourceNum = DefaultXuchengRandomSettings.resourceNum else: self.resourceNum = value @@ -58,7 +58,7 @@ def ConstructionNum(self) -> int: @ConstructionNum.setter def ConstructionNum(self, value: int) -> None: if value < 1 or value > 10: - self.constructionNum = DefaultСюйЧэнRandomSettings.constructionNum + self.constructionNum = DefaultXuchengRandomSettings.constructionNum else: self.constructionNum = value @@ -69,7 +69,7 @@ def ShadowProb(self) -> float: @ShadowProb.setter def ShadowProb(self, value: float) -> None: if value < 0 or value > 0.1: - self.shadowProb = DefaultСюйЧэнRandomSettings.shadowProb + self.shadowProb = DefaultXuchengRandomSettings.shadowProb else: self.shadowProb = value @@ -80,7 +80,7 @@ def ShadowCrossBonus(self) -> int: @ShadowCrossBonus.setter def ShadowCrossBonus(self, value: int) -> None: if value < 1 or value > 50: - self.shadowCrossBonus = DefaultСюйЧэнRandomSettings.shadowCrossBonus + self.shadowCrossBonus = DefaultXuchengRandomSettings.shadowCrossBonus else: self.shadowCrossBonus = value @@ -91,7 +91,7 @@ def RuinProb(self) -> float: @RuinProb.setter def RuinProb(self, value: float) -> None: if value < 0 or value > 0.1: - self.ruinProb = DefaultСюйЧэнRandomSettings.ruinProb + self.ruinProb = DefaultXuchengRandomSettings.ruinProb else: self.ruinProb = value @@ -102,19 +102,19 @@ def RuinCrossBonus(self) -> int: @RuinCrossBonus.setter def RuinCrossBonus(self, value: int) -> None: if value < 1 or value > 50: - self.ruinCrossBonus = DefaultСюйЧэнRandomSettings.ruinCrossBonus + self.ruinCrossBonus = DefaultXuchengRandomSettings.ruinCrossBonus else: self.ruinCrossBonus = value def __init__(self, title, - asteroidWidth: int = DefaultСюйЧэнRandomSettings.asteroidWidth, - resourceNum: int = DefaultСюйЧэнRandomSettings.resourceNum, - constructionNum: int = DefaultСюйЧэнRandomSettings.constructionNum, - shadowProb: float = DefaultСюйЧэнRandomSettings.shadowProb, - shadowCrossBonus: int = DefaultСюйЧэнRandomSettings.shadowCrossBonus, - ruinProb: float = DefaultСюйЧэнRandomSettings.ruinProb, - ruinCrossBonus: int = DefaultСюйЧэнRandomSettings.ruinCrossBonus) -> None: + asteroidWidth: int = DefaultXuchengRandomSettings.asteroidWidth, + resourceNum: int = DefaultXuchengRandomSettings.resourceNum, + constructionNum: int = DefaultXuchengRandomSettings.constructionNum, + shadowProb: float = DefaultXuchengRandomSettings.shadowProb, + shadowCrossBonus: int = DefaultXuchengRandomSettings.shadowCrossBonus, + ruinProb: float = DefaultXuchengRandomSettings.ruinProb, + ruinCrossBonus: int = DefaultXuchengRandomSettings.ruinCrossBonus) -> None: self.title = title self.AsteroidWidth = asteroidWidth self.ResourceNum = resourceNum @@ -126,7 +126,7 @@ def __init__(self, @property def Name(self) -> str: - return 'СюйЧэн' + return 'Xucheng' def Menu(self) -> bool: try: @@ -163,14 +163,14 @@ def Menu(self) -> bool: def Random(self, mp: MapStruct) -> None: mp.Clear() - СюйЧэнRandomCore.generateBorderRuin(mp) - СюйЧэнRandomCore.generateHome(mp) - СюйЧэнRandomCore.generateAsteroid(mp, self.asteroidWidth) - СюйЧэнRandomCore.generateResource(mp, self.resourceNum) - СюйЧэнRandomCore.generateConstruction(mp, self.constructionNum) - СюйЧэнRandomCore.generateShadow(mp, self.shadowProb, self.shadowCrossBonus) - СюйЧэнRandomCore.generateRuin(mp, self.ruinProb, self.ruinCrossBonus) - СюйЧэнRandomCore.generateWormhole(mp) + XuchengRandomCore.generateBorderRuin(mp) + XuchengRandomCore.generateHome(mp) + XuchengRandomCore.generateAsteroid(mp, self.asteroidWidth) + XuchengRandomCore.generateResource(mp, self.resourceNum) + XuchengRandomCore.generateConstruction(mp, self.constructionNum) + XuchengRandomCore.generateShadow(mp, self.shadowProb, self.shadowCrossBonus) + XuchengRandomCore.generateRuin(mp, self.ruinProb, self.ruinCrossBonus) + XuchengRandomCore.generateWormhole(mp) @staticmethod def isEmptyNearby(mp: MapStruct, x: int, y: int, r: int) -> bool: @@ -214,7 +214,7 @@ def generateHome(mp: MapStruct) -> None: mp[46, 3] = PT.Home @staticmethod - def generateAsteroid(mp: MapStruct, width: int = DefaultСюйЧэнRandomSettings.asteroidWidth) -> None: + def generateAsteroid(mp: MapStruct, width: int = DefaultXuchengRandomSettings.asteroidWidth) -> None: for i in range(1, 49): for j in range(24, 24 - width, -1): mp[i, j] = PT.Asteroid @@ -227,12 +227,12 @@ def generateAsteroid(mp: MapStruct, width: int = DefaultСюйЧэнRandomSettin mp[49 - i, 25 - width] = PT.Null @staticmethod - def generateResource(mp: MapStruct, num: int = DefaultСюйЧэнRandomSettings.resourceNum) -> None: + def generateResource(mp: MapStruct, num: int = DefaultXuchengRandomSettings.resourceNum) -> None: i = 0 while i < num: x = floor(random() * 48) + 1 y = floor(random() * 23) + 1 - if СюйЧэнRandomCore.isEmptyNearby(mp, x, y, 2): + if XuchengRandomCore.isEmptyNearby(mp, x, y, 2): mp[x, y] = PT.Resource mp[49 - x, 49 - y] = PT.Resource else: @@ -240,12 +240,12 @@ def generateResource(mp: MapStruct, num: int = DefaultСюйЧэнRandomSettings i += 1 @staticmethod - def generateConstruction(mp: MapStruct, num: int = DefaultСюйЧэнRandomSettings.constructionNum) -> None: + def generateConstruction(mp: MapStruct, num: int = DefaultXuchengRandomSettings.constructionNum) -> None: i = 0 while i < num: x = floor(random() * 48) + 1 y = floor(random() * 23) + 1 - if СюйЧэнRandomCore.isEmptyNearby(mp, x, y, 1): + if XuchengRandomCore.isEmptyNearby(mp, x, y, 1): mp[x, y] = PT.Construction mp[49 - x, 49 - y] = PT.Construction else: @@ -253,26 +253,26 @@ def generateConstruction(mp: MapStruct, num: int = DefaultСюйЧэнRandomSett i += 1 @staticmethod - def generateShadow(mp: MapStruct, prob: float = DefaultСюйЧэнRandomSettings.shadowProb, - crossBonus: int = DefaultСюйЧэнRandomSettings.shadowCrossBonus) -> None: + def generateShadow(mp: MapStruct, prob: float = DefaultXuchengRandomSettings.shadowProb, + crossBonus: int = DefaultXuchengRandomSettings.shadowCrossBonus) -> None: for i in range(50): for j in range(50): if (mp[i, j] == PT.Null and - random() < prob * (СюйЧэнRandomCore.haveSthCross(mp, i, j, 1, PT.Shadow) * crossBonus + 1)): + random() < prob * (XuchengRandomCore.haveSthCross(mp, i, j, 1, PT.Shadow) * crossBonus + 1)): mp[i, j] = PT.Shadow mp[49 - i, 49 - j] = PT.Shadow @staticmethod - def generateRuin(mp: MapStruct, prob: float = DefaultСюйЧэнRandomSettings.ruinProb, - crossBonus: int = DefaultСюйЧэнRandomSettings.ruinCrossBonus) -> None: + def generateRuin(mp: MapStruct, prob: float = DefaultXuchengRandomSettings.ruinProb, + crossBonus: int = DefaultXuchengRandomSettings.ruinCrossBonus) -> None: for i in range(2, 48): for j in range(2, 48): if ((mp[i, j] == PT.Null or mp[i, j] == PT.Shadow) and - not СюйЧэнRandomCore.haveSthNearby(mp, i, j, 1, PT.Asteroid) and - not СюйЧэнRandomCore.haveSthNearby(mp, i, j, 1, PT.Home) and + not XuchengRandomCore.haveSthNearby(mp, i, j, 1, PT.Asteroid) and + not XuchengRandomCore.haveSthNearby(mp, i, j, 1, PT.Home) and random() < prob - * (СюйЧэнRandomCore.haveSthCross(mp, i, j, 1, PT.Ruin) - * (0 if СюйЧэнRandomCore.haveSthCross(mp, i, j, 1, PT.Ruin) > 1 + * (XuchengRandomCore.haveSthCross(mp, i, j, 1, PT.Ruin) + * (0 if XuchengRandomCore.haveSthCross(mp, i, j, 1, PT.Ruin) > 1 else crossBonus) + 1)): mp[i, j] = PT.Ruin mp[49 - i, 49 - j] = PT.Ruin diff --git a/dependency/MapGenerator-Python/GameClass/MapGenerator.pyi b/map-generator/Python/GameClass/MapGenerator.pyi similarity index 100% rename from dependency/MapGenerator-Python/GameClass/MapGenerator.pyi rename to map-generator/Python/GameClass/MapGenerator.pyi diff --git a/dependency/MapGenerator-Python/MapGenerator.spec b/map-generator/Python/MapGenerator.spec old mode 100755 new mode 100644 similarity index 82% rename from dependency/MapGenerator-Python/MapGenerator.spec rename to map-generator/Python/MapGenerator.spec index 333e8673..84986753 --- a/dependency/MapGenerator-Python/MapGenerator.spec +++ b/map-generator/Python/MapGenerator.spec @@ -5,8 +5,8 @@ a = Analysis( ['main.py'], pathex=[], binaries=[], - datas=[('../../logic/Preparation/bin/Debug/net8.0/Preparation.dll', '.'), - ('../../logic/GameClass/bin/Debug/net8.0/GameClass.dll', '.') + datas=[('../../logic/Preparation/bin/Release/net8.0/Preparation.dll', '.'), + ('../../logic/GameClass/bin/Release/net8.0/GameClass.dll', '.') ], hiddenimports=[], hookspath=[], diff --git a/dependency/MapGenerator-Python/Pipfile b/map-generator/Python/Pipfile old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator-Python/Pipfile rename to map-generator/Python/Pipfile diff --git a/dependency/MapGenerator-Python/Pipfile.lock b/map-generator/Python/Pipfile.lock old mode 100755 new mode 100644 similarity index 86% rename from dependency/MapGenerator-Python/Pipfile.lock rename to map-generator/Python/Pipfile.lock index e33cef7f..4379ec69 --- a/dependency/MapGenerator-Python/Pipfile.lock +++ b/map-generator/Python/Pipfile.lock @@ -254,51 +254,51 @@ }, "fonttools": { "hashes": [ - "sha256:0452fcbfbce752ba596737a7c5ec5cf76bc5f83847ce1781f4f90eab14ece252", - "sha256:0a2417547462e468edf35b32e3dd06a6215ac26aa6316b41e03b8eeaf9f079ea", - "sha256:0d2b01428f7da26f229a5656defc824427b741e454b4e210ad2b25ed6ea2aed4", - "sha256:0d533f89819f9b3ee2dbedf0fed3825c425850e32bdda24c558563c71be0064e", - "sha256:12ee86abca46193359ea69216b3a724e90c66ab05ab220d39e3fc068c1eb72ac", - "sha256:18b35fd1a850ed7233a99bbd6774485271756f717dac8b594958224b54118b61", - "sha256:292922dc356d7f11f5063b4111a8b719efb8faea92a2a88ed296408d449d8c2e", - "sha256:2eb4167bde04e172a93cf22c875d8b0cff76a2491f67f5eb069566215302d45d", - "sha256:3cdb9a92521b81bf717ebccf592bd0292e853244d84115bfb4db0c426de58348", - "sha256:4108b1d247953dd7c90ec8f457a2dec5fceb373485973cc852b14200118a51ee", - "sha256:4709c5bf123ba10eac210d2d5c9027d3f472591d9f1a04262122710fa3d23199", - "sha256:5057ade278e67923000041e2b195c9ea53e87f227690d499b6a4edd3702f7f01", - "sha256:56339ec557f0c342bddd7c175f5e41c45fc21282bee58a86bd9aa322bec715f2", - "sha256:578c00f93868f64a4102ecc5aa600a03b49162c654676c3fadc33de2ddb88a81", - "sha256:594206b31c95fcfa65f484385171fabb4ec69f7d2d7f56d27f17db26b7a31814", - "sha256:63c73b9dd56a94a3cbd2f90544b5fca83666948a9e03370888994143b8d7c070", - "sha256:63dc592a16cd08388d8c4c7502b59ac74190b23e16dfc863c69fe1ea74605b68", - "sha256:6978bade7b6c0335095bdd0bd97f8f3d590d2877b370f17e03e0865241694eb5", - "sha256:6f30e605c7565d0da6f0aec75a30ec372072d016957cd8fc4469721a36ea59b7", - "sha256:702ae93058c81f46461dc4b2c79f11d3c3d8fd7296eaf8f75b4ba5bbf813cd5f", - "sha256:8b8a45254218679c7f1127812761e7854ed5c8e34349aebf581e8c9204e7495a", - "sha256:902e9c4e9928301912f34a6638741b8ae0b64824112b42aaf240e06b735774b1", - "sha256:97f0a49fa6aa2d6205c6f72f4f98b74ef4b9bfdcb06fd78e6fe6c7af4989b63e", - "sha256:9b4ec6d42a7555f5ae35f3b805482f0aad0f1baeeef54859492ea3b782959d4a", - "sha256:9b58638d8a85e3a1b32ec0a91d9f8171a877b4b81c408d4cb3257d0dee63e092", - "sha256:a8c8b54bd1420c184a995f980f1a8076f87363e2bb24239ef8c171a369d85a31", - "sha256:aee76fd81a8571c68841d6ef0da750d5ff08ff2c5f025576473016f16ac3bcf7", - "sha256:b10633aafc5932995a391ec07eba5e79f52af0003a1735b2306b3dab8a056d48", - "sha256:bcd77f89fc1a6b18428e7a55dde8ef56dae95640293bfb8f4e929929eba5e2a2", - "sha256:bff5b38d0e76eb18e0b8abbf35d384e60b3371be92f7be36128ee3e67483b3ec", - "sha256:c900508c46274d32d308ae8e82335117f11aaee1f7d369ac16502c9a78930b0a", - "sha256:cad5cfd044ea2e306fda44482b3dd32ee47830fa82dfa4679374b41baa294f5f", - "sha256:cdfd7557d1bd294a200bd211aa665ca3b02998dcc18f8211a5532da5b8fad5c5", - "sha256:cf5a0cd974f85a80b74785db2d5c3c1fd6cc09a2ba3c837359b2b5da629ee1b0", - "sha256:d10979ef14a8beaaa32f613bb698743f7241d92f437a3b5e32356dfb9769c65d", - "sha256:d20588466367f05025bb1efdf4e5d498ca6d14bde07b6928b79199c588800f0a", - "sha256:d3260db55f1843e57115256e91247ad9f68cb02a434b51262fe0019e95a98738", - "sha256:df48798f9a4fc4c315ab46e17873436c8746f5df6eddd02fad91299b2af7af95", - "sha256:e3e33862fc5261d46d9aae3544acb36203b1a337d00bdb5d3753aae50dac860e", - "sha256:e740a7602c2bb71e1091269b5dbe89549749a8817dc294b34628ffd8b2bf7124", - "sha256:f40441437b039930428e04fb05ac3a132e77458fb57666c808d74a556779e784", - "sha256:f7449493886da6a17472004d3818cc050ba3f4a0aa03fb47972e4fa5578e6703" + "sha256:0404faea044577a01bb82d47a8fa4bc7a54067fa7e324785dd65d200d6dd1133", + "sha256:07bc5ea02bb7bc3aa40a1eb0481ce20e8d9b9642a9536cde0218290dd6085828", + "sha256:08877e355d3dde1c11973bb58d4acad1981e6d1140711230a4bfb40b2b937ccc", + "sha256:0af65c720520710cc01c293f9c70bd69684365c6015cc3671db2b7d807fe51f2", + "sha256:0ba0e00620ca28d4ca11fc700806fd69144b463aa3275e1b36e56c7c09915559", + "sha256:1f255ce8ed7556658f6d23f6afd22a6d9bbc3edb9b96c96682124dc487e1bf42", + "sha256:1fac1b7eebfce75ea663e860e7c5b4a8831b858c17acd68263bc156125201abf", + "sha256:263832fae27481d48dfafcc43174644b6706639661e242902ceb30553557e16c", + "sha256:29e89d0e1a7f18bc30f197cfadcbef5a13d99806447c7e245f5667579a808036", + "sha256:33037d9e56e2562c710c8954d0f20d25b8386b397250d65581e544edc9d6b942", + "sha256:33c584c0ef7dc54f5dd4f84082eabd8d09d1871a3d8ca2986b0c0c98165f8e86", + "sha256:36c8865bdb5cfeec88f5028e7e592370a0657b676c6f1d84a2108e0564f90e22", + "sha256:4145f91531fd43c50f9eb893faa08399816bb0b13c425667c48475c9f3a2b9b5", + "sha256:4d418b1fee41a1d14931f7ab4b92dc0bc323b490e41d7a333eec82c9f1780c75", + "sha256:768947008b4dc552d02772e5ebd49e71430a466e2373008ce905f953afea755a", + "sha256:7c7125068e04a70739dad11857a4d47626f2b0bd54de39e8622e89701836eabd", + "sha256:83a0d9336de2cba86d886507dd6e0153df333ac787377325a39a2797ec529814", + "sha256:86eef6aab7fd7c6c8545f3ebd00fd1d6729ca1f63b0cb4d621bccb7d1d1c852b", + "sha256:8fb022d799b96df3eaa27263e9eea306bd3d437cc9aa981820850281a02b6c9a", + "sha256:9d95fa0d22bf4f12d2fb7b07a46070cdfc19ef5a7b1c98bc172bfab5bf0d6844", + "sha256:a974c49a981e187381b9cc2c07c6b902d0079b88ff01aed34695ec5360767034", + "sha256:ac9a745b7609f489faa65e1dc842168c18530874a5f5b742ac3dd79e26bca8bc", + "sha256:af20acbe198a8a790618ee42db192eb128afcdcc4e96d99993aca0b60d1faeb4", + "sha256:af281525e5dd7fa0b39fb1667b8d5ca0e2a9079967e14c4bfe90fd1cd13e0f18", + "sha256:b050d362df50fc6e38ae3954d8c29bf2da52be384649ee8245fdb5186b620836", + "sha256:b44a52b8e6244b6548851b03b2b377a9702b88ddc21dcaf56a15a0393d425cb9", + "sha256:b607ea1e96768d13be26d2b400d10d3ebd1456343eb5eaddd2f47d1c4bd00880", + "sha256:b85ec0bdd7bdaa5c1946398cbb541e90a6dfc51df76dfa88e0aaa41b335940cb", + "sha256:bebd91041dda0d511b0d303180ed36e31f4f54b106b1259b69fade68413aa7ff", + "sha256:c076a9e548521ecc13d944b1d261ff3d7825048c338722a4bd126d22316087b7", + "sha256:cbe61b158deb09cffdd8540dc4a948d6e8f4d5b4f3bf5cd7db09bd6a61fee64e", + "sha256:cdee3ab220283057e7840d5fb768ad4c2ebe65bdba6f75d5d7bf47f4e0ed7d29", + "sha256:ce7033cb61f2bb65d8849658d3786188afd80f53dad8366a7232654804529532", + "sha256:d00af0884c0e65f60dfaf9340e26658836b935052fdd0439952ae42e44fdd2be", + "sha256:d647a0e697e5daa98c87993726da8281c7233d9d4ffe410812a4896c7c57c075", + "sha256:d970ecca0aac90d399e458f0b7a8a597e08f95de021f17785fb68e2dc0b99717", + "sha256:ea329dafb9670ffbdf4dbc3b0e5c264104abcd8441d56de77f06967f032943cb", + "sha256:ebf46e7f01b7af7861310417d7c49591a85d99146fc23a5ba82fdb28af156321", + "sha256:edc0cce355984bb3c1d1e89d6a661934d39586bb32191ebff98c600f8957c63e", + "sha256:f3bbe672df03563d1f3a691ae531f2e31f84061724c319652039e5a70927167e", + "sha256:fc11e5114f3f978d0cea7e9853627935b30d451742eeb4239a81a677bdee6bf6", + "sha256:fdb54b076f25d6b0f0298dc706acee5052de20c83530fa165b60d1f2e9cbe3cb" ], "markers": "python_version >= '3.8'", - "version": "==4.48.1" + "version": "==4.49.0" }, "kiwisolver": { "hashes": [ @@ -412,38 +412,38 @@ }, "matplotlib": { "hashes": [ - "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1", - "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0", - "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4", - "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7", - "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630", - "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89", - "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d", - "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717", - "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a", - "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627", - "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31", - "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213", - "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843", - "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788", - "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367", - "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4", - "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a", - "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8", - "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b", - "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18", - "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6", - "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa", - "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917", - "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20", - "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331", - "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63", - "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f", - "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8" + "sha256:04b36ad07eac9740fc76c2aa16edf94e50b297d6eb4c081e3add863de4bb19a7", + "sha256:09074f8057917d17ab52c242fdf4916f30e99959c1908958b1fc6032e2d0f6d4", + "sha256:1c5c8290074ba31a41db1dc332dc2b62def469ff33766cbe325d32a3ee291aea", + "sha256:242489efdb75b690c9c2e70bb5c6550727058c8a614e4c7716f363c27e10bba1", + "sha256:40321634e3a05ed02abf7c7b47a50be50b53ef3eaa3a573847431a545585b407", + "sha256:4c6e00a65d017d26009bac6808f637b75ceade3e1ff91a138576f6b3065eeeba", + "sha256:5184e07c7e1d6d1481862ee361905b7059f7fe065fc837f7c3dc11eeb3f2f900", + "sha256:5745f6d0fb5acfabbb2790318db03809a253096e98c91b9a31969df28ee604aa", + "sha256:5e431a09e6fab4012b01fc155db0ce6dccacdbabe8198197f523a4ef4805eb26", + "sha256:5f557156f7116be3340cdeef7f128fa99b0d5d287d5f41a16e169819dcf22357", + "sha256:6728dde0a3997396b053602dbd907a9bd64ec7d5cf99e728b404083698d3ca01", + "sha256:7b416239e9ae38be54b028abbf9048aff5054a9aba5416bef0bd17f9162ce161", + "sha256:7c42dae72a62f14982f1474f7e5c9959fc4bc70c9de11cc5244c6e766200ba65", + "sha256:813925d08fb86aba139f2d31864928d67511f64e5945ca909ad5bc09a96189bb", + "sha256:83c0653c64b73926730bd9ea14aa0f50f202ba187c307a881673bad4985967b7", + "sha256:83e0f72e2c116ca7e571c57aa29b0fe697d4c6425c4e87c6e994159e0c008635", + "sha256:b3c5f96f57b0369c288bf6f9b5274ba45787f7e0589a34d24bdbaf6d3344632f", + "sha256:b97653d869a71721b639714b42d87cda4cfee0ee74b47c569e4874c7590c55c5", + "sha256:bf5932eee0d428192c40b7eac1399d608f5d995f975cdb9d1e6b48539a5ad8d0", + "sha256:c4af3f7317f8a1009bbb2d0bf23dfaba859eb7dd4ccbd604eba146dccaaaf0a4", + "sha256:cd3a0c2be76f4e7be03d34a14d49ded6acf22ef61f88da600a18a5cd8b3c5f3c", + "sha256:cf60138ccc8004f117ab2a2bad513cc4d122e55864b4fe7adf4db20ca68a078f", + "sha256:d7e7e0993d0758933b1a241a432b42c2db22dfa37d4108342ab4afb9557cbe3e", + "sha256:e7b49ab49a3bea17802df6872f8d44f664ba8f9be0632a60c99b20b6db2165b7", + "sha256:e9764df0e8778f06414b9d281a75235c1e85071f64bb5d71564b97c1306a2afc", + "sha256:ef6c1025a570354297d6c15f7d0f296d95f88bd3850066b7f1e7b4f2f4c13a39", + "sha256:f386cf162b059809ecfac3bcc491a9ea17da69fa35c8ded8ad154cd4b933d5ec", + "sha256:fa93695d5c08544f4a0dfd0965f378e7afc410d8672816aff1e81be1f45dbf2e" ], "index": "pip_conf_index_global", "markers": "python_version >= '3.9'", - "version": "==3.8.2" + "version": "==3.8.3" }, "numpy": { "hashes": [ @@ -594,11 +594,11 @@ }, "python-dateutil": { "hashes": [ - "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", - "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.8.2" + "version": "==2.9.0.post0" }, "pythonnet": { "hashes": [ diff --git a/dependency/MapGenerator-Python/Preparation/Utility.pyi b/map-generator/Python/Preparation/Utility.pyi similarity index 100% rename from dependency/MapGenerator-Python/Preparation/Utility.pyi rename to map-generator/Python/Preparation/Utility.pyi diff --git a/map-generator/Python/README.md b/map-generator/Python/README.md new file mode 100644 index 00000000..f3e79030 --- /dev/null +++ b/map-generator/Python/README.md @@ -0,0 +1,88 @@ +# MapGenerator开发指南 + +- [MapGenerator开发指南](#mapgenerator开发指南) + - [虚拟环境](#虚拟环境) + - [代码说明](#代码说明) + - [构建项目](#构建项目) + - [其他](#其他) + +## 虚拟环境 + +本项目使用 `pipenv`[^1] 管理虚拟环境. + +`Pipfile` 是关于虚拟环境的信息, 包括 `pip` 的信息、项目使用的第三方库和项目的 Python 版本. + +`Pipfile.lock` 类似于传统的 `requirements.txt`, 用于确保依赖版本的适配. 使用如下指令可以按照 `Pipfile.lock` 安装依赖: + +```shell +pipenv install # 从Pipfile安装 +pipenv install --dev # 安装为仅开发 +pipenv sync # 从Pipfile.lock安装 +``` + +向环境中加入依赖, 使用: + +```shell +pipenv install package # 安装依赖 +pipenv install --dev dev_package # 仅开发安装 +``` + +删除依赖, 需要使用: + +```shell +pipenv uninstall your_package +``` + +在虚拟环境中运行脚本, 使用如下指令: + +```shell +pipenv run python3 main.py +``` + +## 代码说明 + +`./CLR_START.py`、`./CLR_IMPORT.py` 为使用 PythonNet 加载 CLR 的脚本. 在 `./CLR_IMPORT.py` 中有一串 `GameClass` 和 `Preparation` 路径, 是所需的 C# DLL 的位置. 如果出现找不到 DLL 的问题, 请检查 C# 是否编译以及编译产物的路径. + +`./GameClass/MapGenerator.pyi`、`./Preparation/Utility.pyi` 和 `./System.pyi` 为 C# DLL 的调用存根, 用于语法高亮; 不需要语法高亮请无视或删除. + +> 本项目使用了 C# 的 `GameClass.MapGenerator.MapStruct` 和 `Preparation.Utility.PlaceType`, 以及 C# 的基础类型 `UInt32`、`string` 和 `Array`. +> PythonNet 可以自动将数字和字符串类型在 Python 和 Dotnet 之间转换. + +`./SETTINGS.py` 为设置脚本, 分别为程序窗口标题、地图文件后缀名和地图区域类型所对应的颜色. + +`./Classes/MapRenderer.py` 为程序主体, 负责提供 UI 界面和地图渲染及编辑. 其中存在 `on_click()`(鼠标事件侦测) 和 `on_press()`(键盘事件侦测), 可按需修改. + +`./Classes/RandomCore.py` 为 `RandomCore` 虚基类的所在. + +`./Classes/RandomCores/` 为 `RandomCore` 的实现. + +> 注意: `RandomCore` 的实现具有强的项目依赖性, 请根据项目实际情况重写. + +`./main.py` 为启动脚本. 其中需要留意的是 `RandomCore` 的注册——将其改为重写后的实现. + +## 构建项目 + +在代码根据项目实际修改完成后, 先编译依赖 C# DLL. + +C# DLL 编译完成后, 再次检查 DLL 的路径, 包括 `./CLR_IMPORT.py` 的路径和 `./MapGenerator.spec` 里 `datas` 参数的路径. + +检查完成后, 运行下列命令即可: + +```shell +# 首次编译 +pipenv run pyinstaller ./MapGenerator.spec +# 如果项目编译过一次了, 用这个跳过文件夹清除询问 +pipenv run pyinstaller ./MapGenerator.spec -y +``` + +项目编译在 `./dist/`下. + +## 其他 + +`./pyproject.toml` 目前用于规定 autopep8 代码格式化参数. 想要格式化代码, 只需: + +```shell +autopep8 . +``` + +[^1]: https://pipenv.pypa.io/en/latest/cli.html \ No newline at end of file diff --git a/dependency/MapGenerator-Python/SETTINGS.py b/map-generator/Python/SETTINGS.py similarity index 100% rename from dependency/MapGenerator-Python/SETTINGS.py rename to map-generator/Python/SETTINGS.py diff --git a/dependency/MapGenerator-Python/System.pyi b/map-generator/Python/System.pyi similarity index 72% rename from dependency/MapGenerator-Python/System.pyi rename to map-generator/Python/System.pyi index 2e34aeda..0b351596 100644 --- a/dependency/MapGenerator-Python/System.pyi +++ b/map-generator/Python/System.pyi @@ -7,11 +7,11 @@ from __future__ import annotations class UInt32: - def __init__(self, i: int) -> None: ... + def __init__(self, _: int) -> None: ... class String: - def __init__(self, s: str) -> None: ... + def __init__(self, _: str) -> None: ... class Array[T]: diff --git a/dependency/MapGenerator/assets/img/favicon.ico b/map-generator/Python/favicon.ico old mode 100755 new mode 100644 similarity index 100% rename from dependency/MapGenerator/assets/img/favicon.ico rename to map-generator/Python/favicon.ico diff --git a/dependency/MapGenerator-Python/main.py b/map-generator/Python/main.py old mode 100755 new mode 100644 similarity index 52% rename from dependency/MapGenerator-Python/main.py rename to map-generator/Python/main.py index 94842829..db90c938 --- a/dependency/MapGenerator-Python/main.py +++ b/map-generator/Python/main.py @@ -1,17 +1,30 @@ from __future__ import annotations -from io import TextIOWrapper import os import os.path +import sys from easygui import multenterbox import CLR_IMPORT import SETTINGS -from System import UInt32, String from GameClass.MapGenerator import MapStruct from Classes.MapRenderer import MapRenderer from Classes.RandomCores.PerlinRandomCore import PerlinRandomCore -from Classes.RandomCores.СюйЧэнRandomCore import СюйЧэнRandomCore +from Classes.RandomCores.XuchengRandomCore import XuchengRandomCore + +# 命令行接口 +if (argc := len(sys.argv)) != 1: + match sys.argv[1]: + # 生成器最小化 + case "--min": + randomCore = XuchengRandomCore(SETTINGS.title) + mapStruct = MapStruct(50, 50) + randomCore.Random(mapStruct) + if argc >= 3: + MapStruct.ToFile(sys.argv[2], mapStruct) + else: + MapStruct.ToFile(f"demo{SETTINGS.file_suffix}", mapStruct) + exit(0) # 获取路径 path: str = multenterbox(msg='', title=SETTINGS.title, fields=[f'Path(*{SETTINGS.file_suffix})'])[0] @@ -19,14 +32,14 @@ path += SETTINGS.file_suffix # 地图加载 if not os.path.exists(path): - height, width = [UInt32(int(x)) + height, width = [int(x) for x in multenterbox(msg='Create new map', title=SETTINGS.title, fields=['Height', 'Width'])] mapStruct = MapStruct(height, width) - MapStruct.ToFile(String(path), mapStruct) + MapStruct.ToFile(path, mapStruct) else: - mapStruct = MapStruct.FromFile(String(path)) + mapStruct = MapStruct.FromFile(path) # 随机核加载 -randomCores = [СюйЧэнRandomCore(SETTINGS.title), PerlinRandomCore(SETTINGS.title)] +randomCores = [XuchengRandomCore(SETTINGS.title), PerlinRandomCore(SETTINGS.title)] # 地图渲染 -mapRenderer = MapRenderer(SETTINGS.title, mapStruct, SETTINGS.areas, String(path), randomCores) +mapRenderer = MapRenderer(SETTINGS.title, mapStruct, SETTINGS.areas, path, randomCores) mapRenderer.MainFrame() diff --git a/dependency/MapGenerator-Python/pyproject.toml b/map-generator/Python/pyproject.toml similarity index 100% rename from dependency/MapGenerator-Python/pyproject.toml rename to map-generator/Python/pyproject.toml