1
0
Fork 0

Added PieceStructures generator.

This commit is contained in:
Mattes D 2015-11-11 10:32:42 +01:00
parent 1a9c023d6c
commit b8fbba5eb9
56 changed files with 18104 additions and 12079 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,767 @@
-- TestRails.cubeset
-- Defines the prefabs in the group TestRails
-- NOTE: This file has been generated automatically by GalExport!
-- Any manual changes will be overwritten by the next automatic export!
Cubeset =
{
Metadata =
{
CubesetFormatVersion = 1,
ExportDate = "2015-11-28 16:54:47",
["GridSizeX"] = "10",
["GridSizeZ"] = "10",
["IntendedUse"] = "PieceStructures",
["MaxDepth"] = "0",
["MaxOffsetX"] = "1",
["MaxOffsetZ"] = "1",
["MaxStructureSizeX"] = "20",
["MaxStructureSizeZ"] = "20",
},
Pieces =
{
{
OriginData =
{
ExportName = "RegularRail",
Name = "Plains 247",
GalleryName = "Plains",
GalleryIndex = "247",
ID = "742",
CreatorName = "Aloe_vera",
},
Size =
{
x = 7,
y = 3,
z = 7,
},
Hitbox =
{
MinX = 0,
MinY = 0,
MinZ = 0,
MaxX = 6,
MaxY = 2,
MaxZ = 6,
},
Connectors =
{
{
Type = 1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = -1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = 1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = -1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
},
Metadata =
{
["AddWeightIfSame"] = "0",
["AllowedRotations"] = "7",
["DefaultWeight"] = "100",
["DepthWeight"] = "",
["IsStarting"] = "0",
["MergeStrategy"] = "msSpongePrint",
["MoveToGround"] = "0",
["ShouldExpandFloor"] = "0",
},
BlockDefinitions =
{
".: 0: 0", -- air
"a: 1: 0", -- stone
"b: 5: 0", -- planks
"c: 66: 6", -- tracks
"d: 66: 2", -- tracks
"e: 66: 3", -- tracks
"f: 66: 7", -- tracks
"g: 66: 5", -- tracks
"h: 50: 5", -- torch
"i: 66: 4", -- tracks
"j: 66: 9", -- tracks
"k: 66: 8", -- tracks
"l: 66: 1", -- tracks
"m: 19: 0", -- sponge
"n: 66: 0", -- tracks
},
BlockData =
{
-- Level 0
"aaab...", -- 0
"abbbbb.", -- 1
"abbb.b.", -- 2
"bbbb.bb", -- 3
".b...b.", -- 4
".bbbbb.", -- 5
"...b...", -- 6
-- Level 1
".......", -- 0
".cdbef.", -- 1
".gh..g.", -- 2
".b.h.b.", -- 3
".i...i.", -- 4
".jdbek.", -- 5
".......", -- 6
-- Level 2
".......", -- 0
"...l...", -- 1
".......", -- 2
".n...n.", -- 3
".......", -- 4
"...l...", -- 5
".......", -- 6
},
}, -- RegularRail
{
OriginData =
{
ExportName = "PowerRail",
Name = "Plains 248",
GalleryName = "Plains",
GalleryIndex = "248",
ID = "743",
CreatorName = "Aloe_vera",
},
Size =
{
x = 7,
y = 3,
z = 7,
},
Hitbox =
{
MinX = 0,
MinY = 0,
MinZ = 0,
MaxX = 6,
MaxY = 2,
MaxZ = 6,
},
Connectors =
{
{
Type = 1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = -1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = 1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = -1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
{
Type = 1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = -1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
},
Metadata =
{
["AddWeightIfSame"] = "0",
["AllowedRotations"] = "7",
["DefaultWeight"] = "100",
["DepthWeight"] = "",
["IsStarting"] = "0",
["MergeStrategy"] = "msSpongePrint",
["MoveToGround"] = "0",
["ShouldExpandFloor"] = "0",
},
BlockDefinitions =
{
".: 0: 0", -- air
"a: 1: 0", -- stone
"b: 5: 0", -- planks
"c: 27: 0", -- poweredrail
"d: 27: 2", -- poweredrail
"e: 27: 3", -- poweredrail
"f: 27: 5", -- poweredrail
"g: 50: 5", -- torch
"h: 27: 4", -- poweredrail
"i: 27: 1", -- poweredrail
"m: 19: 0", -- sponge
},
BlockData =
{
-- Level 0
"aaab...", -- 0
"abbbbb.", -- 1
"abbb.b.", -- 2
"bbbb.bb", -- 3
".b...b.", -- 4
".bbbbb.", -- 5
"...b...", -- 6
-- Level 1
".......", -- 0
".cdbec.", -- 1
".fg..f.", -- 2
".b.g.b.", -- 3
".h...h.", -- 4
".cdbec.", -- 5
".......", -- 6
-- Level 2
".......", -- 0
"...i...", -- 1
".......", -- 2
".c...c.", -- 3
".......", -- 4
"...i...", -- 5
".......", -- 6
},
}, -- PowerRail
{
OriginData =
{
ExportName = "CentralPiece",
Name = "Plains 249",
GalleryName = "Plains",
GalleryIndex = "249",
ID = "744",
CreatorName = "Aloe_vera",
},
Size =
{
x = 6,
y = 3,
z = 6,
},
Hitbox =
{
MinX = 0,
MinY = 0,
MinZ = 0,
MaxX = 5,
MaxY = 2,
MaxZ = 5,
},
Connectors =
{
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = 1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = -1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = 1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = -1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
},
Metadata =
{
["AddWeightIfSame"] = "0",
["AllowedRotations"] = "7",
["DefaultWeight"] = "100",
["DepthWeight"] = "",
["IsStarting"] = "1",
["MergeStrategy"] = "msSpongePrint",
["MoveToGround"] = "0",
["ShouldExpandFloor"] = "1",
["VerticalStrategy"] = "TerrainOrOceanTop|1",
},
BlockDefinitions =
{
".: 0: 0", -- air
"a: 1: 0", -- stone
"b: 5: 0", -- planks
"c: 66: 6", -- tracks
"d: 66: 2", -- tracks
"e: 66: 3", -- tracks
"f: 66: 7", -- tracks
"g: 66: 5", -- tracks
"h: 50: 5", -- torch
"i: 66: 4", -- tracks
"j: 66: 9", -- tracks
"k: 66: 8", -- tracks
"l: 66: 1", -- tracks
"m: 19: 0", -- sponge
"n: 66: 0", -- tracks
},
BlockData =
{
-- Level 0
"aaab..", -- 0
"abbbbb", -- 1
"abbb.b", -- 2
"bbbb.b", -- 3
".b...b", -- 4
".bbbbb", -- 5
-- Level 1
"......", -- 0
".cdbef", -- 1
".gh..g", -- 2
".b.h.b", -- 3
".i...i", -- 4
".jdbek", -- 5
-- Level 2
"......", -- 0
"...l..", -- 1
"......", -- 2
".n...n", -- 3
"......", -- 4
"...l..", -- 5
},
}, -- CentralPiece
{
OriginData =
{
ExportName = "DetectorRail",
Name = "Plains 250",
GalleryName = "Plains",
GalleryIndex = "250",
ID = "745",
CreatorName = "Aloe_vera",
},
Size =
{
x = 7,
y = 3,
z = 7,
},
Hitbox =
{
MinX = 0,
MinY = 0,
MinZ = 0,
MaxX = 6,
MaxY = 2,
MaxZ = 6,
},
Connectors =
{
{
Type = 1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = -1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
{
Type = 1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = -1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
},
Metadata =
{
["AddWeightIfSame"] = "0",
["AllowedRotations"] = "7",
["DefaultWeight"] = "100",
["DepthWeight"] = "",
["IsStarting"] = "0",
["MergeStrategy"] = "msSpongePrint",
["MoveToGround"] = "0",
["ShouldExpandFloor"] = "0",
},
BlockDefinitions =
{
".: 0: 0", -- air
"a: 1: 0", -- stone
"b: 5: 0", -- planks
"c: 28: 0", -- detectorrail
"d: 28: 2", -- detectorrail
"e: 28: 3", -- detectorrail
"f: 28: 5", -- detectorrail
"g: 50: 5", -- torch
"h: 28: 4", -- detectorrail
"i: 28: 1", -- detectorrail
"m: 19: 0", -- sponge
},
BlockData =
{
-- Level 0
"aaab...", -- 0
"abbbbb.", -- 1
"abbb.b.", -- 2
"bbbb.bb", -- 3
".b...b.", -- 4
".bbbbb.", -- 5
"...b...", -- 6
-- Level 1
".......", -- 0
".cdbec.", -- 1
".fg..f.", -- 2
".b.g.b.", -- 3
".h...h.", -- 4
".cdbec.", -- 5
".......", -- 6
-- Level 2
".......", -- 0
"...i...", -- 1
".......", -- 2
".c...c.", -- 3
".......", -- 4
"...i...", -- 5
".......", -- 6
},
}, -- DetectorRail
{
OriginData =
{
ExportName = "ActivatorRail",
Name = "Plains 251",
GalleryName = "Plains",
GalleryIndex = "251",
ID = "746",
CreatorName = "Aloe_vera",
},
Size =
{
x = 7,
y = 3,
z = 7,
},
Hitbox =
{
MinX = 0,
MinY = 0,
MinZ = 0,
MaxX = 6,
MaxY = 2,
MaxZ = 6,
},
Connectors =
{
{
Type = 1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = -1,
RelX = 6,
RelY = 1,
RelZ = 3,
Direction = 5, -- X+
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 6,
Direction = 3, -- Z+
},
{
Type = 1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = -1,
RelX = 0,
RelY = 1,
RelZ = 3,
Direction = 4, -- X-
},
{
Type = 1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
{
Type = -1,
RelX = 3,
RelY = 1,
RelZ = 0,
Direction = 2, -- Z-
},
},
Metadata =
{
["AddWeightIfSame"] = "0",
["AllowedRotations"] = "7",
["DefaultWeight"] = "100",
["DepthWeight"] = "",
["IsStarting"] = "0",
["MergeStrategy"] = "msSpongePrint",
["MoveToGround"] = "0",
["ShouldExpandFloor"] = "0",
},
BlockDefinitions =
{
".: 0: 0", -- air
"a: 1: 0", -- stone
"b: 5: 0", -- planks
"c:157: 0", -- activatorrail
"d:157: 2", -- activatorrail
"e:157: 3", -- activatorrail
"f:157: 5", -- activatorrail
"g: 50: 5", -- torch
"h:157: 4", -- activatorrail
"i:157: 1", -- activatorrail
"m: 19: 0", -- sponge
},
BlockData =
{
-- Level 0
"aaab...", -- 0
"abbbbb.", -- 1
"abbb.b.", -- 2
"bbbb.bb", -- 3
".b...b.", -- 4
".bbbbb.", -- 5
"...b...", -- 6
-- Level 1
".......", -- 0
".cdbec.", -- 1
".fg..f.", -- 2
".b.g.b.", -- 3
".h...h.", -- 4
".cdbec.", -- 5
".......", -- 6
-- Level 2
".......", -- 0
"...i...", -- 1
".......", -- 2
".c...c.", -- 3
".......", -- 4
"...i...", -- 5
".......", -- 6
},
}, -- ActivatorRail
}, -- Pieces
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ Cubeset =
Metadata =
{
CubesetFormatVersion = 1,
ExportDate = "2015-06-20 10:17:14",
ExportDate = "2015-10-10 20:20:51",
["AllowedBiomes"] = "Desert, DesertM",
["IntendedUse"] = "Village",
},
@ -672,7 +672,7 @@ Cubeset =
"aaaabfffb", -- 0
"agggffffm", -- 1
"agggbeheb", -- 2
"agggehhhe", -- 3
"agddehhhe", -- 3
"beeebhhhe", -- 4
"ehhhhhhhe", -- 5
"ehhhhhhhe", -- 6
@ -3105,14 +3105,15 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "1",
["DepthWeight"] = "",
["VerticalStrategy"] = "TerrainOrOceanTop|-16",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{

View File

@ -14,7 +14,7 @@ Cubeset =
Metadata =
{
CubesetFormatVersion = 1,
ExportDate = "2015-06-20 10:17:02",
ExportDate = "2015-10-10 20:20:57",
["AllowedBiomes"] = "Plains, Savanna, SavannaM, SunflowerPlains",
["IntendedUse"] = "Village",
},
@ -690,20 +690,20 @@ Cubeset =
-- Level 1
"mmmmmmmmmccmmmmm", -- 0
"ccbbbbbbbbbbcccm", -- 1
"ccbbbbbbbbbbcccm", -- 2
"ccbbbbbbbbbbcccm", -- 3
"ccbbbbbbbbbbcccm", -- 4
"ccbbbbbbbbbbcccm", -- 5
"ccbbbbbbbbbbcccm", -- 6
"ccbbbbbbbbbbcccm", -- 7
"ccbbbbbbbbbbcccm", -- 8
"ccbbbbbbbbbbcccm", -- 9
"cccccccccccccccm", -- 10
"cccccccccccccccm", -- 11
"cccccccccccccccm", -- 12
"cccccccccccccacm", -- 13
"cccccccccccccccm", -- 14
"aabbbbbbbbbbaacm", -- 1
"acbbbbbbbbbbccam", -- 2
"acbbbbbbbbbbcaam", -- 3
"acbbbbbbbbbbccam", -- 4
"acbbbbbbbbbbaacm", -- 5
"acbbbbbbbbbbcaam", -- 6
"acbbbbbbbbbbccam", -- 7
"acbbbbbbbbbbccam", -- 8
"acbbbbbbbbbbcaam", -- 9
"acccccccccccccam", -- 10
"aaaaaccaacccacam", -- 11
"acacaccacaccccam", -- 12
"accaaccaccaccaam", -- 13
"cccaccacaccacaam", -- 14
"mmmmmmmmmmmmmmmm", -- 15
-- Level 2
@ -1015,14 +1015,15 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "1",
["DepthWeight"] = "",
["VerticalStrategy"] = "TerrainOrOceanTop|-1",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{
@ -1716,20 +1717,20 @@ Cubeset =
"aaaaaaaaaaaaa", -- 14
-- Level 1
"bbbbbbbbbbbbb", -- 0
"bbbbbbbbbbbbb", -- 1
"bbbaccdabbbbb", -- 2
"bbbedddebbbbb", -- 3
"bbbedddebbbbb", -- 4
"bbbedddebbbbb", -- 5
"bbbacccabbbbb", -- 6
"bbbbbbbbbbbbb", -- 7
"bbbbbbbbbbbbb", -- 8
"bbbbbbbbbbbbb", -- 9
"bbbbbbbbbbabb", -- 10
"bbbbbbbbbbbbb", -- 11
"bbbbbbbbbbbbb", -- 12
"bbbbbbbbbbbbb", -- 13
"aaaabbbaaaaaa", -- 0
"abbbbbbbbbbba", -- 1
"abbaccdabbaba", -- 2
"abbedddebbaba", -- 3
"abbedddebbbba", -- 4
"aabedddebbaba", -- 5
"abbacccabbbbb", -- 6
"abbbbbbbbbaba", -- 7
"aaabbbbbbbbba", -- 8
"ababbbbabbbba", -- 9
"aababbabbbaba", -- 10
"ababbbbabbbba", -- 11
"ababbbbbbbbba", -- 12
"abbbbbbbbbbba", -- 13
"bbbbbbbbbbbbb", -- 14
-- Level 2
@ -2542,14 +2543,15 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "1",
["DepthWeight"] = "",
["VerticalStrategy"] = "TerrainOrOceanTop|-9",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{
@ -2758,62 +2760,63 @@ Cubeset =
{
".: 0: 0", -- air
"a: 2: 0", -- grass
"b: 13: 0", -- gravel
"c:113: 0", -- netherbrickfence
"d: 50: 5", -- torch
"e: 44: 8", -- step
"f: 44: 0", -- step
"g: 43: 0", -- doublestep
"b: 3: 0", -- dirt
"c: 13: 0", -- gravel
"d:113: 0", -- netherbrickfence
"e: 50: 5", -- torch
"f: 44: 8", -- step
"g: 44: 0", -- step
"h: 43: 0", -- doublestep
"m: 19: 0", -- sponge
},
BlockData =
{
-- Level 0
"aaaabbbaaaa", -- 0
"aaaabbbaaaa", -- 1
"aaaabbbaaaa", -- 2
"aaaabbbaaaa", -- 3
"aaaabbbaaaa", -- 4
"aabacccaaaa", -- 0
"aabacccabaa", -- 1
"aabacccaaaa", -- 2
"aaaacccaaaa", -- 3
"aaaacccaaaa", -- 4
-- Level 1
"..c.....c..", -- 0
"..c.....c..", -- 1
"..c.....c..", -- 2
"..c.....c..", -- 3
"..c.....c..", -- 4
"..d.....d..", -- 0
"..d.....d..", -- 1
"..d.....d..", -- 2
"..d.....d..", -- 3
"..d.....d..", -- 4
-- Level 2
"..c.....c..", -- 0
"...........", -- 1
"..c.....c..", -- 2
"...........", -- 3
"..c.....c..", -- 4
-- Level 3
"..d.....d..", -- 0
"...........", -- 1
"..c.....c..", -- 2
"..d.....d..", -- 2
"...........", -- 3
"..d.....d..", -- 4
-- Level 4
"...eeeee...", -- 0
-- Level 3
"..e.....e..", -- 0
"...........", -- 1
"..c.....c..", -- 2
"..d.....d..", -- 2
"...........", -- 3
"...eeeee...", -- 4
"..e.....e..", -- 4
-- Level 4
"...fffff...", -- 0
"...........", -- 1
"..d.....d..", -- 2
"...........", -- 3
"...fffff...", -- 4
-- Level 5
"..f.....f..", -- 0
".egfffffge.", -- 1
".egeeeeege.", -- 2
".egfffffge.", -- 3
"..f.....f..", -- 4
"..g.....g..", -- 0
".fhggggghf.", -- 1
".fhfffffhf.", -- 2
".fhggggghf.", -- 3
"..g.....g..", -- 4
-- Level 6
"...........", -- 0
"...........", -- 1
"gf.......fg", -- 2
"hg.......gh", -- 2
"...........", -- 3
"...........", -- 4
@ -3034,11 +3037,11 @@ Cubeset =
-- Level 1
"bbbbbbb", -- 0
"bbbbbbb", -- 1
"bbbbbbb", -- 2
"bbbabbb", -- 3
"bbbbbbb", -- 4
"bbbbbbb", -- 5
"bbabbbb", -- 1
"bbabaab", -- 2
"bbbaabb", -- 3
"bbabaab", -- 4
"bbababb", -- 5
"bbbbbbb", -- 6
-- Level 2
@ -3168,8 +3171,8 @@ Cubeset =
{
".: 0: 0", -- air
"a: 3: 0", -- dirt
"b: 8: 0", -- water
"c: 2: 0", -- grass
"b: 2: 0", -- grass
"c: 8: 0", -- water
"d: 17: 1", -- tree
"e: 13: 0", -- gravel
"f: 31: 2", -- tallgrass
@ -3187,10 +3190,10 @@ Cubeset =
"aaaaaaaaaaaaaaaa", -- 3
"aaaaaaaaaaaaaaaa", -- 4
"aaaaaaaaaaaaaaaa", -- 5
"aaaaaaaaaaaaaaaa", -- 6
"aaaaaaaaaaaaaaaa", -- 7
"aaaaaaaaaaaaaaaa", -- 8
"aaaaaaaaaaaaaaaa", -- 9
"aaaaabaaaaaaaaaa", -- 6
"aaabbaaaaaaaaaaa", -- 7
"aaabbaaaaaaaaaaa", -- 8
"aaaabaaaaaaaaaaa", -- 9
"aaaaaaaaaaaaaaaa", -- 10
"aaaaaaaaaaaaaaaa", -- 11
"aaaaaaaaaaaaaaaa", -- 12
@ -3204,12 +3207,12 @@ Cubeset =
"aaaaaaaaaaaaaaaa", -- 2
"aaaaaaaaaaaaaaaa", -- 3
"aaaaaaaaaaaaaaaa", -- 4
"aaaaaaaaaaaaaaaa", -- 5
"aaaabbaaaaaaaaaa", -- 6
"aaabbbaaaaaaaaaa", -- 7
"aaabbaaaaaaaaaaa", -- 8
"aaaabaaaaaaaaaaa", -- 9
"aaaaaaaaaaaaaaaa", -- 10
"aaabbbbaaaaaaaaa", -- 5
"aaaaccbaaaaaaaaa", -- 6
"aabcccbaaaaaaaaa", -- 7
"aabccabaaaaaaaaa", -- 8
"aabbcbaaaaaaaaaa", -- 9
"aaaabaaaaaaaaaaa", -- 10
"aaaaaaaaaaaaaaaa", -- 11
"aaaaaaaaaaaaaaaa", -- 12
"aaaaaaaaaaaaaaaa", -- 13
@ -3217,22 +3220,22 @@ Cubeset =
"aaaaaaaaaaaaaaaa", -- 15
-- Level 2
"cccccccccccccccc", -- 0
"ccdccccccccdcccc", -- 1
"cccccceecccccdcc", -- 2
"ccccccceeccccccc", -- 3
"cccccccceccccccc", -- 4
"cccbbbbceccccccc", -- 5
"cccbbbbceecccccc", -- 6
"ccbbbbbcceeeeccc", -- 7
"ccbbbbbccccceecc", -- 8
"ccbbbbcccccccecc", -- 9
"ccccbcccccccceec", -- 10
"ccccccccccccccec", -- 11
"ccccccccaaacccec", -- 12
"cccccccccaccccec", -- 13
"ccccccccccccceec", -- 14
"cccccccccccceecc", -- 15
"bbbbbbabbbbbbbbb", -- 0
"bbdbbbbbbbbdbbbb", -- 1
"abbbbbeebbbabdbb", -- 2
"bbbbbbbeebbbbbbb", -- 3
"bbbbbbbbebbabbbb", -- 4
"bbbccccbebbbbbab", -- 5
"bbbccccbeebbbaab", -- 6
"bbcccccbbeeeebba", -- 7
"bbcccccbbbbbeebb", -- 8
"bbccccbbababbebb", -- 9
"bbbbcbbaabbbbeeb", -- 10
"bbbbbbbbbbbbabeb", -- 11
"bbbbbbbbaaabbbeb", -- 12
"bbbbbbbbbabbbbeb", -- 13
"bbbbabbbbbbbbeeb", -- 14
"bbbbbbbbbbbbeebb", -- 15
-- Level 3
"......f...gg.g..", -- 0
@ -3327,12 +3330,13 @@ Cubeset =
"a: 3: 0", -- dirt
"b: 60: 7", -- tilleddirt
"c: 8: 0", -- water
"d: 43: 0", -- doublestep
"e: 44: 0", -- step
"f: 59: 7", -- crops
"g: 83: 0", -- reedblock
"h:113: 0", -- netherbrickfence
"i: 50: 5", -- torch
"d: 60: 6", -- tilleddirt
"e: 43: 0", -- doublestep
"f: 44: 0", -- step
"g: 59: 7", -- crops
"h: 83: 0", -- reedblock
"i:113: 0", -- netherbrickfence
"j: 50: 5", -- torch
"m: 19: 0", -- sponge
},
BlockData =
@ -3361,7 +3365,7 @@ Cubeset =
"mabbbbbbbam", -- 5
"mabcccccaam", -- 6
"mabbbbbbbam", -- 7
"mabbbbbbbam", -- 8
"madbbbbbbam", -- 8
"mabbbbbbbam", -- 9
"mabbbbbbbam", -- 10
"maaaaaaaaam", -- 11
@ -3369,52 +3373,52 @@ Cubeset =
-- Level 2
"...........", -- 0
".deeeeeeed.", -- 1
".efffffffe.", -- 2
".efffffffe.", -- 3
".efffffffe.", -- 4
".efgggggfe.", -- 5
".eg.....ge.", -- 6
".efgggggfe.", -- 7
".efffffffe.", -- 8
".efffffffe.", -- 9
".efffffffe.", -- 10
".deeeeeeed.", -- 11
".efffffffe.", -- 1
".fgggggggf.", -- 2
".fgggggggf.", -- 3
".fgggggggf.", -- 4
".fghhhhhgf.", -- 5
".fh.....hf.", -- 6
".fghhhhhgf.", -- 7
".fgggggggf.", -- 8
".fgggggggf.", -- 9
".fgggggggf.", -- 10
".efffffffe.", -- 11
"...........", -- 12
-- Level 3
"...........", -- 0
".h.......h.", -- 1
".i.......i.", -- 1
"...........", -- 2
"...........", -- 3
"...........", -- 4
"...ggggg...", -- 5
"..g.....g..", -- 6
"...ggggg...", -- 7
"...hhhhh...", -- 5
"..h.....h..", -- 6
"...hhhhh...", -- 7
"...........", -- 8
"...........", -- 9
"...........", -- 10
".h.......h.", -- 11
".i.......i.", -- 11
"...........", -- 12
-- Level 4
"...........", -- 0
".h.......h.", -- 1
".i.......i.", -- 1
"...........", -- 2
"...........", -- 3
"...........", -- 4
"...ggggg...", -- 5
"..g.....g..", -- 6
"...ggggg...", -- 7
"...hhhhh...", -- 5
"..h.....h..", -- 6
"...hhhhh...", -- 7
"...........", -- 8
"...........", -- 9
"...........", -- 10
".h.......h.", -- 11
".i.......i.", -- 11
"...........", -- 12
-- Level 5
"...........", -- 0
".h.......h.", -- 1
".i.......i.", -- 1
"...........", -- 2
"...........", -- 3
"...........", -- 4
@ -3424,27 +3428,12 @@ Cubeset =
"...........", -- 8
"...........", -- 9
"...........", -- 10
".h.......h.", -- 11
".i.......i.", -- 11
"...........", -- 12
-- Level 6
".h.......h.", -- 0
"hhh.....hhh", -- 1
".h.......h.", -- 2
"...........", -- 3
"...........", -- 4
"...........", -- 5
"...........", -- 6
"...........", -- 7
"...........", -- 8
"...........", -- 9
".h.......h.", -- 10
"hhh.....hhh", -- 11
".h.......h.", -- 12
-- Level 7
".i.......i.", -- 0
"i.i.....i.i", -- 1
"iii.....iii", -- 1
".i.......i.", -- 2
"...........", -- 3
"...........", -- 4
@ -3454,9 +3443,24 @@ Cubeset =
"...........", -- 8
"...........", -- 9
".i.......i.", -- 10
"i.i.....i.i", -- 11
"iii.....iii", -- 11
".i.......i.", -- 12
-- Level 7
".j.......j.", -- 0
"j.j.....j.j", -- 1
".j.......j.", -- 2
"...........", -- 3
"...........", -- 4
"...........", -- 5
"...........", -- 6
"...........", -- 7
"...........", -- 8
"...........", -- 9
".j.......j.", -- 10
"j.j.....j.j", -- 11
".j.......j.", -- 12
},
}, -- Farm
}, -- Pieces

View File

@ -14,7 +14,7 @@ Cubeset =
Metadata =
{
CubesetFormatVersion = 1,
ExportDate = "2015-10-05 21:08:55",
ExportDate = "2015-10-10 20:21:06",
["AllowedBiomes"] = "Plains, Savanna, SavannaM, SunflowerPlains",
["IntendedUse"] = "Village",
},
@ -74,7 +74,7 @@ Cubeset =
"b: 67: 0", -- stairs
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 5: 0", -- wood
"e: 5: 0", -- planks
"f: 67: 3", -- stairs
"g: 17: 0", -- tree
"h: 64: 3", -- wooddoorblock
@ -304,14 +304,15 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "1",
["DepthWeight"] = "",
["VerticalStrategy"] = "TerrainOrOceanTop|-9",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{
@ -464,9 +465,9 @@ Cubeset =
"f: 60: 5", -- tilleddirt
"g: 60: 2", -- tilleddirt
"h: 60: 6", -- tilleddirt
"i: 60: 0", -- tilleddirt
"j: 60: 4", -- tilleddirt
"k: 60: 3", -- tilleddirt
"i: 60: 4", -- tilleddirt
"j: 60: 3", -- tilleddirt
"k: 60: 0", -- tilleddirt
"l: 50: 5", -- torch
"m: 19: 0", -- sponge
"n: 59: 7", -- crops
@ -497,13 +498,13 @@ Cubeset =
-- Level 2
"ccccccc.ccccccc", -- 0
"cddeddc.cffegfc", -- 1
"cddeddc.cfdegfc", -- 1
"cddeddc.chdeddc", -- 2
"cddeddc.cfheijc", -- 3
"cddeddc.ckhehdc", -- 4
"cddeddc.cdjedhc", -- 5
"cddeddc.cfhekdc", -- 6
"cddeddc.cdjefic", -- 7
"cddeddc.cdhedic", -- 3
"cddeddc.cjhehdc", -- 4
"cddeddc.cddeddc", -- 5
"cddeddc.cfheddc", -- 6
"cddeddc.cdiefkc", -- 7
"ccccccc.ccccccc", -- 8
-- Level 3
@ -617,10 +618,10 @@ Cubeset =
".: 0: 0", -- air
"a: 4: 0", -- cobblestone
"b: 3: 0", -- dirt
"c: 5: 0", -- wood
"c: 5: 0", -- planks
"d: 2: 0", -- grass
"e: 67: 2", -- stairs
"f: 43: 0", -- doubleslab
"f: 43: 0", -- doublestep
"g: 67: 0", -- stairs
"h: 67: 3", -- stairs
"i: 17: 0", -- tree
@ -932,7 +933,7 @@ Cubeset =
"s: 50: 1", -- torch
"t: 50: 2", -- torch
"u: 53: 6", -- woodstairs
"v: 5: 0", -- wood
"v: 5: 0", -- planks
},
BlockData =
{
@ -1054,7 +1055,7 @@ Cubeset =
{
".: 0: 0", -- air
"a: 3: 0", -- dirt
"b: 5: 0", -- wood
"b: 5: 0", -- planks
"c: 13: 0", -- gravel
"d: 17: 0", -- tree
"e: 60: 7", -- tilleddirt
@ -1234,7 +1235,7 @@ Cubeset =
{
".: 0: 0", -- air
"a: 3: 0", -- dirt
"b: 43: 0", -- doubleslab
"b: 43: 0", -- doublestep
"c:139: 0", -- cobblestonewall
"d: 50: 4", -- torch
"e: 50: 2", -- torch
@ -1339,7 +1340,7 @@ Cubeset =
"d: 67: 1", -- stairs
"e: 67: 3", -- stairs
"f: 17: 0", -- tree
"g: 5: 0", -- wood
"g: 5: 0", -- planks
"h: 64: 7", -- wooddoorblock
"i: 64: 1", -- wooddoorblock
"j:102: 0", -- glasspane
@ -1506,9 +1507,9 @@ Cubeset =
"b: 67: 0", -- stairs
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 43: 0", -- doubleslab
"e: 43: 0", -- doublestep
"f: 17: 0", -- tree
"g: 5: 0", -- wood
"g: 5: 0", -- planks
"h: 64: 3", -- wooddoorblock
"i: 96: 8", -- trapdoor
"j: 61: 2", -- furnace
@ -1752,7 +1753,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 3", -- wooddoorblock
"h:102: 0", -- glasspane
"i: 64: 9", -- wooddoorblock
@ -1887,7 +1888,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 3", -- wooddoorblock
"h:102: 0", -- glasspane
"i: 64: 9", -- wooddoorblock
@ -2022,7 +2023,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 3", -- wooddoorblock
"h:102: 0", -- glasspane
"i: 64: 9", -- wooddoorblock
@ -2192,7 +2193,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 3", -- wooddoorblock
"h:102: 0", -- glasspane
"i: 64: 9", -- wooddoorblock
@ -2360,7 +2361,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 3", -- wooddoorblock
"h: 53: 3", -- woodstairs
"i: 85: 0", -- fence
@ -2502,7 +2503,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 3", -- wooddoorblock
"h: 53: 3", -- woodstairs
"i: 85: 0", -- fence
@ -2671,9 +2672,9 @@ Cubeset =
"d: 67: 0", -- stairs
"e: 67: 2", -- stairs
"f: 67: 1", -- stairs
"g: 43: 0", -- doubleslab
"g: 43: 0", -- doublestep
"h: 17: 0", -- tree
"i: 5: 0", -- wood
"i: 5: 0", -- planks
"j: 64: 3", -- wooddoorblock
"k: 53: 3", -- woodstairs
"l: 85: 0", -- fence
@ -2869,7 +2870,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 3", -- wooddoorblock
"h: 64: 9", -- wooddoorblock
"i:102: 0", -- glasspane
@ -3004,7 +3005,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 0", -- wooddoorblock
"h: 10: 0", -- lava
"i: 54: 2", -- chest
@ -3020,7 +3021,7 @@ Cubeset =
"s: 50: 1", -- torch
"t: 53: 6", -- woodstairs
"u: 53: 3", -- woodstairs
"v: 43: 0", -- doubleslab
"v: 43: 0", -- doublestep
"w: 44: 0", -- step
},
BlockData =
@ -3201,7 +3202,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 3", -- wooddoorblock
"h:102: 0", -- glasspane
"i: 64: 9", -- wooddoorblock
@ -3363,7 +3364,7 @@ Cubeset =
"d: 67: 2", -- stairs
"e: 67: 1", -- stairs
"f: 17: 0", -- tree
"g: 5: 0", -- wood
"g: 5: 0", -- planks
"h:170: 4", -- haybale
"i:170: 8", -- haybale
"j: 54: 2", -- chest
@ -3515,7 +3516,7 @@ Cubeset =
"f: 17: 0", -- tree
"g:107: 0", -- fencegate
"h:107: 4", -- fencegate
"i: 5: 0", -- wood
"i: 5: 0", -- planks
"j:107: 6", -- fencegate
"k: 85: 0", -- fence
"l:170: 0", -- haybale
@ -3691,7 +3692,7 @@ Cubeset =
"c: 67: 2", -- stairs
"d: 67: 1", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 64: 1", -- wooddoorblock
"h: 65: 3", -- ladder
"i: 53: 3", -- woodstairs
@ -3999,7 +4000,7 @@ Cubeset =
"c: 67: 1", -- stairs
"d: 67: 3", -- stairs
"e: 17: 0", -- tree
"f: 5: 0", -- wood
"f: 5: 0", -- planks
"g: 54: 4", -- chest
"h:154: 4", -- hopper
"i: 64: 0", -- wooddoorblock
@ -4336,14 +4337,15 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "1",
["DepthWeight"] = "",
["VerticalStrategy"] = "TerrainOrOceanTop|-9",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{
@ -4358,7 +4360,7 @@ Cubeset =
"h: 85: 0", -- fence
"i: 53: 2", -- woodstairs
"j: 53: 7", -- woodstairs
"k: 5: 0", -- wood
"k: 5: 0", -- planks
"l: 53: 4", -- woodstairs
"m: 19: 0", -- sponge
"n: 53: 5", -- woodstairs
@ -4572,19 +4574,20 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["MoveToGround"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["VerticalStrategy"] = "TerrainOrOceanTop|-32",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "0",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 77: 2", -- stonebutton
"c: 66: 6", -- tracks
"d: 27: 1", -- poweredrail
@ -5013,7 +5016,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 85: 0", -- fence
"c: 66: 1", -- tracks
"d: 50: 2", -- torch
@ -5101,7 +5104,7 @@ Cubeset =
"c:126: 4", -- woodenslab
"d: 86: 1", -- pumpkin
"e:139: 1", -- cobblestonewall
"f:163: 4", -- acaciawoodenstairs
"f:163: 4", -- acaciawoodstairs
"m: 19: 0", -- sponge
},
BlockData =
@ -5239,7 +5242,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 66: 0", -- tracks
"c: 66: 1", -- tracks
"m: 19: 0", -- sponge
@ -5433,7 +5436,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 66: 0", -- tracks
"c: 66: 1", -- tracks
"m: 19: 0", -- sponge
@ -5599,7 +5602,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 66: 0", -- tracks
"c: 85: 0", -- fence
"d: 66: 1", -- tracks
@ -5752,7 +5755,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 66: 0", -- tracks
"c: 85: 0", -- fence
"d: 66: 1", -- tracks
@ -5875,7 +5878,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 66: 1", -- tracks
"c: 66: 2", -- tracks
"d: 85: 0", -- fence
@ -5999,7 +6002,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 85: 0", -- fence
"c: 66: 4", -- tracks
"d: 66: 0", -- tracks
@ -6229,7 +6232,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 66: 0", -- tracks
"c: 66: 5", -- tracks
"d: 85: 0", -- fence
@ -6484,7 +6487,7 @@ Cubeset =
BlockDefinitions =
{
".: 0: 0", -- air
"a: 5: 0", -- wood
"a: 5: 0", -- planks
"b: 85: 0", -- fence
"c: 66: 1", -- tracks
"d: 50: 2", -- torch

View File

@ -14,7 +14,7 @@ Cubeset =
Metadata =
{
CubesetFormatVersion = 1,
ExportDate = "2015-06-20 10:17:05",
ExportDate = "2015-10-10 20:21:16",
["AllowedBiomes"] = "Desert, DesertM",
["IntendedUse"] = "Village",
},
@ -1417,14 +1417,15 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "1",
["DepthWeight"] = "",
["VerticalStrategy"] = "TerrainOrOceanTop|-11",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{

View File

@ -14,7 +14,7 @@ Cubeset =
Metadata =
{
CubesetFormatVersion = 1,
ExportDate = "2015-06-20 10:16:49",
ExportDate = "2015-10-10 20:21:27",
["AllowedBiomes"] = "Desert, DesertM",
["IntendedUse"] = "Village",
},
@ -79,14 +79,15 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "1",
["DepthWeight"] = "",
["VerticalStrategy"] = "TerrainOrOceanTop|-8",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{
@ -348,8 +349,10 @@ Cubeset =
"a: 24: 0", -- sandstone
"b: 60: 7", -- tilleddirt
"c: 8: 0", -- water
"d: 50: 5", -- torch
"e: 59: 7", -- crops
"d: 60: 5", -- tilleddirt
"e: 60: 6", -- tilleddirt
"f: 50: 5", -- torch
"g: 59: 7", -- crops
"m: 19: 0", -- sponge
},
BlockData =
@ -370,22 +373,22 @@ Cubeset =
"abbcbbabbcbba", -- 1
"abbcbbabbcbba", -- 2
"abbcbbabbcbba", -- 3
"abbcbbabbcbba", -- 4
"abbcdbabbcbba", -- 4
"abbcbbabbcbba", -- 5
"abbcbbabbcbba", -- 6
"abbceeabbcbba", -- 6
"abbcbbabbcbba", -- 7
"aaaaaaaaaaaaa", -- 8
-- Level 2
"d.....d.....d", -- 0
".ee.ee.ee.ee.", -- 1
".ee.ee.ee.ee.", -- 2
".ee.ee.ee.ee.", -- 3
".ee.ee.ee.ee.", -- 4
".ee.ee.ee.ee.", -- 5
".ee.ee.ee.ee.", -- 6
".ee.ee.ee.ee.", -- 7
"d.....d.....d", -- 8
"f.....f.....f", -- 0
".gg.gg.gg.gg.", -- 1
".gg.gg.gg.gg.", -- 2
".gg.gg.gg.gg.", -- 3
".gg.gg.gg.gg.", -- 4
".gg.gg.gg.gg.", -- 5
".gg.gg.gg.gg.", -- 6
".gg.gg.gg.gg.", -- 7
"f.....f.....f", -- 8
},
}, -- DoubleField
@ -2223,14 +2226,15 @@ Cubeset =
},
Metadata =
{
["DefaultWeight"] = "100",
["AddWeightIfSame"] = "0",
["IsStarting"] = "1",
["AllowedRotations"] = "7",
["MergeStrategy"] = "msSpongePrint",
["IsStarting"] = "1",
["DepthWeight"] = "",
["ShouldExpandFloor"] = "1",
["DepthWeight"] = "",
["VerticalStrategy"] = "TerrainOrOceanTop|-8",
["MoveToGround"] = "1",
["AddWeightIfSame"] = "0",
["DefaultWeight"] = "100",
},
BlockDefinitions =
{

View File

@ -286,7 +286,7 @@ void cLuaState::AddPackagePath(const AString & a_PathVariable, const AString & a
bool cLuaState::LoadFile(const AString & a_FileName, bool a_LogWarnings)
{
ASSERT(IsValid());
// Load the file:
int s = luaL_loadfile(m_LuaState, a_FileName.c_str());
if (s != 0)
@ -310,7 +310,42 @@ bool cLuaState::LoadFile(const AString & a_FileName, bool a_LogWarnings)
lua_pop(m_LuaState, 1);
return false;
}
return true;
}
bool cLuaState::LoadString(const AString & a_StringToLoad, const AString & a_FileName, bool a_LogWarnings)
{
ASSERT(IsValid());
// Load the file:
int s = luaL_loadstring(m_LuaState, a_StringToLoad.c_str());
if (s != 0)
{
if (a_LogWarnings)
{
LOGWARNING("Can't load %s because of a load error in string from \"%s\": %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1));
}
lua_pop(m_LuaState, 1);
return false;
}
// Execute the globals:
s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
if (s != 0)
{
if (a_LogWarnings)
{
LOGWARNING("Can't load %s because of an initialization error in string from \"%s\": %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1));
}
lua_pop(m_LuaState, 1);
return false;
}
return true;
}
@ -952,6 +987,11 @@ cLuaState::cStackValue cLuaState::WalkToValue(const AString & a_Name)
// Remove the previous value from the stack (keep only the new one):
lua_remove(m_LuaState, -2);
} // for elem - path[]
if (lua_isnil(m_LuaState, -1))
{
lua_pop(m_LuaState, 1);
return cStackValue();
}
return cStackValue(*this);
}
@ -959,6 +999,38 @@ cLuaState::cStackValue cLuaState::WalkToValue(const AString & a_Name)
cLuaState::cStackValue cLuaState::WalkToNamedGlobal(const AString & a_Name)
{
// Iterate over path and replace the top of the stack with the walked element
lua_getglobal(m_LuaState, "_G");
auto path = StringSplit(a_Name, ".");
for (const auto & elem: path)
{
// If the value is not a table, bail out (error):
if (!lua_istable(m_LuaState, -1))
{
lua_pop(m_LuaState, 1);
return cStackValue();
}
// Get the next part of the path:
lua_getfield(m_LuaState, -1, elem.c_str());
// Remove the previous value from the stack (keep only the new one):
lua_remove(m_LuaState, -2);
} // for elem - path[]
if (lua_isnil(m_LuaState, -1))
{
lua_pop(m_LuaState, 1);
return cStackValue();
}
return std::move(cStackValue(*this));
}
bool cLuaState::CallFunction(int a_NumResults)
{
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first

View File

@ -207,24 +207,30 @@ public:
/** Detaches a previously attached state. */
void Detach(void);
/** Returns true if the m_LuaState is valid */
bool IsValid(void) const { return (m_LuaState != nullptr); }
/** Returns the name of the subsystem, as specified when the instance was created. */
AString GetSubsystemName(void) const { return m_SubsystemName; }
/** Adds the specified path to package.<a_PathVariable> */
void AddPackagePath(const AString & a_PathVariable, const AString & a_Path);
/** Loads the specified file
Returns false and optionally logs a warning to the console if not successful (but the LuaState is kept open).
m_SubsystemName is displayed in the warning log message. */
bool LoadFile(const AString & a_FileName, bool a_LogWarnings = true);
/** Loads the specified string.
Returns false and optionally logs a warning to the console if not successful (but the LuaState is kept open).
a_FileName is the original filename from where the string was read, and is used only for logging. It may be empty.
m_SubsystemName is displayed in the warning log message. */
bool LoadString(const AString & a_StringToLoad, const AString & a_FileName, bool a_LogWarnings = true);
/** Returns true if a_FunctionName is a valid Lua function that can be called */
bool HasFunction(const char * a_FunctionName);
void PushNil(void);
// Push a const value onto the stack (keep alpha-sorted):
@ -291,11 +297,17 @@ public:
}
/** Pushes the named value in the table at the top of the stack.
a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue".
a_Name may be a path containing multiple table levels, such as "cChatColor.Blue".
If the value is found, it is pushed on top of the stack and the returned cStackValue is valid.
If the value is not found, the stack is unchanged and the returned cStackValue is invalid. */
cStackValue WalkToValue(const AString & a_Name);
/** Pushes the named value in the global table to the top of the stack.
a_Name may be a path containing multiple table levels, such as "cChatColor.Blue".
If the value is found in the global table, it is pushed to the top of the stack and the returned cStackValue is valid.
If the value is not found, the stack is unchanged and the returned cStackValue is invalid. */
cStackValue WalkToNamedGlobal(const AString & a_Name);
/** Retrieves the named value in the table at the top of the Lua stack.
a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue".
Returns true if the value was successfully retrieved, false on error. */

View File

@ -9,7 +9,7 @@ include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libevent/include
set(FOLDERS
OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++ Bindings
WorldStorage Mobs Entities Simulator BlockEntities UI Generating/Prefabs
WorldStorage Mobs Entities Simulator BlockEntities UI
Noise
)
@ -146,6 +146,7 @@ SET (HDRS
SettingsRepositoryInterface.h
SpawnPrepare.h
Statistics.h
Stopwatch.h
StringCompression.h
StringUtils.h
Tracer.h
@ -364,7 +365,7 @@ endif ()
if (NOT MSVC)
target_link_libraries(${EXECUTABLE}
OSSupport HTTPServer Bindings Items Blocks Noise
Protocol Generating Generating_Prefabs WorldStorage
Protocol Generating WorldStorage
Mobs Entities Simulator BlockEntities UI PolarSSL++
)
endif ()

View File

@ -19,20 +19,19 @@ SET (SRCS
GridStructGen.cpp
HeiGen.cpp
MineShafts.cpp
NetherFortGen.cpp
Noise3DGenerator.cpp
POCPieceGenerator.cpp
PieceGenerator.cpp
PieceStructuresGen.cpp
Prefab.cpp
PrefabPiecePool.cpp
RainbowRoadsGen.cpp
PrefabStructure.cpp
Ravines.cpp
RoughRavines.cpp
StructGen.cpp
TestRailsGen.cpp
Trees.cpp
TwoHeights.cpp
UnderwaterBaseGen.cpp
VerticalLimit.cpp
VerticalStrategy.cpp
VillageGen.cpp
)
@ -53,22 +52,21 @@ SET (HDRS
HeiGen.h
IntGen.h
MineShafts.h
NetherFortGen.h
Noise3DGenerator.h
POCPieceGenerator.h
PieceGenerator.h
PieceStructuresGen.h
Prefab.h
PrefabPiecePool.h
PrefabStructure.h
ProtIntGen.h
RainbowRoadsGen.h
Ravines.h
RoughRavines.h
ShapeGen.cpp
StructGen.h
TestRailsGen.h
Trees.h
TwoHeights.h
UnderwaterBaseGen.h
VerticalLimit.h
VerticalStrategy.h
VillageGen.h
)
@ -80,16 +78,12 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set_source_files_properties(EndGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast")
set_source_files_properties(FinishGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=switch-enum -Wno-error=switch")
set_source_files_properties(HeiGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast")
set_source_files_properties(NetherFortGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=global-constructors")
set_source_files_properties(Noise3DGenerator.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast")
set_source_files_properties(PieceGenerator.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=global-constructors")
set_source_files_properties(Prefab.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=global-constructors")
set_source_files_properties(RainbowRoadsGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=global-constructors")
set_source_files_properties(Ravines.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast")
set_source_files_properties(RoughRavines.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=float-equal -Wno-error=old-style-cast")
set_source_files_properties(StructGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=switch-enum -Wno-error=switch -Wno-error=old-style-cast")
set_source_files_properties(TestRailsGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=global-constructors")
set_source_files_properties(UnderwaterBaseGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=global-constructors -Wno-error=switch-enum")
set_source_files_properties(VillageGen.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=global-constructors -Wno-error=switch-enum")
endif()

View File

@ -26,15 +26,11 @@
#include "DungeonRoomsFinisher.h"
#include "EndGen.h"
#include "MineShafts.h"
#include "NetherFortGen.h"
#include "Noise3DGenerator.h"
#include "POCPieceGenerator.h"
#include "RainbowRoadsGen.h"
#include "Ravines.h"
#include "RoughRavines.h"
#include "TestRailsGen.h"
#include "UnderwaterBaseGen.h"
#include "VillageGen.h"
#include "PieceStructuresGen.h"
@ -202,14 +198,13 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
m_BiomeGen = cBiomeGen::CreateBiomeGen(a_IniFile, m_ChunkGenerator.GetSeed(), CacheOffByDefault);
// Add a cache, if requested:
int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 64);
// The default is 16 * 128 caches, which is 2 MiB of RAM. Reasonable, for the amount of work this is saving.
int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 16);
if (CacheSize <= 0)
{
return;
}
int MultiCacheLength = a_IniFile.GetValueSetI("Generator", "BiomeGenMultiCacheLength", 4);
int MultiCacheLength = a_IniFile.GetValueSetI("Generator", "BiomeGenMultiCacheLength", 128);
if (CacheSize < 4)
{
LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
@ -221,11 +216,11 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
if (MultiCacheLength > 0)
{
LOGD("Enabling multicache for biomegen of length %d.", MultiCacheLength);
m_BiomeGen = cBiomeGenPtr(new cBioGenMulticache(m_BiomeGen, static_cast<size_t>(CacheSize), static_cast<size_t>(MultiCacheLength)));
m_BiomeGen = std::make_shared<cBioGenMulticache>(m_BiomeGen, static_cast<size_t>(CacheSize), static_cast<size_t>(MultiCacheLength));
}
else
{
m_BiomeGen = cBiomeGenPtr(new cBioGenCache(m_BiomeGen, static_cast<size_t>(CacheSize)));
m_BiomeGen = std::make_shared<cBioGenCache>(m_BiomeGen, static_cast<size_t>(CacheSize));
}
}
@ -274,8 +269,8 @@ void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile)
}
// Create a cache of the composited heightmaps, so that finishers may use it:
m_CompositedHeightCache = std::make_shared<cHeiGenMultiCache>(std::make_shared<cCompositedHeiGen>(m_BiomeGen, m_ShapeGen, m_CompositionGen), 16, 24);
// 24 subcaches of depth 16 each = 96 KiB of RAM. Acceptable, for the amount of work this saves.
m_CompositedHeightCache = std::make_shared<cHeiGenMultiCache>(std::make_shared<cCompositedHeiGen>(m_BiomeGen, m_ShapeGen, m_CompositionGen), 16, 128);
// 128 subcaches of depth 16 each = 0.5 MiB of RAM. Acceptable, for the amount of work this saves.
}
@ -286,6 +281,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
{
int Seed = m_ChunkGenerator.GetSeed();
eDimension Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld"));
auto seaLevel = a_IniFile.GetValueI("Generator", "SeaLevel");
AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "");
@ -293,18 +289,24 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
AStringVector Str = StringSplitAndTrim(Finishers, ",");
for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr)
{
auto split = StringSplitAndTrim(*itr, ":");
if (split.empty())
{
continue;
}
const auto & finisher = split[0];
// Finishers, alpha-sorted:
if (NoCaseCompare(*itr, "Animals") == 0)
if (NoCaseCompare(finisher, "Animals") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenPassiveMobs(Seed, a_IniFile, Dimension)));
}
else if (NoCaseCompare(*itr, "BottomLava") == 0)
else if (NoCaseCompare(finisher, "BottomLava") == 0)
{
int DefaultBottomLavaLevel = (Dimension == dimNether) ? 30 : 10;
int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel);
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenBottomLava(BottomLavaLevel)));
}
else if (NoCaseCompare(*itr, "DeadBushes") == 0)
else if (NoCaseCompare(finisher, "DeadBushes") == 0)
{
// A list with all the allowed biomes.
cFinishGenSingleTopBlock::BiomeList AllowedBiomes;
@ -326,11 +328,11 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSingleTopBlock(Seed, E_BLOCK_DEAD_BUSH, AllowedBiomes, 2, AllowedBlocks)));
}
else if (NoCaseCompare(*itr, "DirectOverhangs") == 0)
else if (NoCaseCompare(finisher, "DirectOverhangs") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cStructGenDirectOverhangs(Seed)));
}
else if (NoCaseCompare(*itr, "DirtPockets") == 0)
else if (NoCaseCompare(finisher, "DirtPockets") == 0)
{
auto gen = std::make_shared<cFinishGenOrePockets>(Seed + 1, cFinishGenOrePockets::DefaultNaturalPatches());
if (gen->Initialize(a_IniFile, "DirtPockets"))
@ -338,16 +340,16 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
m_FinishGens.push_back(gen);
}
}
else if (NoCaseCompare(*itr, "DistortedMembraneOverhangs") == 0)
else if (NoCaseCompare(finisher, "DistortedMembraneOverhangs") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cStructGenDistortedMembraneOverhangs(Seed)));
}
else if (NoCaseCompare(*itr, "DualRidgeCaves") == 0)
else if (NoCaseCompare(finisher, "DualRidgeCaves") == 0)
{
float Threshold = static_cast<float>(a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3));
m_FinishGens.push_back(cFinishGenPtr(new cStructGenDualRidgeCaves(Seed, Threshold)));
}
else if (NoCaseCompare(*itr, "DungeonRooms") == 0)
else if (NoCaseCompare(finisher, "DungeonRooms") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsGridSize", 48);
int MaxSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMaxSize", 7);
@ -355,41 +357,24 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
AString HeightDistrib = a_IniFile.GetValueSet ("Generator", "DungeonRoomsHeightDistrib", "0, 0; 10, 10; 11, 500; 40, 500; 60, 40; 90, 1");
m_FinishGens.push_back(cFinishGenPtr(new cDungeonRoomsFinisher(m_ShapeGen, Seed, GridSize, MaxSize, MinSize, HeightDistrib)));
}
else if (NoCaseCompare(*itr, "GlowStone") == 0)
else if (NoCaseCompare(finisher, "GlowStone") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenGlowStone(Seed)));
}
else if (NoCaseCompare(*itr, "Ice") == 0)
else if (NoCaseCompare(finisher, "Ice") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenIce));
}
else if (NoCaseCompare(*itr, "LavaLakes") == 0)
else if (NoCaseCompare(finisher, "LavaLakes") == 0)
{
int Probability = a_IniFile.GetValueSetI("Generator", "LavaLakesProbability", 10);
m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, m_ShapeGen, Probability)));
}
else if (NoCaseCompare(*itr, "LavaSprings") == 0)
else if (NoCaseCompare(finisher, "LavaSprings") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenFluidSprings(Seed, E_BLOCK_LAVA, a_IniFile, Dimension)));
}
else if (NoCaseCompare(*itr, "MarbleCaves") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cStructGenMarbleCaves(Seed)));
}
else if (NoCaseCompare(*itr, "MineShafts") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "MineShaftsGridSize", 512);
int MaxOffset = a_IniFile.GetValueSetI("Generator", "MineShaftsMaxOffset", 256);
int MaxSystemSize = a_IniFile.GetValueSetI("Generator", "MineShaftsMaxSystemSize", 160);
int ChanceCorridor = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCorridor", 600);
int ChanceCrossing = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCrossing", 200);
int ChanceStaircase = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceStaircase", 200);
m_FinishGens.push_back(cFinishGenPtr(new cStructGenMineShafts(
Seed, GridSize, MaxOffset, MaxSystemSize,
ChanceCorridor, ChanceCrossing, ChanceStaircase
)));
}
else if (NoCaseCompare(*itr, "Lilypads") == 0)
else if (NoCaseCompare(finisher, "Lilypads") == 0)
{
// A list with all the allowed biomes.
cFinishGenSingleTopBlock::BiomeList AllowedBiomes;
@ -403,30 +388,49 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSingleTopBlock(Seed, E_BLOCK_LILY_PAD, AllowedBiomes, 4, AllowedBlocks)));
}
else if (NoCaseCompare(*itr, "NaturalPatches") == 0)
else if (NoCaseCompare(finisher, "MarbleCaves") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cStructGenMarbleCaves(Seed)));
}
else if (NoCaseCompare(finisher, "MineShafts") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "MineShaftsGridSize", 512);
int MaxOffset = a_IniFile.GetValueSetI("Generator", "MineShaftsMaxOffset", 256);
int MaxSystemSize = a_IniFile.GetValueSetI("Generator", "MineShaftsMaxSystemSize", 160);
int ChanceCorridor = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCorridor", 600);
int ChanceCrossing = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCrossing", 200);
int ChanceStaircase = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceStaircase", 200);
m_FinishGens.push_back(cFinishGenPtr(new cStructGenMineShafts(
Seed, GridSize, MaxOffset, MaxSystemSize,
ChanceCorridor, ChanceCrossing, ChanceStaircase
)));
}
else if (NoCaseCompare(finisher, "NaturalPatches") == 0)
{
m_FinishGens.push_back(std::make_shared<cFinishGenOreNests>(Seed + 1, cFinishGenOreNests::DefaultNaturalPatches()));
}
else if (NoCaseCompare(*itr, "NetherClumpFoliage") == 0)
else if (NoCaseCompare(finisher, "NetherClumpFoliage") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenNetherClumpFoliage(Seed)));
}
else if (NoCaseCompare(*itr, "NetherForts") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "NetherFortsGridSize", 512);
int MaxOffset = a_IniFile.GetValueSetI("Generator", "NetherFortsMaxOffset", 128);
int MaxDepth = a_IniFile.GetValueSetI("Generator", "NetherFortsMaxDepth", 12);
m_FinishGens.push_back(cFinishGenPtr(new cNetherFortGen(Seed, GridSize, MaxOffset, MaxDepth)));
LOGINFO("The NetherForts finisher is obsolete, you should use \"PieceStructures: NetherForts\" instead.");
auto gen = std::make_shared<cPieceStructuresGen>(Seed);
if (gen->Initialize("NetherForts", seaLevel, m_BiomeGen, m_CompositedHeightCache))
{
m_FinishGens.push_back(gen);
}
}
else if (NoCaseCompare(*itr, "NetherOreNests") == 0)
else if (NoCaseCompare(finisher, "NetherOreNests") == 0)
{
m_FinishGens.push_back(std::make_shared<cFinishGenOreNests>(Seed + 2, cFinishGenOreNests::DefaultNetherOres()));
}
else if (NoCaseCompare(*itr, "OreNests") == 0)
else if (NoCaseCompare(finisher, "OreNests") == 0)
{
m_FinishGens.push_back(std::make_shared<cFinishGenOreNests>(Seed + 3, cFinishGenOreNests::DefaultOverworldOres()));
}
else if (NoCaseCompare(*itr, "OrePockets") == 0)
else if (NoCaseCompare(finisher, "OrePockets") == 0)
{
auto gen = std::make_shared<cFinishGenOrePockets>(Seed + 2, cFinishGenOrePockets::DefaultOverworldOres());
if (gen->Initialize(a_IniFile, "OrePockets"))
@ -434,11 +438,21 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
m_FinishGens.push_back(gen);
}
}
else if (NoCaseCompare(*itr, "POCPieces") == 0)
else if (NoCaseCompare(finisher, "POCPieces") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cPOCPieceGenerator(Seed)));
if (split.size() < 2)
{
LOGWARNING("The PieceStructures generator needs the structures to use. Example: \"PieceStructures: NetherForts\".");
continue;
}
auto gen = std::make_shared<cPieceStructuresGen>(Seed);
if (gen->Initialize(split[1], seaLevel, m_BiomeGen, m_CompositedHeightCache))
{
m_FinishGens.push_back(gen);
}
}
else if (NoCaseCompare(*itr, "PreSimulator") == 0)
else if (NoCaseCompare(finisher, "PreSimulator") == 0)
{
// Load the settings
bool PreSimulateFallingBlocks = a_IniFile.GetValueSetB("Generator", "PreSimulatorFallingBlocks", true);
@ -447,19 +461,20 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenPreSimulator(PreSimulateFallingBlocks, PreSimulateWater, PreSimulateLava)));
}
else if (NoCaseCompare(*itr, "RainbowRoads") == 0)
else if (NoCaseCompare(finisher, "RainbowRoads") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsGridSize", 512);
int MaxOffset = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxOffset", 128);
int MaxDepth = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxDepth", 30);
int MaxSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxSize", 260);
m_FinishGens.push_back(cFinishGenPtr(new cRainbowRoadsGen(Seed, GridSize, MaxOffset, MaxDepth, MaxSize)));
LOGINFO("The RainbowRoads finisher is obsolete, you should use \"PieceStructures: RainbowRoads\" instead.");
auto gen = std::make_shared<cPieceStructuresGen>(Seed);
if (gen->Initialize("RainbowRoads", seaLevel, m_BiomeGen, m_CompositedHeightCache))
{
m_FinishGens.push_back(gen);
}
}
else if (NoCaseCompare(*itr, "Ravines") == 0)
else if (NoCaseCompare(finisher, "Ravines") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cStructGenRavines(Seed, 128)));
}
else if (NoCaseCompare(*itr, "RoughRavines") == 0)
else if (NoCaseCompare(finisher, "RoughRavines") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesGridSize", 256);
int MaxOffset = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxOffset", 128);
@ -494,39 +509,36 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
GridSize, MaxOffset
)));
}
else if (NoCaseCompare(*itr, "SoulsandRims") == 0)
else if (NoCaseCompare(finisher, "SoulsandRims") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSoulsandRims(Seed)));
}
else if (NoCaseCompare(*itr, "Snow") == 0)
else if (NoCaseCompare(finisher, "Snow") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSnow));
}
else if (NoCaseCompare(*itr, "SprinkleFoliage") == 0)
else if (NoCaseCompare(finisher, "SprinkleFoliage") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSprinkleFoliage(Seed)));
}
else if (NoCaseCompare(*itr, "TallGrass") == 0)
else if (NoCaseCompare(finisher, "TallGrass") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenTallGrass(Seed)));
}
else if (NoCaseCompare(*itr, "TestRails") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cTestRailsGen(Seed, 100, 1, 7, 50)));
}
else if (NoCaseCompare(*itr, "Trees") == 0)
else if (NoCaseCompare(finisher, "Trees") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cStructGenTrees(Seed, m_BiomeGen, m_ShapeGen, m_CompositionGen)));
}
else if (NoCaseCompare(*itr, "UnderwaterBases") == 0)
else if (NoCaseCompare(finisher, "UnderwaterBases") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseGridSize", 1024);
int MaxOffset = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxOffset", 128);
int MaxDepth = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxDepth", 7);
int MaxSize = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxSize", 128);
m_FinishGens.push_back(std::make_shared<cUnderwaterBaseGen>(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, m_BiomeGen));
LOGINFO("The UnderwaterBases finisher is obsolete, you should use \"PieceStructures: UnderwaterBases\" instead.");
auto gen = std::make_shared<cPieceStructuresGen>(Seed);
if (gen->Initialize("UnderwaterBases", seaLevel, m_BiomeGen, m_CompositedHeightCache))
{
m_FinishGens.push_back(gen);
}
}
else if (NoCaseCompare(*itr, "Villages") == 0)
else if (NoCaseCompare(finisher, "Villages") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "VillageGridSize", 384);
int MaxOffset = a_IniFile.GetValueSetI("Generator", "VillageMaxOffset", 128);
@ -536,23 +548,23 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
int MaxDensity = a_IniFile.GetValueSetI("Generator", "VillageMaxDensity", 80);
AString PrefabList = a_IniFile.GetValueSet("Generator", "VillagePrefabs", "PlainsVillage, SandVillage");
auto Prefabs = StringSplitAndTrim(PrefabList, ",");
m_FinishGens.push_back(std::make_shared<cVillageGen>(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, MinDensity, MaxDensity, m_BiomeGen, m_CompositedHeightCache, Prefabs));
m_FinishGens.push_back(std::make_shared<cVillageGen>(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, MinDensity, MaxDensity, m_BiomeGen, m_CompositedHeightCache, seaLevel, Prefabs));
}
else if (NoCaseCompare(*itr, "Vines") == 0)
else if (NoCaseCompare(finisher, "Vines") == 0)
{
int Level = a_IniFile.GetValueSetI("Generator", "VinesLevel", 40);
m_FinishGens.push_back(std::make_shared<cFinishGenVines>(Seed, Level));
}
else if (NoCaseCompare(*itr, "WaterLakes") == 0)
else if (NoCaseCompare(finisher, "WaterLakes") == 0)
{
int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25);
m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, m_ShapeGen, Probability)));
}
else if (NoCaseCompare(*itr, "WaterSprings") == 0)
else if (NoCaseCompare(finisher, "WaterSprings") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenFluidSprings(Seed, E_BLOCK_WATER, a_IniFile, Dimension)));
}
else if (NoCaseCompare(*itr, "WormNestCaves") == 0)
else if (NoCaseCompare(finisher, "WormNestCaves") == 0)
{
int Size = a_IniFile.GetValueSetI("Generator", "WormNestCavesSize", 64);
int Grid = a_IniFile.GetValueSetI("Generator", "WormNestCavesGrid", 96);
@ -561,7 +573,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
}
else
{
LOGWARNING("Unknown Finisher in the [Generator] section: \"%s\". Ignoring.", itr->c_str());
LOGWARNING("Unknown Finisher in the [Generator] section: \"%s\". Ignoring.", finisher.c_str());
}
} // for itr - Str[]
}

View File

@ -113,6 +113,18 @@ public:
/** Initializes the generator, reading its parameters from the INI file. */
virtual void InitializeHeightGen(cIniFile & a_IniFile) {}
/** Returns the height at the specified column.
The default implementation calls GenHeightMap(), and then queries the heightmap.
Descendants may provide a better-performing method. */
virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ)
{
int chunkX, chunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, chunkX, chunkZ);
cChunkDef::HeightMap heightMap;
GenHeightMap(chunkX, chunkZ, heightMap);
return cChunkDef::GetHeight(heightMap, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width);
}
/** Creates a cTerrainHeightGen descendant based on the INI file settings. */
static cTerrainHeightGenPtr CreateHeightGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault);
} ;

View File

@ -9,6 +9,7 @@
////////////////////////////////////////////////////////////////////////////////
// cEmptyStructure:
@ -79,6 +80,54 @@ cGridStructGen::cGridStructGen(
cGridStructGen::cGridStructGen(int a_Seed):
m_BaseSeed(a_Seed),
m_Seed(a_Seed),
m_Noise(a_Seed),
m_GridSizeX(256),
m_GridSizeZ(256),
m_MaxOffsetX(128),
m_MaxOffsetZ(128),
m_MaxStructureSizeX(128),
m_MaxStructureSizeZ(128),
m_MaxCacheSize(256)
{
}
void cGridStructGen::SetGeneratorParams(const AStringMap & a_GeneratorParams)
{
ASSERT(m_Cache.empty()); // No changing the params after chunks are generated
m_GridSizeX = GetStringMapInteger<int>(a_GeneratorParams, "GridSizeX", m_GridSizeX);
m_GridSizeZ = GetStringMapInteger<int>(a_GeneratorParams, "GridSizeZ", m_GridSizeZ);
m_MaxOffsetX = GetStringMapInteger<int>(a_GeneratorParams, "MaxOffsetX", m_MaxOffsetX);
m_MaxOffsetZ = GetStringMapInteger<int>(a_GeneratorParams, "MaxOffsetZ", m_MaxOffsetZ);
m_MaxStructureSizeX = GetStringMapInteger<int>(a_GeneratorParams, "MaxStructureSizeX", m_MaxStructureSizeX);
m_MaxStructureSizeZ = GetStringMapInteger<int>(a_GeneratorParams, "MaxStructureSizeZ", m_MaxStructureSizeZ);
// Silently fix out-of-range parameters:
if (m_MaxOffsetX < 1)
{
m_MaxOffsetX = 1;
}
if (m_MaxOffsetZ < 1)
{
m_MaxOffsetZ = 1;
}
// Set the seed based on the seed offset from the parameters:
auto seedOffset = GetStringMapInteger<int>(a_GeneratorParams, "SeedOffset", 0);
m_Seed = m_BaseSeed + seedOffset;
m_Noise.SetSeed(m_Seed);
}
void cGridStructGen::GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures)
{
// Calculate the min and max grid coords of the structures to be returned:

View File

@ -85,9 +85,24 @@ public:
int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
size_t a_MaxCacheSize
);
/** Creates a new instance that has the generation parameters set to defaults.
This is used for instances that are later loaded from a file. */
cGridStructGen(int a_Seed);
/** Sets the generator params based on the dictionary passed in.
Note that this must not be called anymore after generating a chunk. */
void SetGeneratorParams(const AStringMap & a_GeneratorParams);
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
protected:
/** Seed for generating grid offsets and also available for descendants. */
/** Base seed of the world for which the generator generates chunk. */
int m_BaseSeed;
/** Seed for generating grid offsets and also available for descendants.
Calculated from m_BaseSeed by adding the SeedOffset parameter loaded from the cubeset file (if applicable); otherwise the same as m_BaseSeed. */
int m_Seed;
/** The noise used for generating grid offsets. */
@ -131,9 +146,6 @@ protected:
around their gridpoint intersects the chunk. */
void GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures);
// cFinishGen overrides:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
// Functions for the descendants to override:
/** Create a new structure at the specified gridpoint */
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) = 0;

View File

@ -192,6 +192,27 @@ void cHeiGenCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap
HEIGHTTYPE cHeiGenCache::GetHeightAt(int a_BlockX, int a_BlockZ)
{
// First try if the chunk is already in the cache:
int chunkX, chunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, chunkX, chunkZ);
HEIGHTTYPE res;
if (GetHeightAt(chunkX, chunkZ, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width, res))
{
return res;
}
// Chunk not in cache, generate the chunk and ask again:
cChunkDef::HeightMap heightMap;
GenHeightMap(chunkX, chunkZ, heightMap);
return cChunkDef::GetHeight(heightMap, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width);
}
bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height)
{
for (size_t i = 0; i < m_CacheSize; i++)
@ -240,6 +261,27 @@ void cHeiGenMultiCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::Heig
HEIGHTTYPE cHeiGenMultiCache::GetHeightAt(int a_BlockX, int a_BlockZ)
{
// First try if the chunk is already in the cache:
int chunkX, chunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, chunkX, chunkZ);
HEIGHTTYPE res;
if (GetHeightAt(chunkX, chunkZ, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width, res))
{
return res;
}
// Chunk not in cache, generate the chunk and ask again:
cChunkDef::HeightMap heightMap;
GenHeightMap(chunkX, chunkZ, heightMap);
return cChunkDef::GetHeight(heightMap, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width);
}
bool cHeiGenMultiCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height)
{
// Get the subcache responsible for this chunk:

View File

@ -33,6 +33,7 @@ public:
// cTerrainHeightGen overrides:
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override;
/** Retrieves height at the specified point in the cache, returns true if found, false if not found */
bool GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height);
@ -72,6 +73,7 @@ public:
// cTerrainHeightGen overrides:
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override;
/** Retrieves height at the specified point in the cache, returns true if found, false if not found */
bool GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height);
@ -164,6 +166,8 @@ protected:
class cHeiGenBiomal :
public cTerrainHeightGen
{
typedef cTerrainHeightGen Super;
public:
cHeiGenBiomal(int a_Seed, cBiomeGenPtr a_BiomeGen) :
m_Noise(a_Seed),
@ -173,6 +177,10 @@ public:
// cTerrainHeightGen overrides:
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override // Need to provide this override due to clang's overzealous detection of overloaded virtuals
{
return Super::GetHeightAt(a_BlockX, a_BlockZ);
}
virtual void InitializeHeightGen(cIniFile & a_IniFile) override;
protected:

View File

@ -1,134 +0,0 @@
// NetherFortGen.cpp
// Implements the cNetherFortGen class representing the nether fortress generator
#include "Globals.h"
#include "NetherFortGen.h"
#include "Prefabs/NetherFortPrefabs.h"
////////////////////////////////////////////////////////////////////////////////
// cNetherFortGen::cNetherFort:
class cNetherFortGen::cNetherFort :
public cGridStructGen::cStructure
{
typedef cGridStructGen::cStructure super;
public:
cNetherFortGen & m_ParentGen;
int m_GridSize;
int m_Seed;
cPlacedPieces m_Pieces;
cNetherFort(cNetherFortGen & a_ParentGen, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxDepth, int a_Seed) :
super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
m_ParentGen(a_ParentGen),
m_GridSize(a_GridSize),
m_Seed(a_Seed)
{
// TODO: Proper Y-coord placement
int BlockY = 64;
// Generate pieces:
for (int i = 0; m_Pieces.size() < static_cast<size_t>(a_MaxDepth * a_MaxDepth / 8 + a_MaxDepth); i++)
{
cBFSPieceGenerator pg(cNetherFortGen::m_PiecePool, a_Seed + i);
pg.PlacePieces(a_OriginX, BlockY, a_OriginZ, a_MaxDepth, m_Pieces);
}
}
~cNetherFort()
{
cPieceGenerator::FreePieces(m_Pieces);
}
/** Carves the system into the chunk data */
virtual void DrawIntoChunk(cChunkDesc & a_Chunk)
{
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
const cPrefab & Prefab = static_cast<const cPrefab &>((*itr)->GetPiece());
Prefab.Draw(a_Chunk, *itr);
} // for itr - m_PlacedPieces[]
}
};
////////////////////////////////////////////////////////////////////////////////
// Performance test of the NetherFort generator:
/*
#include "OSSupport/Timer.h"
static class cNetherFortPerfTest
{
public:
cNetherFortPerfTest(void)
{
cTimer Timer;
long long StartTime = Timer.GetNowTime();
const int GridSize = 512;
const int MaxDepth = 12;
const int NumIterations = 100;
for (int i = 0; i < NumIterations; i++)
{
cNetherFortGen FortGen(i, GridSize, MaxDepth);
delete new cNetherFortGen::cNetherFort(FortGen, 0, 0, GridSize, MaxDepth, i);
}
long long EndTime = Timer.GetNowTime();
printf("%d forts took %lld msec (%f sec) to generate\n", NumIterations, EndTime - StartTime, ((double)(EndTime - StartTime)) / 1000);
exit(0);
}
} g_PerfTest;
//*/
////////////////////////////////////////////////////////////////////////////////
// cNetherFortGen:
cPrefabPiecePool cNetherFortGen::m_PiecePool(g_NetherFortPrefabs, g_NetherFortPrefabsCount, g_NetherFortStartingPrefabs, g_NetherFortStartingPrefabsCount);
cNetherFortGen::cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth) :
super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxDepth * 10, a_MaxDepth * 10, 200),
m_MaxDepth(a_MaxDepth)
{
/*
// DEBUG: Try one round of placement:
cPlacedPieces Pieces;
cBFSPieceGenerator pg(m_PiecePool, a_Seed);
pg.PlacePieces(0, 64, 0, a_MaxDepth, Pieces);
//*/
}
cGridStructGen::cStructurePtr cNetherFortGen::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
{
return cStructurePtr(new cNetherFort(*this, a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_GridSizeX, m_MaxDepth, m_Seed));
}

View File

@ -1,45 +0,0 @@
// NetherFortGen.h
// Declares the cNetherFortGen class representing the nether fortress generator
#pragma once
#include "ComposableGenerator.h"
#include "PrefabPiecePool.h"
#include "GridStructGen.h"
class cNetherFortGen :
public cGridStructGen
{
typedef cGridStructGen super;
public:
cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth);
protected:
friend class cNetherFortPerfTest; // fwd: NetherFortGen.cpp
class cNetherFort; // fwd: NetherFortGen.cpp
/** Maximum depth of the piece-generator tree */
int m_MaxDepth;
/** The pool of pieces to use for generating. Static, so that it's shared by multiple generators. */
static cPrefabPiecePool m_PiecePool;
// cGridStructGen overrides:
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
} ;

View File

@ -1,275 +0,0 @@
// POCPieceGenerator.cpp
// Implements the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique
// The generator generates a maze of rooms at {0, 50, 0}
#include "Globals.h"
#include "POCPieceGenerator.h"
#include "ChunkDesc.h"
/** POC pieces are simple boxes that have connectors in the middle of their walls.
Each wall has one connector, there are 3 connector types that get assigned semi-randomly.
The piece also knows how to imprint itself in a cChunkDesc, each piece has a different color glass
and each connector is uses a different color wool frame. */
class cPOCPiece :
public cPiece
{
public:
cPOCPiece(int a_SizeXZ, int a_Height) :
m_SizeXZ(a_SizeXZ),
m_Height(a_Height)
{
m_Connectors.push_back(cConnector(m_SizeXZ / 2, a_Height / 2, 0, 0, BLOCK_FACE_ZM));
m_Connectors.push_back(cConnector(m_SizeXZ / 2, a_Height / 2, m_SizeXZ - 1, 1, BLOCK_FACE_ZP));
m_Connectors.push_back(cConnector(0, a_Height / 2, m_SizeXZ / 2, 2, BLOCK_FACE_XM));
m_Connectors.push_back(cConnector(m_SizeXZ - 1, a_Height - 1, m_SizeXZ / 2, m_SizeXZ % 3, BLOCK_FACE_XP));
}
/** Imprints the piece in the specified chunk. Assumes they intersect. */
void ImprintInChunk(cChunkDesc & a_ChunkDesc, const Vector3i & a_Pos, int a_NumCCWRotations) const
{
int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
Vector3i Min = a_Pos;
Min.Move(-BlockX, 0, -BlockZ);
Vector3i Max = Min;
Max.Move(m_SizeXZ - 1, m_Height - 1, m_SizeXZ - 1);
ASSERT(Min.x < cChunkDef::Width);
ASSERT(Min.z < cChunkDef::Width);
ASSERT(Max.x >= 0);
ASSERT(Max.z >= 0);
if (Min.x >= 0)
{
// Draw the XM wall:
a_ChunkDesc.FillRelCuboid(Min.x, Min.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_SizeXZ % 16);
}
if (Min.z >= 0)
{
// Draw the ZM wall:
a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Min.z, Min.z, E_BLOCK_STAINED_GLASS, m_SizeXZ % 16);
}
if (Max.x < cChunkDef::Width)
{
// Draw the XP wall:
a_ChunkDesc.FillRelCuboid(Max.x, Max.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_SizeXZ % 16);
}
if (Max.z < cChunkDef::Width)
{
// Draw the ZP wall:
a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Max.z, Max.z, E_BLOCK_STAINED_GLASS, m_SizeXZ % 16);
}
// Draw all the connectors:
for (cConnectors::const_iterator itr = m_Connectors.begin(), end = m_Connectors.end(); itr != end; ++itr)
{
cConnector Conn = cPiece::RotateMoveConnector(*itr, a_NumCCWRotations, a_Pos.x, a_Pos.y, a_Pos.z);
Conn.m_Pos.Move(-BlockX, 0, -BlockZ);
if (
(Conn.m_Pos.x >= 0) && (Conn.m_Pos.x < cChunkDef::Width) &&
(Conn.m_Pos.z >= 0) && (Conn.m_Pos.z < cChunkDef::Width)
)
{
a_ChunkDesc.SetBlockTypeMeta(Conn.m_Pos.x, Conn.m_Pos.y, Conn.m_Pos.z, E_BLOCK_WOOL, itr->m_Type % 16);
}
/*
// TODO: Frame the connectors
switch (itr->m_Direction)
{
case BLOCK_FACE_XM:
case BLOCK_FACE_XP:
{
// TODO
break;
}
case BLOCK_FACE_ZM:
case BLOCK_FACE_ZP:
{
// TODO
break;
}
}
*/
} // for itr - m_Connectors[]
}
protected:
int m_SizeXZ;
int m_Height;
cConnectors m_Connectors;
// cPiece overrides:
virtual cConnectors GetConnectors(void) const override
{
return m_Connectors;
}
virtual Vector3i GetSize(void) const override
{
return Vector3i(m_SizeXZ, m_Height, m_SizeXZ);
}
virtual cCuboid GetHitBox(void) const override
{
return cCuboid(0, 0, 0, m_SizeXZ - 1, m_Height - 1, m_SizeXZ - 1);
}
virtual bool CanRotateCCW(int a_NumRotations) const override
{
return true;
}
};
/*
static void DebugPieces(const cPlacedPieces & a_Pieces)
{
size_t idx = 0;
for (cPlacedPieces::const_iterator itr = a_Pieces.begin(), end = a_Pieces.end(); itr != end; ++itr, ++idx)
{
const cCuboid & HitBox = (*itr)->GetHitBox();
printf(" %u: %d rotations, {%d - %d, %d - %d}\n",
idx, (*itr)->GetNumCCWRotations(),
HitBox.p1.x, HitBox.p2.x, HitBox.p1.z, HitBox.p2.z
);
} // for itr - a_Pieces[]
}
//*/
////////////////////////////////////////////////////////////////////////////////
// cPOCPieceGenerator:
cPOCPieceGenerator::cPOCPieceGenerator(int a_Seed) :
m_Seed(a_Seed)
{
// Prepare a vector of available pieces:
m_AvailPieces.push_back(new cPOCPiece(5, 3));
m_AvailPieces.push_back(new cPOCPiece(7, 5));
m_AvailPieces.push_back(new cPOCPiece(9, 5));
m_AvailPieces.push_back(new cPOCPiece(5, 7));
// Generate the structure:
cBFSPieceGenerator Gen(*this, a_Seed);
Gen.PlacePieces(0, 50, 0, 6, m_Pieces);
// DebugPieces(m_Pieces);
// Get the smallest cuboid encompassing the entire generated structure:
cCuboid Bounds(0, 50, 0, 0, 50, 0);
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
Vector3i MinCoords = (*itr)->GetCoords();
Bounds.Engulf(MinCoords);
Bounds.Engulf(MinCoords + (*itr)->GetPiece().GetSize());
} // for itr - m_Pieces[]
m_Bounds = Bounds;
}
cPOCPieceGenerator::~cPOCPieceGenerator()
{
cPieceGenerator::FreePieces(m_Pieces);
for (cPieces::iterator itr = m_AvailPieces.begin(), end = m_AvailPieces.end(); itr != end; ++itr)
{
delete *itr;
}
m_AvailPieces.clear();
}
void cPOCPieceGenerator::GenFinish(cChunkDesc & a_ChunkDesc)
{
int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
if (
(BlockX + 16 < m_Bounds.p1.x) || (BlockX > m_Bounds.p2.x) || // X coords out of bounds of the generated structure
(BlockZ + 16 < m_Bounds.p1.z) || (BlockZ > m_Bounds.p2.z) // Z coords out of bounds of the generated structure
)
{
return;
}
// Imprint each piece in the chunk:
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
const Vector3i & Pos = (*itr)->GetCoords();
Vector3i Size = (*itr)->GetPiece().GetSize();
if (((*itr)->GetNumCCWRotations() % 2) == 1)
{
std::swap(Size.x, Size.z);
}
if (
(Pos.x >= BlockX + 16) || (Pos.x + Size.x - 1 < BlockX) ||
(Pos.z >= BlockZ + 16) || (Pos.z + Size.z - 1 < BlockZ)
)
{
// This piece doesn't intersect the chunk
continue;
}
(static_cast<const cPOCPiece &>((*itr)->GetPiece())).ImprintInChunk(a_ChunkDesc, Pos, (*itr)->GetNumCCWRotations());
} // for itr - m_Pieces[]
a_ChunkDesc.UpdateHeightmap();
}
cPieces cPOCPieceGenerator::GetPiecesWithConnector(int a_ConnectorType)
{
// Each piece has each connector
return m_AvailPieces;
}
cPieces cPOCPieceGenerator::GetStartingPieces(void)
{
// Any piece can be a starting piece
return m_AvailPieces;
}
void cPOCPieceGenerator::PiecePlaced(const cPiece & a_Piece)
{
UNUSED(a_Piece);
}
void cPOCPieceGenerator::Reset(void)
{
// Nothing needed
}

View File

@ -1,54 +0,0 @@
// POCPieceGenerator.h
// Declares the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique
// The generator generates a maze of rooms at {0, 100, 0}
#pragma once
#include "PieceGenerator.h"
#include "ComposableGenerator.h"
class cPOCPieceGenerator :
public cFinishGen,
protected cPiecePool
{
public:
cPOCPieceGenerator(int a_Seed);
~cPOCPieceGenerator();
protected:
int m_Seed;
/** The pieces from which the generated structure is built. */
cPieces m_AvailPieces;
/** The placed pieces of the generated structure. */
cPlacedPieces m_Pieces;
/** Bounds of the complete structure, to save on processing outside chunks. */
cCuboid m_Bounds;
// cFinishGen overrides:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
// cPiecePool overrides:
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
virtual cPieces GetStartingPieces(void) override;
virtual void PiecePlaced(const cPiece & a_Piece) override;
virtual void Reset(void) override;
} ;

View File

@ -7,140 +7,8 @@
#include "Globals.h"
#include "PieceGenerator.h"
#include "../SelfTests.h"
#ifdef SELF_TEST
////////////////////////////////////////////////////////////////////////////////
// Self-test:
static class cPieceGeneratorSelfTest :
public cPiecePool
{
public:
cPieceGeneratorSelfTest(void)
{
cSelfTests::Get().Register(std::bind(&cPieceGeneratorSelfTest::Test, this), "PieceGenerator");
}
void Test(void)
{
// Prepare the internal state:
InitializePieces();
// Generate:
cBFSPieceGenerator Gen(*this, 0);
cPlacedPieces OutPieces;
Gen.PlacePieces(500, 50, 500, 3, OutPieces);
// Print out the pieces:
LOG("OutPieces.size() = " SIZE_T_FMT, OutPieces.size());
size_t idx = 0;
for (cPlacedPieces::const_iterator itr = OutPieces.begin(), end = OutPieces.end(); itr != end; ++itr, ++idx)
{
const Vector3i & Coords = (*itr)->GetCoords();
cCuboid Hitbox = (*itr)->GetHitBox();
Hitbox.Sort();
LOG(SIZE_T_FMT ": {%d, %d, %d}, rot %d, hitbox {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)", idx,
Coords.x, Coords.y, Coords.z,
(*itr)->GetNumCCWRotations(),
Hitbox.p1.x, Hitbox.p1.y, Hitbox.p1.z,
Hitbox.p2.x, Hitbox.p2.y, Hitbox.p2.z,
Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1
);
} // itr - OutPieces[]
LOG("Done.");
// Free the placed pieces properly:
Gen.FreePieces(OutPieces);
}
~cPieceGeneratorSelfTest()
{
// Dealloc all the pieces:
for (cPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
delete *itr;
}
m_Pieces.clear();
}
protected:
class cTestPiece :
public cPiece
{
int m_Size;
public:
cTestPiece(int a_Size) :
m_Size(a_Size)
{
}
virtual cConnectors GetConnectors(void) const override
{
// Each piece has 4 connectors, one of each type, plus one extra, at the center of its walls:
cConnectors res;
res.push_back(cConnector(m_Size / 2, 1, 0, 0, BLOCK_FACE_ZM));
res.push_back(cConnector(m_Size / 2, 1, m_Size - 1, 1, BLOCK_FACE_ZP));
res.push_back(cConnector(0, 1, m_Size / 2, 2, BLOCK_FACE_XM));
res.push_back(cConnector(m_Size - 1, 1, m_Size / 2, m_Size % 3, BLOCK_FACE_XP));
return res;
}
virtual Vector3i GetSize(void) const override
{
return Vector3i(m_Size, 5, m_Size);
}
virtual cCuboid GetHitBox(void) const override
{
return cCuboid(0, 0, 0, m_Size - 1, 4, m_Size - 1);
}
virtual bool CanRotateCCW(int a_NumCCWRotations) const override
{
return true;
}
};
cPieces m_Pieces;
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override
{
// Each piece contains each connector
return m_Pieces;
}
virtual cPieces GetStartingPieces(void) override
{
return m_Pieces;
}
virtual void PiecePlaced(const cPiece & a_Piece) override
{
UNUSED(a_Piece);
}
virtual void Reset(void) override
{
}
void InitializePieces(void)
{
m_Pieces.push_back(new cTestPiece(5));
m_Pieces.push_back(new cTestPiece(7));
m_Pieces.push_back(new cTestPiece(9));
}
} g_Test;
#endif // SELF_TEST
#include "VerticalStrategy.h"
#include "VerticalLimit.h"
@ -149,7 +17,36 @@ protected:
////////////////////////////////////////////////////////////////////////////////
// cPiece:
bool cPiece::SetVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings)
{
auto strategy = CreateVerticalStrategyFromString(a_StrategyDesc, a_LogWarnings);
if (strategy == nullptr)
{
return false;
}
m_VerticalStrategy = strategy;
return true;
}
bool cPiece::SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings)
{
auto limit = CreateVerticalLimitFromString(a_LimitDesc, a_LogWarnings);
if (limit == nullptr)
{
return false;
}
m_VerticalLimit = limit;
return true;
}
Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const
{
Vector3i Size = GetSize();
@ -361,10 +258,10 @@ void cPieceGenerator::FreePieces(cPlacedPieces & a_PlacedPieces)
cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockY, int a_BlockZ, cFreeConnectors & a_OutConnectors)
cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockZ, cFreeConnectors & a_OutConnectors)
{
m_PiecePool.Reset();
int rnd = m_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) / 7;
int rnd = m_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7;
// Choose a random one of the starting pieces:
cPieces StartingPieces = m_PiecePool.GetStartingPieces();
@ -407,15 +304,17 @@ cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockY, i
}
}
int Rotation = Rotations[rnd % NumRotations];
cPlacedPiece * res = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, a_BlockY, a_BlockZ), Rotation);
int BlockY = StartingPiece->GetStartingPieceHeight(a_BlockX, a_BlockZ);
ASSERT(BlockY >= 0); // The vertical strategy should have been provided and should give valid coords
cPlacedPiece * res = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, BlockY, a_BlockZ), Rotation);
// Place the piece's connectors into a_OutConnectors:
const cPiece::cConnectors & Conn = StartingPiece->GetConnectors();
for (cPiece::cConnectors::const_iterator itr = Conn.begin(), end = Conn.end(); itr != end; ++itr)
{
a_OutConnectors.push_back(
cFreeConnector(res, StartingPiece->RotateMoveConnector(*itr, Rotation, a_BlockX, a_BlockY, a_BlockZ))
cFreeConnector(res, StartingPiece->RotateMoveConnector(*itr, Rotation, a_BlockX, BlockY, a_BlockZ))
);
}
@ -466,6 +365,7 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
// Try fitting each of the piece's connector:
cPiece::cConnectors Connectors = (*itrP)->GetConnectors();
auto verticalLimit = (*itrP)->GetVerticalLimit();
for (cPiece::cConnectors::iterator itrC = Connectors.begin(), endC = Connectors.end(); itrC != endC; ++itrC)
{
if (itrC->m_Type != WantedConnectorType)
@ -479,6 +379,13 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
// Doesn't support this rotation
continue;
}
// Check if the piece's VerticalLimit allows this connection:
if ((verticalLimit != nullptr) && (!verticalLimit->CanBeAtHeight(ConnPos.x, ConnPos.z, ConnPos.y - itrC->m_Pos.y)))
{
continue;
}
if (!CheckConnection(a_Connector, ConnPos, **itrP, *itrC, NumCCWRotations, a_OutPieces))
{
// Doesn't fit in this rotation
@ -627,13 +534,13 @@ cBFSPieceGenerator::cBFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed) :
void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces)
void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces)
{
a_OutPieces.clear();
cFreeConnectors ConnectorPool;
// Place the starting piece:
a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockY, a_BlockZ, ConnectorPool));
a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockZ, ConnectorPool));
/*
// DEBUG:
@ -681,9 +588,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
NumProcessed++;
if (NumProcessed > 1000)
{
typedef cPieceGenerator::cFreeConnectors::difference_type difType;
ConnectorPool.erase(ConnectorPool.begin(), ConnectorPool.begin() + static_cast<difType>(NumProcessed));
NumProcessed = 0;
}

View File

@ -18,6 +18,7 @@ Each uses a slightly different approach to generating:
#pragma once
#include "ComposableGenerator.h"
#include "../Defines.h"
#include "../Cuboid.h"
#include "../Noise/Noise.h"
@ -49,9 +50,70 @@ public:
cConnector(int a_X, int a_Y, int a_Z, int a_Type, eBlockFace a_Direction);
cConnector(const Vector3i & a_Pos, int a_Type, eBlockFace a_Direction);
};
typedef std::vector<cConnector> cConnectors;
/** Base class (interface) for strategies for placing the starting pieces vertically.
Descendants can override the GetVerticalPlacement() method to provide custom placement decisions. */
class cVerticalStrategy
{
public:
// Force a virtual destructor in descendants
virtual ~cVerticalStrategy() {}
/** Returns the Y coord of the piece */
virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) = 0;
/** Initializes the strategy's parameters from the string representation.
a_Params is the string containing only the parameters (substring after the first pipe character in the strategy description string).
If a_LogWarnings is true, logs any problems to the console.
Returns true if successful, false if the string parsing failed.
Used when loading the strategy from a file. */
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) = 0;
/** Called when the piece pool is assigned to a generator,
so that the strategies may bind to the underlying subgenerators. */
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_TerrainHeightGen, int a_SeaLevel) {}
};
typedef SharedPtr<cVerticalStrategy> cVerticalStrategyPtr;
/** Base class (interface) for the vertical limit of piece placement.
Each placed piece can have a limit, represented by this class, that gets queried for validity of the placement. */
class cVerticalLimit
{
public:
virtual ~cVerticalLimit() {}
/** Called to inquire whether the specified piece can be placed at the specified height.
a_BlockX, a_BlockZ is the column of the connector that is being queried.
a_Height is the requested height of the piece's lowest block. */
virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) = 0;
/** Initializes the limit's parameters from the string representation.
a_Params is the string containing only the parameters (substring after the first pipe character in the limit description string).
Returns true if successful, false if the string parsing failed.
If a_LogWarnings is true, any error while parsing the string is output to the server console.
Used when loading the limit from a file. */
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) = 0;
/** Called when the piece pool is assigned to a generator,
so that the limits may bind to the underlying subgenerators. */
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_TerrainHeightGen, int a_SeaLevel) {}
};
typedef SharedPtr<cVerticalLimit> cVerticalLimitPtr;
/** The strategy used for vertical placement of this piece when it is used as a starting piece. */
cVerticalStrategyPtr m_VerticalStrategy;
/** The checker that verifies each placement's vertical position. */
cVerticalLimitPtr m_VerticalLimit;
/** Returns all of the available connectors that the piece has.
Each connector has a (relative) position in the piece, and a type associated with it. */
virtual cConnectors GetConnectors(void) const = 0;
@ -66,7 +128,43 @@ public:
/** Returns true if the piece can be rotated CCW the specific number of 90-degree turns. */
virtual bool CanRotateCCW(int a_NumRotations) const = 0;
/** Returns the height, based on m_VerticalStrategy, for this piece when used as the starting piece.
If there's no strategy assigned to this piece, returns -1. */
int GetStartingPieceHeight(int a_BlockX, int a_BlockZ)
{
if (m_VerticalStrategy != nullptr)
{
return m_VerticalStrategy->GetVerticalPlacement(a_BlockX, a_BlockZ);
}
return -1;
}
void SetVerticalStrategy(cVerticalStrategyPtr a_VerticalStrategy)
{
m_VerticalStrategy = a_VerticalStrategy;
}
cVerticalStrategyPtr GetVerticalStrategy(void) const
{
return m_VerticalStrategy;
}
cVerticalLimitPtr GetVerticalLimit(void) const
{
return m_VerticalLimit;
}
/** Sets the vertical strategy based on the description in the string.
If a_LogWarnings is true, logs the parsing problems into the server console.
Returns true if successful, false if strategy parsing failed (no strategy assigned). */
bool SetVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings);
/** Sets the vertical limit based on the description string.
Returns true if successful, false if limit parsing failed (no limit assigned).
If a_LogWarnings is true, any problem is reported into the server console. */
bool SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings);
/** Returns a copy of the a_Pos after rotating the piece the specified number of CCW rotations. */
Vector3i RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const;
@ -112,22 +210,24 @@ public:
/** Returns the relative weight with which the a_NewPiece is to be selected for placing under a_PlacedPiece through a_ExistingConnector.
a_ExistingConnector is the original connector, before any movement or rotation is applied to it.
This allows the pool to tweak the piece's chances, based on the previous pieces in the tree and the connector used.
The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will never be chosen.
*/
The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will never be chosen. */
virtual int GetPieceWeight(
const cPlacedPiece & a_PlacedPiece,
const cPiece::cConnector & a_ExistingConnector,
const cPiece & a_NewPiece
) { return 1; }
)
{
return 1;
}
/** Returns the relative weight with which the a_NewPiece is to be selected for placing as the first piece.
This allows the pool to tweak the piece's chances.
The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will not be chosen.
If all pieces return 0, a random piece is chosen, with all equal chances.
*/
virtual int GetStartingPieceWeight(
const cPiece & a_NewPiece
) { return 1; }
If all pieces return 0, a random piece is chosen, with all equal chances. */
virtual int GetStartingPieceWeight(const cPiece & a_NewPiece)
{
return 1;
}
/** Called after a piece is placed, to notify the pool that it has been used.
The pool may adjust the pieces it will return the next time. */
@ -229,9 +329,9 @@ protected:
int m_Seed;
/** Selects a starting piece and places it, including the rotations.
/** Selects a starting piece and places it, including its height and rotation.
Also puts the piece's connectors in a_OutConnectors. */
cPlacedPiece * PlaceStartingPiece(int a_BlockX, int a_BlockY, int a_BlockZ, cFreeConnectors & a_OutConnectors);
cPlacedPiece * PlaceStartingPiece(int a_BlockX, int a_BlockZ, cFreeConnectors & a_OutConnectors);
/** Tries to place a new piece at the specified (placed) connector. Returns true if successful. */
bool TryPlacePieceAtConnector(
@ -269,13 +369,14 @@ class cBFSPieceGenerator :
public cPieceGenerator
{
typedef cPieceGenerator super;
public:
cBFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed);
/** Generates a placement for pieces at the specified coords.
Caller must free each individual cPlacedPiece in a_OutPieces. */
void PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces);
The Y coord is generated automatically based on the starting piece that is chosen.
Caller must free each individual cPlacedPiece in a_OutPieces using cPieceGenerator::FreePieces(). */
void PlacePieces(int a_BlockX, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces);
};
@ -289,8 +390,9 @@ public:
cDFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed);
/** Generates a placement for pieces at the specified coords.
Caller must free each individual cPlacedPiece in a_OutPieces. */
void PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, cPlacedPieces & a_OutPieces);
The Y coord is generated automatically based on the starting piece that is chosen.
Caller must free each individual cPlacedPiece in a_OutPieces using cPieceGenerator::FreePieces(). */
void PlacePieces(int a_BlockX, int a_BlockZ, cPlacedPieces & a_OutPieces);
};

View File

@ -0,0 +1,129 @@
// PieceStructuresGen.cpp
// Declares the cPieceStructuresGen class representing the PieceStructures finisher generator
#include "Globals.h"
#include "PieceStructuresGen.h"
#include "PrefabStructure.h"
#include "IniFile.h"
#include "../Stopwatch.h"
cPieceStructuresGen::cPieceStructuresGen(int a_Seed):
m_Seed(a_Seed)
{
}
bool cPieceStructuresGen::Initialize(const AString & a_Prefabs, int a_SeaLevel, cBiomeGenPtr a_BiomeGen, cTerrainHeightGenPtr a_HeightGen)
{
// Load each piecepool:
auto structures = StringSplitAndTrim(a_Prefabs, "|");
for (const auto & s: structures)
{
auto fileName = Printf("Prefabs%cPieceStructures%c%s.cubeset", cFile::PathSeparator, cFile::PathSeparator, s.c_str());
if (!cFile::IsFile(fileName))
{
fileName.append(".gz");
if (!cFile::IsFile(fileName))
{
LOGWARNING("Cannot load PieceStructures cubeset file %s", fileName.c_str());
continue;
}
}
auto gen = std::make_shared<cGen>(m_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel, s);
if (gen->LoadFromFile(fileName))
{
m_Gens.push_back(gen);
}
}
// Report a warning if no generators available:
if (m_Gens.empty())
{
LOGWARNING("The PieceStructures generator was asked to generate \"%s\", but none of them are valid.", a_Prefabs.c_str());
return false;
}
return true;
}
void cPieceStructuresGen::GenFinish(cChunkDesc & a_Chunk)
{
for (auto & gen: m_Gens)
{
gen->GenFinish(a_Chunk);
}
}
////////////////////////////////////////////////////////////////////////////////
// cPieceStructuresGen::cGen:
cPieceStructuresGen::cGen::cGen(int a_Seed, cBiomeGenPtr a_BiomeGen, cTerrainHeightGenPtr a_HeightGen, int a_SeaLevel, const AString & a_Name):
Super(a_Seed),
m_BiomeGen(a_BiomeGen),
m_HeightGen(a_HeightGen),
m_SeaLevel(a_SeaLevel),
m_Name(a_Name),
m_MaxDepth(5)
{
}
bool cPieceStructuresGen::cGen::LoadFromFile(const AString & a_FileName)
{
// Load the piecepool from the file, log any warnings:
if (!m_Pool.LoadFromFile(a_FileName, true))
{
return false;
}
if (NoCaseCompare(m_Pool.GetIntendedUse(), "PieceStructures") != 0)
{
LOGWARNING("PieceStructures generator: File %s is intended for use in \"%s\", rather than piece structures. Loading the file, but the generator may behave unexpectedly.",
a_FileName.c_str(), m_Pool.GetIntendedUse().c_str()
);
}
m_Pool.AssignGens(m_Seed, m_BiomeGen, m_HeightGen, m_SeaLevel);
// Apply generator params from the piecepool (in the metadata) into the generator:
auto & generatorParams = m_Pool.GetAllMetadata();
SetGeneratorParams(generatorParams);
m_MaxDepth = GetStringMapInteger<int>(generatorParams, "MaxDepth", m_MaxDepth);
return true;
}
cGridStructGen::cStructurePtr cPieceStructuresGen::cGen::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
{
cStopwatch sw(Printf("CreateStructure for %s at <%d, %d>", m_Name.c_str(), a_GridX, a_GridZ));
cBFSPieceGenerator pg(m_Pool, m_Seed);
cPlacedPieces outPieces;
pg.PlacePieces(a_OriginX, a_OriginZ, m_MaxDepth, outPieces);
return std::make_shared<cPrefabStructure>(a_GridX, a_GridZ, a_OriginX, a_OriginZ, outPieces, m_HeightGen);
}

View File

@ -0,0 +1,91 @@
// PieceStructuresGen.h
// Declares the cPieceStructuresGen class representing the PieceStructures finisher generator
/*
This generator loads various pieces from "piecepool" files, and each such piecepool is then used in a separate
cPieceGenerator instance.
*/
#pragma once
#include "ComposableGenerator.h"
#include "PrefabPiecePool.h"
#include "GridStructGen.h"
class cPieceStructuresGen :
public cFinishGen
{
typedef cFinishGen Super;
public:
cPieceStructuresGen(int a_Seed);
/** Initializes the generator based on the specified prefab sets.
a_Prefabs contains the list of prefab sets that should be activated, "|"-separated.
All problems are logged to the console and the generator skips over them.
Returns true if at least one prefab set is valid (the generator should be kept). */
bool Initialize(const AString & a_Prefabs, int a_SeaLevel, cBiomeGenPtr a_BiomeGen, cTerrainHeightGenPtr a_HeightGen);
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
protected:
class cGen:
public cGridStructGen
{
typedef cGridStructGen Super;
public:
cGen(int a_Seed, cBiomeGenPtr a_BiomeGen, cTerrainHeightGenPtr a_HeightGen, int a_SeaLevel, const AString & a_Name);
/** Loads the piecepool from a file.
Returns true on success, logs warning and returns false on failure. */
bool LoadFromFile(const AString & a_FileName);
// cGridStructGen overrides:
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
protected:
/** The underlying biome generator that defines whether the structure is created or not */
cBiomeGenPtr m_BiomeGen;
/** The underlying height generator, used to position the prefabs crossing chunk borders if they are set to FitGround. */
cTerrainHeightGenPtr m_HeightGen;
/** The world's sea level, if available. Used for some cVerticalStrategy descendants. */
int m_SeaLevel;
/** The name that is used for reporting. */
AString m_Name;
/** All available prefabs. */
cPrefabPiecePool m_Pool;
/** Maximum depth of the generated piece tree. */
int m_MaxDepth;
};
typedef SharedPtr<cGen> cGenPtr;
typedef std::vector<cGenPtr> cGenPtrs;
/** The individual structure generators, one per piecepool. */
cGenPtrs m_Gens;
/** The seed for the random number generator */
int m_Seed;
};

View File

@ -8,6 +8,8 @@
#include "../Bindings/LuaState.h"
#include "SelfTests.h"
#include "WorldStorage/SchematicFileSerializer.h"
#include "VerticalStrategy.h"
#include "../StringCompression.h"
@ -60,13 +62,14 @@ cPrefabPiecePool::cPrefabPiecePool(void)
cPrefabPiecePool::cPrefabPiecePool(
const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs,
int a_DefaultStartingPieceHeight
)
{
AddPieceDefs(a_PieceDefs, a_NumPieceDefs);
if (a_StartingPieceDefs != nullptr)
{
AddStartingPieceDefs(a_StartingPieceDefs, a_NumStartingPieceDefs);
AddStartingPieceDefs(a_StartingPieceDefs, a_NumStartingPieceDefs, a_DefaultStartingPieceHeight);
}
}
@ -126,12 +129,21 @@ void cPrefabPiecePool::AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_
void cPrefabPiecePool::AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs)
void cPrefabPiecePool::AddStartingPieceDefs(
const cPrefab::sDef * a_StartingPieceDefs,
size_t a_NumStartingPieceDefs,
int a_DefaultPieceHeight
)
{
ASSERT(a_StartingPieceDefs != nullptr);
auto verticalStrategy = CreateVerticalStrategyFromString(Printf("Fixed|%d", a_DefaultPieceHeight), false);
for (size_t i = 0; i < a_NumStartingPieceDefs; i++)
{
cPrefab * Prefab = new cPrefab(a_StartingPieceDefs[i]);
if (a_DefaultPieceHeight >= 0)
{
Prefab->SetVerticalStrategy(verticalStrategy);
}
m_StartingPieces.push_back(Prefab);
}
}
@ -142,21 +154,43 @@ void cPrefabPiecePool::AddStartingPieceDefs(const cPrefab::sDef * a_StartingPiec
bool cPrefabPiecePool::LoadFromFile(const AString & a_FileName, bool a_LogWarnings)
{
// Read the first 4 KiB of the file in order to auto-detect format:
cFile f;
if (!f.Open(a_FileName, cFile::fmRead))
// Read the file into a string buffer, load from string:
auto contents = cFile::ReadWholeFile(a_FileName);
if (contents.empty())
{
CONDWARNING(a_LogWarnings, "Cannot open file %s for reading", a_FileName.c_str());
CONDWARNING(a_LogWarnings, "Cannot read data from file %s", a_FileName.c_str());
return false;
}
char buf[4096];
auto len = f.Read(buf, sizeof(buf));
f.Close();
AString Header(buf, static_cast<size_t>(len));
return LoadFromString(contents, a_FileName, a_LogWarnings);
}
bool cPrefabPiecePool::LoadFromString(const AString & a_Contents, const AString & a_FileName, bool a_LogWarnings)
{
// If the contents start with GZip signature, ungzip and retry:
if (a_Contents.substr(0, 3) == "\x1f\x8b\x08")
{
AString Uncompressed;
auto res = UncompressStringGZIP(a_Contents.data(), a_Contents.size(), Uncompressed);
if (res == Z_OK)
{
return LoadFromString(Uncompressed, a_FileName, a_LogWarnings);
}
else
{
CONDWARNING(a_LogWarnings, "Failed to decompress Gzip data in file %s: %d", a_FileName.c_str(), res);
return false;
}
}
// Read the first 4 KiB of the file in order to auto-detect format:
auto Header = a_Contents.substr(0, 4096);
if (Header.find("CubesetFormatVersion =") != AString::npos)
{
return LoadFromCubesetFile(a_FileName, a_LogWarnings);
return LoadFromCubeset(a_Contents, a_FileName, a_LogWarnings);
}
CONDWARNING(a_LogWarnings, "Cannot load prefabs from file %s, unknown file format", a_FileName.c_str());
return false;
@ -166,12 +200,12 @@ bool cPrefabPiecePool::LoadFromFile(const AString & a_FileName, bool a_LogWarnin
bool cPrefabPiecePool::LoadFromCubesetFile(const AString & a_FileName, bool a_LogWarnings)
bool cPrefabPiecePool::LoadFromCubeset(const AString & a_Contents, const AString & a_FileName, bool a_LogWarnings)
{
// Load the file in the Lua interpreter:
cLuaState Lua(Printf("LoadablePiecePool %s", a_FileName.c_str()));
Lua.Create();
if (!Lua.LoadFile(a_FileName, a_LogWarnings))
if (!Lua.LoadString(a_Contents, a_FileName, a_LogWarnings))
{
// Reason for failure has already been logged in LoadFile()
return false;
@ -188,7 +222,7 @@ bool cPrefabPiecePool::LoadFromCubesetFile(const AString & a_FileName, bool a_Lo
// Load the data, using the correct version loader:
if (Version == 1)
{
return LoadFromCubesetFileVer1(a_FileName, Lua, a_LogWarnings);
return LoadFromCubesetVer1(a_FileName, Lua, a_LogWarnings);
}
// Unknown version:
@ -213,15 +247,14 @@ void cPrefabPiecePool::AddToPerConnectorMap(cPrefab * a_Prefab)
bool cPrefabPiecePool::LoadFromCubesetFileVer1(const AString & a_FileName, cLuaState & a_LuaState, bool a_LogWarnings)
bool cPrefabPiecePool::LoadFromCubesetVer1(const AString & a_FileName, cLuaState & a_LuaState, bool a_LogWarnings)
{
// Load the metadata:
ApplyPoolMetadataCubesetVer1(a_FileName, a_LuaState, a_LogWarnings);
// Load the metadata and apply the known ones:
ReadPoolMetadataCubesetVer1(a_FileName, a_LuaState, a_LogWarnings);
ApplyBaseMetadataCubesetVer1(a_FileName, a_LogWarnings);
// Push the Cubeset.Pieces global value on the stack:
lua_getglobal(a_LuaState, "_G");
cLuaState::cStackValue stk(a_LuaState);
auto pieces = a_LuaState.WalkToValue("Cubeset.Pieces");
auto pieces = a_LuaState.WalkToNamedGlobal("Cubeset.Pieces");
if (!pieces.IsValid() || !lua_istable(a_LuaState, -1))
{
CONDWARNING(a_LogWarnings, "The cubeset file %s doesn't contain any pieces", a_FileName.c_str());
@ -300,16 +333,28 @@ bool cPrefabPiecePool::LoadCubesetPieceVer1(const AString & a_FileName, cLuaStat
a_LuaState.GetNamedValue("Metadata.AllowedRotations", AllowedRotations);
prefab->SetAllowedRotations(AllowedRotations);
// Apply the relevant metadata:
if (!ApplyPieceMetadataCubesetVer1(a_FileName, a_LuaState, PieceName, prefab.get(), a_LogWarnings))
// Read the relevant metadata for the piece:
if (!ReadPieceMetadataCubesetVer1(a_FileName, a_LuaState, PieceName, prefab.get(), a_LogWarnings))
{
return false;
}
// Add the prefab into the list of pieces:
// If the piece is a starting piece, check that it has a vertical strategy:
int IsStartingPiece = 0;
a_LuaState.GetNamedValue("Metadata.IsStarting", IsStartingPiece);
if (IsStartingPiece != 0)
{
if (prefab->GetVerticalStrategy() == nullptr)
{
CONDWARNING(a_LogWarnings, "Starting prefab %s in file %s doesn't have its VerticalStrategy set. Setting to Fixed|150.",
PieceName.c_str(), a_FileName.c_str()
);
VERIFY(prefab->SetVerticalStrategyFromString("Fixed|150", false));
}
}
// Add the prefab into the list of pieces:
if (IsStartingPiece != 0)
{
m_StartingPieces.push_back(prefab.release());
}
@ -319,6 +364,7 @@ bool cPrefabPiecePool::LoadCubesetPieceVer1(const AString & a_FileName, cLuaStat
m_AllPieces.push_back(p);
AddToPerConnectorMap(p);
}
return true;
}
@ -465,7 +511,7 @@ bool cPrefabPiecePool::ReadConnectorsCubesetVer1(
bool cPrefabPiecePool::ApplyPieceMetadataCubesetVer1(
bool cPrefabPiecePool::ReadPieceMetadataCubesetVer1(
const AString & a_FileName,
cLuaState & a_LuaState,
const AString & a_PieceName,
@ -482,13 +528,15 @@ bool cPrefabPiecePool::ApplyPieceMetadataCubesetVer1(
// Get the values:
int AddWeightIfSame = 0, DefaultWeight = 100, MoveToGround = 0, ShouldExpandFloor = 0;
AString DepthWeight, MergeStrategy;
AString DepthWeight, MergeStrategy, VerticalLimit, VerticalStrategy;
a_LuaState.GetNamedValue("AddWeightIfSame", AddWeightIfSame);
a_LuaState.GetNamedValue("DefaultWeight", DefaultWeight);
a_LuaState.GetNamedValue("DepthWeight", DepthWeight);
a_LuaState.GetNamedValue("MergeStrategy", MergeStrategy);
a_LuaState.GetNamedValue("MoveToGround", MoveToGround);
a_LuaState.GetNamedValue("ShouldExpandFloor", ShouldExpandFloor);
a_LuaState.GetNamedValue("VerticalLimit", VerticalLimit);
a_LuaState.GetNamedValue("VerticalStrategy", VerticalStrategy);
// Apply the values:
a_Prefab->SetAddWeightIfSame(AddWeightIfSame);
@ -509,6 +557,16 @@ bool cPrefabPiecePool::ApplyPieceMetadataCubesetVer1(
}
a_Prefab->SetMoveToGround(MoveToGround != 0);
a_Prefab->SetExtendFloor(ShouldExpandFloor != 0);
if (!VerticalLimit.empty())
{
if (!a_Prefab->SetVerticalLimitFromString(VerticalLimit, a_LogWarnings))
{
CONDWARNING(a_LogWarnings, "Unknown VerticalLimit (\"%s\") specified for piece %s in file %s. Using no limit instead.",
VerticalLimit.c_str(), a_PieceName.c_str(), a_FileName.c_str()
);
}
}
a_Prefab->SetVerticalStrategyFromString(VerticalStrategy, a_LogWarnings);
return true;
}
@ -517,21 +575,11 @@ bool cPrefabPiecePool::ApplyPieceMetadataCubesetVer1(
bool cPrefabPiecePool::ApplyPoolMetadataCubesetVer1(
void cPrefabPiecePool::ApplyBaseMetadataCubesetVer1(
const AString & a_FileName,
cLuaState & a_LuaState,
bool a_LogWarnings
)
{
// Push the Cubeset.Metadata table on top of the Lua stack:
lua_getglobal(a_LuaState, "_G");
auto md = a_LuaState.WalkToValue("Cubeset.Metadata");
if (!md.IsValid())
{
CONDWARNING(a_LogWarnings, "Cannot load cubeset from file %s: Cubeset.Metadata table is missing", a_FileName.c_str());
return false;
}
// Set the metadata values to defaults:
m_MinDensity = 100;
m_MaxDensity = 100;
@ -541,15 +589,29 @@ bool cPrefabPiecePool::ApplyPoolMetadataCubesetVer1(
m_VillageWaterRoadBlockMeta = 0;
// Read the metadata values:
a_LuaState.GetNamedValue("IntendedUse", m_IntendedUse);
a_LuaState.GetNamedValue("MaxDensity", m_MaxDensity);
a_LuaState.GetNamedValue("MinDensity", m_MinDensity);
a_LuaState.GetNamedValue("VillageRoadBlockType", m_VillageRoadBlockType);
a_LuaState.GetNamedValue("VillageRoadBlockMeta", m_VillageRoadBlockMeta);
a_LuaState.GetNamedValue("VillageWaterRoadBlockType", m_VillageWaterRoadBlockType);
a_LuaState.GetNamedValue("VillageWaterRoadBlockMeta", m_VillageWaterRoadBlockMeta);
AString allowedBiomes;
if (a_LuaState.GetNamedValue("AllowedBiomes", allowedBiomes))
m_IntendedUse = GetMetadata("IntendedUse");
GetStringMapInteger(m_Metadata, "MaxDensity", m_MaxDensity);
GetStringMapInteger(m_Metadata, "MinDensity", m_MinDensity);
GetStringMapInteger(m_Metadata, "VillageRoadBlockType", m_VillageRoadBlockType);
GetStringMapInteger(m_Metadata, "VillageRoadBlockMeta", m_VillageRoadBlockMeta);
GetStringMapInteger(m_Metadata, "VillageWaterRoadBlockType", m_VillageWaterRoadBlockType);
GetStringMapInteger(m_Metadata, "VillageWaterRoadBlockMeta", m_VillageWaterRoadBlockMeta);
// Read the allowed biomes:
AString allowedBiomes = GetMetadata("AllowedBiomes");
if (allowedBiomes.empty())
{
// All biomes are allowed:
for (int b = biFirstBiome; b <= biMaxBiome; b++)
{
m_AllowedBiomes.insert(static_cast<EMCSBiome>(b));
}
for (int b = biFirstVariantBiome; b <= biMaxVariantBiome; b++)
{
m_AllowedBiomes.insert(static_cast<EMCSBiome>(b));
}
}
else
{
auto biomes = StringSplitAndTrim(allowedBiomes, ",");
for (const auto & biome: biomes)
@ -565,17 +627,34 @@ bool cPrefabPiecePool::ApplyPoolMetadataCubesetVer1(
m_AllowedBiomes.insert(b);
}
}
else
}
bool cPrefabPiecePool::ReadPoolMetadataCubesetVer1(
const AString & a_FileName,
cLuaState & a_LuaState,
bool a_LogWarnings
)
{
// Push the Cubeset.Metadata table on top of the Lua stack:
auto gp = a_LuaState.WalkToNamedGlobal("Cubeset.Metadata");
if (!gp.IsValid())
{
// All biomes are allowed:
for (int b = biFirstBiome; b <= biMaxBiome; b++)
{
m_AllowedBiomes.insert(static_cast<EMCSBiome>(b));
}
for (int b = biFirstVariantBiome; b <= biMaxVariantBiome; b++)
{
m_AllowedBiomes.insert(static_cast<EMCSBiome>(b));
}
return true;
}
// Iterate over elements in the table, put them into the m_GeneratorParams map:
lua_pushnil(a_LuaState); // Table is at index -2, starting key (nil) at index -1
while (lua_next(a_LuaState, -2) != 0)
{
// Table at index -3, key at index -2, value at index -1
AString key, val;
a_LuaState.GetStackValues(-2, key, val);
m_Metadata[key] = val;
lua_pop(a_LuaState, 1); // Table at index -2, key at index -1
}
return true;
}
@ -584,6 +663,47 @@ bool cPrefabPiecePool::ApplyPoolMetadataCubesetVer1(
AString cPrefabPiecePool::GetMetadata(const AString & a_ParamName) const
{
auto itr = m_Metadata.find(a_ParamName);
if (itr == m_Metadata.end())
{
return AString();
}
return itr->second;
}
void cPrefabPiecePool::AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_HeightGen, int a_SeaLevel)
{
// Assign the generator linkage to all starting pieces' VerticalStrategies:
for (auto & piece: m_StartingPieces)
{
auto verticalStrategy = piece->GetVerticalStrategy();
if (verticalStrategy != nullptr)
{
verticalStrategy->AssignGens(a_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel);
}
} // for piece - m_StartingPieces[]
// Assign the generator linkage to all pieces' VerticalLimits:
for (auto & piece: m_AllPieces)
{
auto verticalLimit = piece->GetVerticalLimit();
if (verticalLimit != nullptr)
{
verticalLimit->AssignGens(a_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel);
}
} // for piece - m_AllPieces[]
}
cPieces cPrefabPiecePool::GetPiecesWithConnector(int a_ConnectorType)
{
return m_PiecesByConnector[a_ConnectorType];
@ -611,7 +731,7 @@ cPieces cPrefabPiecePool::GetStartingPieces(void)
int cPrefabPiecePool::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece)
{
return (static_cast<const cPrefab &>(a_NewPiece)).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
return (reinterpret_cast<const cPrefab &>(a_NewPiece)).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
}
@ -620,7 +740,7 @@ int cPrefabPiecePool::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const c
int cPrefabPiecePool::GetStartingPieceWeight(const cPiece & a_NewPiece)
{
return (static_cast<const cPrefab &>(a_NewPiece)).GetDefaultWeight();
return (reinterpret_cast<const cPrefab &>(a_NewPiece)).GetDefaultWeight();
}

View File

@ -36,10 +36,13 @@ public:
pieces for the pool, and they do not participate in the generation any further.
If only a_PieceDefs is given, any such piece can be chosen as a starting piece, and all the pieces are used
for generating.
More pieces can be added to the instance afterwards by calling AddPieceDefs() and AddStartingPieceDefs(). */
More pieces can be added to the instance afterwards by calling AddPieceDefs() and AddStartingPieceDefs().
If a_DefaultStartingPieceHeight is non-negative, it is applied to each starting piece as its fixed
height (for the GetStartingPieceHeight() call). */
cPrefabPiecePool(
const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs,
int a_DefaultStartingPieceHeight = -1
);
/** Creates a pool and loads the contents of the specified file into it.
@ -59,16 +62,30 @@ public:
/** Adds pieces from the specified definitions into m_StartingPieces. Doesn't add them to
the m_PiecesByConnector map.
May be called multiple times with different PieceDefs, will add all such pieces. */
void AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs);
May be called multiple times with different PieceDefs, will add all such pieces.
If a_DefaultPieceHeight is non-negative, it is applied to each piece as its fixed
height (for the GetStartingPieceHeight() call). */
void AddStartingPieceDefs(
const cPrefab::sDef * a_StartingPieceDefs,
size_t a_NumStartingPieceDefs,
int a_DefaultPieceHeight = -1
);
/** Loads the pieces from the specified file. Returns true if successful, false on error.
If a_LogWarnings is true, logs a warning to console when loading fails. */
bool LoadFromFile(const AString & a_FileName, bool a_LogWarnings);
/** Loads the pieces from the specified Cubeset file. Returns true if successful, false on error.
/** Loads the pieces from the specified string.
Returns true if successful, false on error.
a_FileName is used only logging.
If a_LogWarnings is true, logs a warning to console when loading fails. */
bool LoadFromCubesetFile(const AString & a_FileName, bool a_LogWarnings);
bool LoadFromString(const AString & a_Contents, const AString & a_FileName, bool a_LogWarnings);
/** Loads the pieces from the specified string containing Cubeset file data.
Returns true if successful, false on error.
a_FileName is used only logging.
If a_LogWarnings is true, logs a warning to console when loading fails. */
bool LoadFromCubeset(const AString & a_Contents, const AString & a_FileName, bool a_LogWarnings);
/** Returns the number of regular (non-starting) pieces. */
size_t GetAllPiecesCount(void) const { return m_AllPieces.size(); }
@ -88,6 +105,16 @@ public:
/** Returns true if a_Biome is among the accepted biomes in the m_AcceptedBiomes metadata member. */
bool IsBiomeAllowed(EMCSBiome a_Biome) const { return (m_AllowedBiomes.find(a_Biome) != m_AllowedBiomes.end()); }
/** Returns the specified value from the metadata map.
Returns an empty string if no such value had been read. */
AString GetMetadata(const AString & a_ParamName) const;
const AStringMap & GetAllMetadata(void) const { return m_Metadata; }
/** Called when the piece pool is assigned to a generator,
so that the individual starting pieces' vertical strategies may bind to the underlying subgenerators. */
void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_HeightGen, int a_SeaLevel);
// cPiecePool overrides:
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
virtual cPieces GetStartingPieces(void) override;
@ -100,7 +127,8 @@ protected:
/** The type used to map a connector type to the list of pieces with that connector */
typedef std::map<int, cPieces> cPiecesMap;
/** All the pieces that are allowed for building.
This is the list that's used for memory allocation and deallocation for the pieces. */
cPieces m_AllPieces;
@ -137,14 +165,18 @@ protected:
/** A set of allowed biomes for the pool. The pool will only be used within the specified biomes. */
std::unordered_set<EMCSBiome, BiomeHasher> m_AllowedBiomes;
/** A dictionary of pool-wide metadata, as read from the cubeset file. */
AStringMap m_Metadata;
/** Adds the prefab to the m_PiecesByConnector map for all its connectors. */
void AddToPerConnectorMap(cPrefab * a_Prefab);
/** Loads the pieces from the cubeset file parsed into the specified Lua state.
Returns true on success, false on error.
a_FileName is used only logging.
If a_LogWarnings is true, logs a warning to console when loading fails. */
bool LoadFromCubesetFileVer1(const AString & a_FileName, cLuaState & a_LuaState, bool a_LogWarnings);
bool LoadFromCubesetVer1(const AString & a_FileName, cLuaState & a_LuaState, bool a_LogWarnings);
/** Loads a single piece from the cubeset file parsed into the specified Lua state.
The piece's definition table is expected to be at the top of the Lua stack.
@ -187,7 +219,7 @@ protected:
The metadata is applied into the a_Prefab object.
a_PieceName is the identification of the piece, used for logging only.
If a_LogWarnings is true, logs a warning to console when loading fails. */
bool ApplyPieceMetadataCubesetVer1(
bool ReadPieceMetadataCubesetVer1(
const AString & a_FileName,
cLuaState & a_LuaState,
const AString & a_PieceName,
@ -195,15 +227,21 @@ protected:
bool a_LogWarnings
);
/** Reads the metadata for the entire pool from the cubeset file parsed into the specified Lua state.
/** Reads the metadata for the entire pool from the cubeset file, stores it in the m_Metadata map.
Returns true on success, false on failure.
The metadata is applied into "this".
If a_LogWarnings is true, logs a warning to console when loading fails. */
bool ApplyPoolMetadataCubesetVer1(
bool ReadPoolMetadataCubesetVer1(
const AString & a_FileName,
cLuaState & a_LuaState,
bool a_LogWarnings
);
/** Applies the base known metadata from the m_Metadata map into this pool.
If a_LogWarnings is true, logs a warning to console when loading fails. */
void ApplyBaseMetadataCubesetVer1(
const AString & a_FileName,
bool a_LogWarnings
);
} ;

View File

@ -0,0 +1,74 @@
// PrefabStructure.cpp
// Implements the cPrefabStructure class representing a cGridStructGen::cStructure descendant based on placed cPrefab instances
#include "Globals.h"
#include "PrefabStructure.h"
#include "Prefab.h"
cPrefabStructure::cPrefabStructure(
int a_GridX, int a_GridZ,
int a_OriginX, int a_OriginZ,
cPlacedPieces & a_Pieces,
cTerrainHeightGenPtr a_HeightGen
):
Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
m_Pieces(a_Pieces),
m_HeightGen(a_HeightGen)
{
}
cPrefabStructure::~cPrefabStructure()
{
cPieceGenerator::FreePieces(m_Pieces);
}
void cPrefabStructure::DrawIntoChunk(cChunkDesc & a_Chunk)
{
// Iterate over all items
// Each intersecting prefab is placed on ground, if requested, then drawn
for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
const cPrefab & Prefab = static_cast<const cPrefab &>((*itr)->GetPiece());
if (Prefab.ShouldMoveToGround() && !(*itr)->HasBeenMovedToGround())
{
PlacePieceOnGround(**itr);
}
Prefab.Draw(a_Chunk, *itr);
} // for itr - m_PlacedPieces[]
}
void cPrefabStructure::PlacePieceOnGround(cPlacedPiece & a_Piece)
{
cPiece::cConnector FirstConnector = a_Piece.GetRotatedConnector(0);
int ChunkX, ChunkZ;
int BlockX = FirstConnector.m_Pos.x;
int BlockZ = FirstConnector.m_Pos.z;
int BlockY;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cChunkDef::HeightMap HeightMap;
m_HeightGen->GenHeightMap(ChunkX, ChunkZ, HeightMap);
int TerrainHeight = cChunkDef::GetHeight(HeightMap, BlockX, BlockZ);
a_Piece.MoveToGroundBy(TerrainHeight - FirstConnector.m_Pos.y + 1);
}

View File

@ -0,0 +1,52 @@
// PrefabStructure.h
// Declares the cPrefabStructure class representing a cGridStructGen::cStructure descendant based on placed cPrefab instances
#pragma once
#include "GridStructGen.h"
#include "PieceGenerator.h"
class cPrefabStructure:
public cGridStructGen::cStructure
{
typedef cGridStructGen::cStructure Super;
public:
cPrefabStructure(
int a_GridX, int a_GridZ,
int a_OriginX, int a_OriginZ,
cPlacedPieces & a_Pieces,
cTerrainHeightGenPtr a_HeightGen
);
virtual ~cPrefabStructure();
protected:
/** The pieces placed by the generator. */
cPlacedPieces m_Pieces;
/** The height generator used when adjusting pieces onto the ground. */
cTerrainHeightGenPtr m_HeightGen;
// cGridStructGen::cStructure overrides:
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override;
/** Adjusts the Y coord of the given piece so that the piece is on the ground.
Ground level is assumed to be represented by the first connector in the piece. */
void PlacePieceOnGround(cPlacedPiece & a_Piece);
};

View File

@ -1,25 +0,0 @@
cmake_minimum_required (VERSION 2.6)
project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../../")
SET (SRCS
NetherFortPrefabs.cpp
RainbowRoadPrefabs.cpp
TestRailsPrefabs.cpp
UnderwaterBasePrefabs.cpp
)
SET (HDRS
NetherFortPrefabs.h
RainbowRoadPrefabs.h
TestRailsPrefabs.h
UnderwaterBasePrefabs.h
)
if(NOT MSVC)
add_library(Generating_Prefabs ${SRCS} ${HDRS})
target_link_libraries(Generating_Prefabs OSSupport Blocks)
endif()

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +0,0 @@
// NetherFortPrefabs.h
// Declares the prefabs in the group NetherFort
#include "../Prefab.h"
extern const cPrefab::sDef g_NetherFortPrefabs[];
extern const cPrefab::sDef g_NetherFortStartingPrefabs[];
extern const size_t g_NetherFortPrefabsCount;
extern const size_t g_NetherFortStartingPrefabsCount;

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +0,0 @@
// RainbowRoadPrefabs.h
// Declares the prefabs in the group RainbowRoad
#include "../Prefab.h"
extern const cPrefab::sDef g_RainbowRoadPrefabs[];
extern const cPrefab::sDef g_RainbowRoadStartingPrefabs[];
extern const size_t g_RainbowRoadPrefabsCount;
extern const size_t g_RainbowRoadStartingPrefabsCount;

View File

@ -1,484 +0,0 @@
// TestRailsPrefabs.cpp
// Defines the prefabs in the group TestRails
// NOTE: This file has been generated automatically by GalExport!
// Any manual changes will be overwritten by the next automatic export!
#include "Globals.h"
#include "TestRailsPrefabs.h"
const cPrefab::sDef g_TestRailsPrefabs[] =
{
////////////////////////////////////////////////////////////////////////////////
// ActivatorRail:
// The data has been exported from the gallery Plains, area index 251, ID 746, created by Aloe_vera
{
// Size:
7, 3, 7, // SizeX = 7, SizeY = 3, SizeZ = 7
// Hitbox (relative to bounding box):
0, 0, 0, // MinX, MinY, MinZ
6, 2, 6, // MaxX, MaxY, MaxZ
// Block definitions:
".: 0: 0\n" /* air */
"a: 1: 0\n" /* stone */
"b: 5: 0\n" /* wood */
"c:157: 0\n" /* activatorrail */
"d:157: 2\n" /* activatorrail */
"e:157: 3\n" /* activatorrail */
"f:157: 5\n" /* activatorrail */
"g: 50: 5\n" /* torch */
"h:157: 4\n" /* activatorrail */
"i:157: 1\n" /* activatorrail */
"m: 19: 0\n" /* sponge */,
// Block data:
// Level 0
/* z\x* 0123456 */
/* 0 */ "aaab..."
/* 1 */ "abbbbb."
/* 2 */ "abbb.b."
/* 3 */ "bbbb.bb"
/* 4 */ ".b...b."
/* 5 */ ".bbbbb."
/* 6 */ "...b..."
// Level 1
/* z\x* 0123456 */
/* 0 */ "......."
/* 1 */ ".cdbec."
/* 2 */ ".fg..f."
/* 3 */ ".b.g.b."
/* 4 */ ".h...h."
/* 5 */ ".cdbec."
/* 6 */ "......."
// Level 2
/* z\x* 0123456 */
/* 0 */ "......."
/* 1 */ "...i..."
/* 2 */ "......."
/* 3 */ ".c...c."
/* 4 */ "......."
/* 5 */ "...i..."
/* 6 */ ".......",
// Connectors:
"1: 6, 1, 3: 5\n" /* Type 1, direction X+ */
"-1: 6, 1, 3: 5\n" /* Type -1, direction X+ */
"1: 3, 1, 6: 3\n" /* Type 1, direction Z+ */
"-1: 3, 1, 6: 3\n" /* Type -1, direction Z+ */
"1: 0, 1, 3: 4\n" /* Type 1, direction X- */
"-1: 0, 1, 3: 4\n" /* Type -1, direction X- */
"1: 3, 1, 0: 2\n" /* Type 1, direction Z- */
"-1: 3, 1, 0: 2\n" /* Type -1, direction Z- */,
// AllowedRotations:
7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy:
cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
// MoveToGround:
false,
}, // ActivatorRail
////////////////////////////////////////////////////////////////////////////////
// DetectorRail:
// The data has been exported from the gallery Plains, area index 250, ID 745, created by Aloe_vera
{
// Size:
7, 3, 7, // SizeX = 7, SizeY = 3, SizeZ = 7
// Hitbox (relative to bounding box):
0, 0, 0, // MinX, MinY, MinZ
6, 2, 6, // MaxX, MaxY, MaxZ
// Block definitions:
".: 0: 0\n" /* air */
"a: 1: 0\n" /* stone */
"b: 5: 0\n" /* wood */
"c: 28: 0\n" /* detectorrail */
"d: 28: 2\n" /* detectorrail */
"e: 28: 3\n" /* detectorrail */
"f: 28: 5\n" /* detectorrail */
"g: 50: 5\n" /* torch */
"h: 28: 4\n" /* detectorrail */
"i: 28: 1\n" /* detectorrail */
"m: 19: 0\n" /* sponge */,
// Block data:
// Level 0
/* z\x* 0123456 */
/* 0 */ "aaab..."
/* 1 */ "abbbbb."
/* 2 */ "abbb.b."
/* 3 */ "bbbb.bb"
/* 4 */ ".b...b."
/* 5 */ ".bbbbb."
/* 6 */ "...b..."
// Level 1
/* z\x* 0123456 */
/* 0 */ "......."
/* 1 */ ".cdbec."
/* 2 */ ".fg..f."
/* 3 */ ".b.g.b."
/* 4 */ ".h...h."
/* 5 */ ".cdbec."
/* 6 */ "......."
// Level 2
/* z\x* 0123456 */
/* 0 */ "......."
/* 1 */ "...i..."
/* 2 */ "......."
/* 3 */ ".c...c."
/* 4 */ "......."
/* 5 */ "...i..."
/* 6 */ ".......",
// Connectors:
"1: 6, 1, 3: 5\n" /* Type 1, direction X+ */
"-1: 6, 1, 3: 5\n" /* Type -1, direction X+ */
"1: 3, 1, 0: 2\n" /* Type 1, direction Z- */
"-1: 3, 1, 0: 2\n" /* Type -1, direction Z- */
"1: 0, 1, 3: 4\n" /* Type 1, direction X- */
"-1: 0, 1, 3: 4\n" /* Type -1, direction X- */
"1: 3, 1, 6: 3\n" /* Type 1, direction Z+ */
"-1: 3, 1, 6: 3\n" /* Type -1, direction Z+ */,
// AllowedRotations:
7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy:
cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
// MoveToGround:
false,
}, // DetectorRail
////////////////////////////////////////////////////////////////////////////////
// PowerRail:
// The data has been exported from the gallery Plains, area index 248, ID 743, created by Aloe_vera
{
// Size:
7, 3, 7, // SizeX = 7, SizeY = 3, SizeZ = 7
// Hitbox (relative to bounding box):
0, 0, 0, // MinX, MinY, MinZ
6, 2, 6, // MaxX, MaxY, MaxZ
// Block definitions:
".: 0: 0\n" /* air */
"a: 1: 0\n" /* stone */
"b: 5: 0\n" /* wood */
"c: 27: 0\n" /* poweredrail */
"d: 27: 2\n" /* poweredrail */
"e: 27: 3\n" /* poweredrail */
"f: 27: 5\n" /* poweredrail */
"g: 50: 5\n" /* torch */
"h: 27: 4\n" /* poweredrail */
"i: 27: 1\n" /* poweredrail */
"m: 19: 0\n" /* sponge */,
// Block data:
// Level 0
/* z\x* 0123456 */
/* 0 */ "aaab..."
/* 1 */ "abbbbb."
/* 2 */ "abbb.b."
/* 3 */ "bbbb.bb"
/* 4 */ ".b...b."
/* 5 */ ".bbbbb."
/* 6 */ "...b..."
// Level 1
/* z\x* 0123456 */
/* 0 */ "......."
/* 1 */ ".cdbec."
/* 2 */ ".fg..f."
/* 3 */ ".b.g.b."
/* 4 */ ".h...h."
/* 5 */ ".cdbec."
/* 6 */ "......."
// Level 2
/* z\x* 0123456 */
/* 0 */ "......."
/* 1 */ "...i..."
/* 2 */ "......."
/* 3 */ ".c...c."
/* 4 */ "......."
/* 5 */ "...i..."
/* 6 */ ".......",
// Connectors:
"1: 6, 1, 3: 5\n" /* Type 1, direction X+ */
"-1: 6, 1, 3: 5\n" /* Type -1, direction X+ */
"1: 3, 1, 6: 3\n" /* Type 1, direction Z+ */
"-1: 3, 1, 6: 3\n" /* Type -1, direction Z+ */
"1: 0, 1, 3: 4\n" /* Type 1, direction X- */
"-1: 0, 1, 3: 4\n" /* Type -1, direction X- */
"1: 3, 1, 0: 2\n" /* Type 1, direction Z- */
"-1: 3, 1, 0: 2\n" /* Type -1, direction Z- */
"1: 6, 1, 3: 5\n" /* Type 1, direction X+ */
"-1: 6, 1, 3: 5\n" /* Type -1, direction X+ */,
// AllowedRotations:
7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy:
cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
// MoveToGround:
false,
}, // PowerRail
////////////////////////////////////////////////////////////////////////////////
// RegularRail:
// The data has been exported from the gallery Plains, area index 247, ID 742, created by Aloe_vera
{
// Size:
7, 3, 7, // SizeX = 7, SizeY = 3, SizeZ = 7
// Hitbox (relative to bounding box):
0, 0, 0, // MinX, MinY, MinZ
6, 2, 6, // MaxX, MaxY, MaxZ
// Block definitions:
".: 0: 0\n" /* air */
"a: 1: 0\n" /* stone */
"b: 5: 0\n" /* wood */
"c: 66: 6\n" /* tracks */
"d: 66: 2\n" /* tracks */
"e: 66: 3\n" /* tracks */
"f: 66: 7\n" /* tracks */
"g: 66: 5\n" /* tracks */
"h: 50: 5\n" /* torch */
"i: 66: 4\n" /* tracks */
"j: 66: 9\n" /* tracks */
"k: 66: 8\n" /* tracks */
"l: 66: 1\n" /* tracks */
"m: 19: 0\n" /* sponge */
"n: 66: 0\n" /* tracks */,
// Block data:
// Level 0
/* z\x* 0123456 */
/* 0 */ "aaab..."
/* 1 */ "abbbbb."
/* 2 */ "abbb.b."
/* 3 */ "bbbb.bb"
/* 4 */ ".b...b."
/* 5 */ ".bbbbb."
/* 6 */ "...b..."
// Level 1
/* z\x* 0123456 */
/* 0 */ "......."
/* 1 */ ".cdbef."
/* 2 */ ".gh..g."
/* 3 */ ".b.h.b."
/* 4 */ ".i...i."
/* 5 */ ".jdbek."
/* 6 */ "......."
// Level 2
/* z\x* 0123456 */
/* 0 */ "......."
/* 1 */ "...l..."
/* 2 */ "......."
/* 3 */ ".n...n."
/* 4 */ "......."
/* 5 */ "...l..."
/* 6 */ ".......",
// Connectors:
"1: 6, 1, 3: 5\n" /* Type 1, direction X+ */
"-1: 6, 1, 3: 5\n" /* Type -1, direction X+ */
"1: 3, 1, 6: 3\n" /* Type 1, direction Z+ */
"-1: 3, 1, 6: 3\n" /* Type -1, direction Z+ */
"1: 0, 1, 3: 4\n" /* Type 1, direction X- */
"-1: 0, 1, 3: 4\n" /* Type -1, direction X- */
"1: 3, 1, 0: 2\n" /* Type 1, direction Z- */
"-1: 3, 1, 0: 2\n" /* Type -1, direction Z- */,
// AllowedRotations:
7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy:
cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
// MoveToGround:
false,
}, // RegularRail
}; // g_TestRailsPrefabs
const cPrefab::sDef g_TestRailsStartingPrefabs[] =
{
////////////////////////////////////////////////////////////////////////////////
// CentralPiece:
// The data has been exported from the gallery Plains, area index 249, ID 744, created by Aloe_vera
{
// Size:
6, 3, 6, // SizeX = 6, SizeY = 3, SizeZ = 6
// Hitbox (relative to bounding box):
0, 0, 0, // MinX, MinY, MinZ
5, 2, 5, // MaxX, MaxY, MaxZ
// Block definitions:
".: 0: 0\n" /* air */
"a: 1: 0\n" /* stone */
"b: 5: 0\n" /* wood */
"c: 66: 6\n" /* tracks */
"d: 66: 2\n" /* tracks */
"e: 66: 3\n" /* tracks */
"f: 66: 7\n" /* tracks */
"g: 66: 5\n" /* tracks */
"h: 50: 5\n" /* torch */
"i: 66: 4\n" /* tracks */
"j: 66: 9\n" /* tracks */
"k: 66: 8\n" /* tracks */
"l: 66: 1\n" /* tracks */
"m: 19: 0\n" /* sponge */
"n: 66: 0\n" /* tracks */,
// Block data:
// Level 0
/* z\x* 012345 */
/* 0 */ "aaab.."
/* 1 */ "abbbbb"
/* 2 */ "abbb.b"
/* 3 */ "bbbb.b"
/* 4 */ ".b...b"
/* 5 */ ".bbbbb"
// Level 1
/* z\x* 012345 */
/* 0 */ "......"
/* 1 */ ".cdbef"
/* 2 */ ".gh..g"
/* 3 */ ".b.h.b"
/* 4 */ ".i...i"
/* 5 */ ".jdbek"
// Level 2
/* z\x* 012345 */
/* 0 */ "......"
/* 1 */ "...l.."
/* 2 */ "......"
/* 3 */ ".n...n"
/* 4 */ "......"
/* 5 */ "...l..",
// Connectors:
"1: 3, 1, 6: 3\n" /* Type 1, direction Z+ */
"1: 0, 1, 3: 4\n" /* Type 1, direction X- */
"-1: 0, 1, 3: 4\n" /* Type -1, direction X- */
"-1: 3, 1, 6: 3\n" /* Type -1, direction Z+ */
"1: 6, 1, 3: 5\n" /* Type 1, direction X+ */
"-1: 6, 1, 3: 5\n" /* Type -1, direction X+ */
"1: 3, 1, 0: 2\n" /* Type 1, direction Z- */
"-1: 3, 1, 0: 2\n" /* Type -1, direction Z- */,
// AllowedRotations:
7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy:
cBlockArea::msSpongePrint,
// ShouldExtendFloor:
true,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
// MoveToGround:
false,
}, // CentralPiece
};
// The prefab counts:
const size_t g_TestRailsPrefabsCount = ARRAYCOUNT(g_TestRailsPrefabs);
const size_t g_TestRailsStartingPrefabsCount = ARRAYCOUNT(g_TestRailsStartingPrefabs);

View File

@ -1,15 +0,0 @@
// TestRailsPrefabs.h
// Declares the prefabs in the group TestRails
#include "../Prefab.h"
extern const cPrefab::sDef g_TestRailsPrefabs[];
extern const cPrefab::sDef g_TestRailsStartingPrefabs[];
extern const size_t g_TestRailsPrefabsCount;
extern const size_t g_TestRailsStartingPrefabsCount;

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +0,0 @@
// UnderwaterBasePrefabs.h
// Declares the prefabs in the group UnderwaterBase
#include "../Prefab.h"
extern const cPrefab::sDef g_UnderwaterBasePrefabs[];
extern const cPrefab::sDef g_UnderwaterBaseStartingPrefabs[];
extern const size_t g_UnderwaterBasePrefabsCount;
extern const size_t g_UnderwaterBaseStartingPrefabsCount;

View File

@ -1,116 +0,0 @@
// RainbowRoadsGen.cpp
// Implements the cRainbowRoadsGen class representing the rainbow road generator
#include "Globals.h"
#include "RainbowRoadsGen.h"
#include "Prefabs/RainbowRoadPrefabs.h"
#include "PieceGenerator.h"
static cPrefabPiecePool g_RainbowRoads(g_RainbowRoadPrefabs, g_RainbowRoadPrefabsCount, g_RainbowRoadStartingPrefabs, g_RainbowRoadStartingPrefabsCount);
////////////////////////////////////////////////////////////////////////////////
// cRainbowRoadsGen::cRainbowRoads:
class cRainbowRoadsGen::cRainbowRoads :
public cGridStructGen::cStructure
{
typedef cGridStructGen::cStructure super;
public:
cRainbowRoads(
int a_Seed,
int a_GridX, int a_GridZ,
int a_OriginX, int a_OriginZ,
int a_MaxDepth,
int a_MaxSize
) :
super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
m_Seed(a_Seed),
m_Noise(a_Seed),
m_MaxSize(a_MaxSize),
m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize)
{
// Generate the pieces for this base:
cBFSPieceGenerator pg(g_RainbowRoads, a_Seed);
pg.PlacePieces(a_OriginX, 190, a_OriginZ, a_MaxDepth, m_Pieces);
if (m_Pieces.empty())
{
return;
}
}
~cRainbowRoads()
{
cPieceGenerator::FreePieces(m_Pieces);
}
protected:
/** Seed for the random functions */
int m_Seed;
/** The noise used as a pseudo-random generator */
cNoise m_Noise;
/** Maximum size, in X / Z blocks, of the village (radius from the origin) */
int m_MaxSize;
/** Borders of the vilalge - no item may reach out of this cuboid. */
cCuboid m_Borders;
/** The village pieces, placed by the generator. */
cPlacedPieces m_Pieces;
// cGridStructGen::cStructure overrides:
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
{
for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
const cPrefab & Prefab = static_cast<const cPrefab &>((*itr)->GetPiece());
Prefab.Draw(a_Chunk, *itr);
} // for itr - m_PlacedPieces[]
}
} ;
////////////////////////////////////////////////////////////////////////////////
// cRainbowRoadsGen:
cRainbowRoadsGen::cRainbowRoadsGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize) :
super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 100),
m_Noise(a_Seed + 9000),
m_MaxDepth(a_MaxDepth),
m_MaxSize(a_MaxSize)
{
}
cGridStructGen::cStructurePtr cRainbowRoadsGen::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
{
// Create a base based on the chosen prefabs:
return cStructurePtr(new cRainbowRoads(m_Seed, a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize));
}

View File

@ -1,47 +0,0 @@
// RainbowRoadsGen.h
// Declares the cRainbowRoadsGen class representing the underwater base generator
#pragma once
#include "GridStructGen.h"
#include "PrefabPiecePool.h"
class cRainbowRoadsGen :
public cGridStructGen
{
typedef cGridStructGen super;
public:
cRainbowRoadsGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize);
protected:
class cRainbowRoads; // fwd: RainbowRoadsGen.cpp
/** The noise used for generating random numbers */
cNoise m_Noise;
/** Maximum depth of the generator tree */
int m_MaxDepth;
/** Maximum size, in X / Z blocks, of the structure (radius from the origin) */
int m_MaxSize;
// cGridStructGen overrides:
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
} ;

View File

@ -1,116 +0,0 @@
// TestRailsGen.cpp
// Implements the cTestRailsGen class representing the testing rails generator
#include "Globals.h"
#include "TestRailsGen.h"
#include "Prefabs/TestRailsPrefabs.h"
#include "PieceGenerator.h"
static cPrefabPiecePool g_TestRails(g_TestRailsPrefabs, g_TestRailsPrefabsCount, g_TestRailsStartingPrefabs, g_TestRailsStartingPrefabsCount);
////////////////////////////////////////////////////////////////////////////////
// cTestRailsGen::cTestRails:
class cTestRailsGen::cTestRails :
public cGridStructGen::cStructure
{
typedef cGridStructGen::cStructure super;
public:
cTestRails(
int a_Seed,
int a_GridX, int a_GridZ,
int a_OriginX, int a_OriginZ,
int a_MaxDepth,
int a_MaxSize
) :
super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
m_Seed(a_Seed),
m_Noise(a_Seed),
m_MaxSize(a_MaxSize),
m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize)
{
// Generate the pieces for this test:
cBFSPieceGenerator pg(g_TestRails, a_Seed);
pg.PlacePieces(a_OriginX, 150, a_OriginZ, a_MaxDepth, m_Pieces);
if (m_Pieces.empty())
{
return;
}
}
~cTestRails()
{
cPieceGenerator::FreePieces(m_Pieces);
}
protected:
/** Seed for the random functions */
int m_Seed;
/** The noise used as a pseudo-random generator */
cNoise m_Noise;
/** Maximum size, in X / Z blocks, of the structure (radius from the origin) */
int m_MaxSize;
/** Borders of the structure - no item may reach out of this cuboid. */
cCuboid m_Borders;
/** The rails pieces, placed by the generator. */
cPlacedPieces m_Pieces;
// cGridStructGen::cStructure overrides:
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
{
for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
const cPrefab & Prefab = static_cast<const cPrefab &>((*itr)->GetPiece());
Prefab.Draw(a_Chunk, *itr);
} // for itr - m_PlacedPieces[]
}
} ;
////////////////////////////////////////////////////////////////////////////////
// cTestRailsGen:
cTestRailsGen::cTestRailsGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize) :
super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 100),
m_Noise(a_Seed + 1000),
m_MaxDepth(a_MaxDepth),
m_MaxSize(a_MaxSize)
{
}
cGridStructGen::cStructurePtr cTestRailsGen::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
{
// Create a base based on the chosen prefabs:
return cStructurePtr(new cTestRails(m_Seed, a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize));
}

View File

@ -1,47 +0,0 @@
// TestRailsGen.h
// Declares the cTestRailsGen class representing the testing rails generator
#pragma once
#include "GridStructGen.h"
#include "PrefabPiecePool.h"
class cTestRailsGen :
public cGridStructGen
{
typedef cGridStructGen super;
public:
cTestRailsGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize);
protected:
class cTestRails; // fwd: TestRailsGen.cpp
/** The noise used for generating random numbers */
cNoise m_Noise;
/** Maximum depth of the generator tree */
int m_MaxDepth;
/** Maximum size, in X / Z blocks, of the structure (radius from the origin) */
int m_MaxSize;
// cGridStructGen overrides:
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
} ;

View File

@ -1,143 +0,0 @@
// UnderwaterBaseGen.cpp
// Implements the cUnderwaterBaseGen class representing the underwater base generator
#include "Globals.h"
#include "UnderwaterBaseGen.h"
#include "Prefabs/UnderwaterBasePrefabs.h"
#include "PieceGenerator.h"
static cPrefabPiecePool g_UnderwaterBase(g_UnderwaterBasePrefabs, g_UnderwaterBasePrefabsCount, g_UnderwaterBaseStartingPrefabs, g_UnderwaterBaseStartingPrefabsCount);
////////////////////////////////////////////////////////////////////////////////
// cUnderwaterBaseGen::cUnderwaterBase:
class cUnderwaterBaseGen::cUnderwaterBase :
public cGridStructGen::cStructure
{
typedef cGridStructGen::cStructure super;
public:
cUnderwaterBase(
int a_Seed,
int a_GridX, int a_GridZ,
int a_OriginX, int a_OriginZ,
int a_MaxDepth,
int a_MaxSize
) :
super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
m_Seed(a_Seed),
m_Noise(a_Seed),
m_MaxSize(a_MaxSize),
m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize)
{
// Generate the pieces for this base:
cBFSPieceGenerator pg(g_UnderwaterBase, a_Seed);
pg.PlacePieces(a_OriginX, 50, a_OriginZ, a_MaxDepth, m_Pieces);
if (m_Pieces.empty())
{
return;
}
}
~cUnderwaterBase()
{
cPieceGenerator::FreePieces(m_Pieces);
}
protected:
/** Seed for the random functions */
int m_Seed;
/** The noise used as a pseudo-random generator */
cNoise m_Noise;
/** Maximum size, in X / Z blocks, of the base (radius from the origin) */
int m_MaxSize;
/** Borders of the vilalge - no item may reach out of this cuboid. */
cCuboid m_Borders;
/** The village pieces, placed by the generator. */
cPlacedPieces m_Pieces;
// cGridStructGen::cStructure overrides:
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
{
for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
{
const cPrefab & Prefab = static_cast<const cPrefab &>((*itr)->GetPiece());
Prefab.Draw(a_Chunk, *itr);
} // for itr - m_PlacedPieces[]
}
} ;
////////////////////////////////////////////////////////////////////////////////
// cUnderwaterBaseGen:
cUnderwaterBaseGen::cUnderwaterBaseGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize, cBiomeGenPtr a_BiomeGen) :
super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 100),
m_Noise(a_Seed + 1000),
m_MaxDepth(a_MaxDepth),
m_MaxSize(a_MaxSize),
m_BiomeGen(a_BiomeGen)
{
}
cGridStructGen::cStructurePtr cUnderwaterBaseGen::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
{
// Generate the biomes for the chunk surrounding the origin:
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_OriginX, a_OriginZ, ChunkX, ChunkZ);
cChunkDef::BiomeMap Biomes;
m_BiomeGen->GenBiomes(ChunkX, ChunkZ, Biomes);
// Check if all the biomes are ocean:
// If just one is not, no base is created, because it's likely that an unfriendly biome is too close
for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++)
{
switch (Biomes[i])
{
case biOcean:
case biDeepOcean:
{
// These biomes allow underwater bases
break;
}
default:
{
// base-unfriendly biome, bail out with zero structure:
return cStructurePtr();
}
} // switch (Biomes[i])
} // for i - Biomes[]
// Create a base based on the chosen prefabs:
return cStructurePtr(new cUnderwaterBase(m_Seed, a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize));
}

View File

@ -1,50 +0,0 @@
// UnderwaterBaseGen.h
// Declares the cUnderwaterBaseGen class representing the underwater base generator
#pragma once
#include "GridStructGen.h"
#include "PrefabPiecePool.h"
class cUnderwaterBaseGen :
public cGridStructGen
{
typedef cGridStructGen super;
public:
cUnderwaterBaseGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize, cBiomeGenPtr a_BiomeGen);
protected:
class cUnderwaterBase; // fwd: UnderwaterBaseGen.cpp
/** The noise used for generating random numbers */
cNoise m_Noise;
/** Maximum depth of the generator tree */
int m_MaxDepth;
/** Maximum size, in X / Z blocks, of the structure (radius from the origin) */
int m_MaxSize;
/** The underlying biome generator that defines whether the base is created or not */
cBiomeGenPtr m_BiomeGen;
// cGridStructGen overrides:
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
} ;

View File

@ -0,0 +1,414 @@
// VerticalLimit.cpp
#include "Globals.h"
#include "VerticalLimit.h"
// Emit a warning if the first param is true
#define CONDWARNING(ShouldLog, Fmt, ...) \
if (ShouldLog) \
{ \
LOGWARNING(Fmt, __VA_ARGS__); \
}
////////////////////////////////////////////////////////////////////////////////
// Globals:
/** Parses a string containing a range in which both values are optional ("<MinHeight>|<MaxHeight>") into Min, Max.
Returns true if successful, false on failure.
If a_LogWarnings is true, outputs failure reasons to console.
The range is returned in a_Min and a_Max.
If no value is in the string, both values are left unchanged.
If only the minimum is in the string, it is assigned to both a_Min and a_Max. */
static bool ParseRange(const AString & a_Params, int & a_Min, int & a_Max, bool a_LogWarnings)
{
auto params = StringSplitAndTrim(a_Params, "|");
if (params.size() == 0)
{
// No params, generate directly on top:
return true;
}
if (!StringToInteger(params[0], a_Min))
{
// Failed to parse the min rel height:
CONDWARNING(a_LogWarnings, "Cannot parse minimum height from string \"%s\"!", params[0].c_str());
return false;
}
if (params.size() == 1)
{
// Only one param was given, there's no range
a_Max = a_Min;
return true;
}
if (!StringToInteger(params[1], a_Max))
{
CONDWARNING(a_LogWarnings, "Cannot parse maximum height from string \"%s\"!", params[1].c_str());
return false;
}
if (a_Max < a_Min)
{
std::swap(a_Max, a_Min);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/** Limit that accepts any height. The default for all pieces. */
class cVerticalLimitNone:
public cPiece::cVerticalLimit
{
public:
virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override
{
// Any height is okay
return true;
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// No parameters to read, no checks being done
return true;
}
};
////////////////////////////////////////////////////////////////////////////////
/** Limit that accepts heights above the specified minimum fixed height. */
class cVerticalLimitAbove:
public cPiece::cVerticalLimit
{
public:
virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override
{
return (a_Height >= m_MinHeight);
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Parameters: "<MinHeight>", compulsory
if (!StringToInteger(a_Params, m_MinHeight))
{
CONDWARNING(a_LogWarnings, "Cannot parse the minimum height from string \"%s\"!", a_Params.c_str());
return false;
}
return true;
}
protected:
/** The minimum accepted height. */
int m_MinHeight;
};
////////////////////////////////////////////////////////////////////////////////
/** Limit that accepts heights that are a specified number of blocks above terrain. */
class cVerticalLimitAboveTerrain:
public cPiece::cVerticalLimit
{
public:
virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override
{
auto terrainHeight = m_TerrainHeightGen->GetHeightAt(a_BlockX, a_BlockZ);
int compareHeight = a_Height - terrainHeight;
return (
(compareHeight >= m_MinBlocksAbove) && // Above the minimum
(compareHeight <= m_MaxBlocksAbove) // and below the maximum
);
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Parameters: "<MinBlocksAbove>|<MaxBlocksAbove>", both optional
m_MinBlocksAbove = 0;
m_MaxBlocksAbove = 0;
return ParseRange(a_Params, m_MinBlocksAbove, m_MaxBlocksAbove, a_LogWarnings);
}
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_TerrainHeightGen, int a_SeaLevel) override
{
m_TerrainHeightGen = a_TerrainHeightGen;
}
protected:
/** The underlying height generator. */
cTerrainHeightGenPtr m_TerrainHeightGen;
/** How many blocks above the terrain level do we accept on minimum. */
int m_MinBlocksAbove;
/** How many blocks above the terrain level do we accept on maximum. */
int m_MaxBlocksAbove;
};
////////////////////////////////////////////////////////////////////////////////
/** Limit that accepts heights that are a specified number of blocks above terrain and sealevel, whichever is higher. */
class cVerticalLimitAboveTerrainAndOcean:
public cPiece::cVerticalLimit
{
public:
virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override
{
ASSERT(m_TerrainHeightGen != nullptr);
int terrainHeight = m_TerrainHeightGen->GetHeightAt(a_BlockX, a_BlockZ);
int compareHeight = a_Height - std::max(terrainHeight, m_SeaLevel);
return (
(compareHeight >= m_MinBlocksAbove) && // Above the minimum
(compareHeight <= m_MaxBlocksAbove) // and below the maximum
);
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Parameters: "<MinBlocksAbove>|<MaxBlocksAbove>", both optional
m_MinBlocksAbove = 0;
m_MaxBlocksAbove = 0;
return ParseRange(a_Params, m_MinBlocksAbove, m_MaxBlocksAbove, a_LogWarnings);
}
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_TerrainHeightGen, int a_SeaLevel) override
{
m_TerrainHeightGen = a_TerrainHeightGen;
m_SeaLevel = a_SeaLevel;
}
protected:
/** The underlying height generator. */
cTerrainHeightGenPtr m_TerrainHeightGen;
/** The sealevel for the current world. */
int m_SeaLevel;
/** How many blocks above the terrain level / ocean do we accept on minimum. */
int m_MinBlocksAbove;
/** How many blocks above the terrain level / ocean do we accept on maximum. */
int m_MaxBlocksAbove;
};
////////////////////////////////////////////////////////////////////////////////
/** Limit that accepts heights below the specified fixed height.
NOTE that the query height is the BOTTOM of the piece. */
class cVerticalLimitBelow:
public cPiece::cVerticalLimit
{
public:
virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override
{
return (a_Height <= m_MaxHeight);
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Parameters: "<MaxHeight>"
if (!StringToInteger(a_Params, m_MaxHeight))
{
CONDWARNING(a_LogWarnings, "Cannot parse the maximum height from string \"%s\"!", a_Params.c_str());
return false;
}
return true;
}
protected:
/** The maximum accepted height. */
int m_MaxHeight;
};
////////////////////////////////////////////////////////////////////////////////
/** Limit that accepts heights that are within a specified range below terrain.
NOTE that the query height is the BOTTOM of the piece. */
class cVerticalLimitBelowTerrain:
public cPiece::cVerticalLimit
{
public:
virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override
{
auto terrainHeight = m_TerrainHeightGen->GetHeightAt(a_BlockX, a_BlockZ);
auto compareHeight = terrainHeight - a_Height;
return (
(compareHeight >= m_MinBlocksBelow) &&
(compareHeight <= m_MaxBlocksBelow)
);
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Parameters: "<MinBlocksBelow>|<MaxBlocksBelow>", both optional
m_MinBlocksBelow = 0;
m_MaxBlocksBelow = 0;
return ParseRange(a_Params, m_MinBlocksBelow, m_MaxBlocksBelow, a_LogWarnings);
}
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_TerrainHeightGen, int a_SeaLevel) override
{
m_TerrainHeightGen = a_TerrainHeightGen;
}
protected:
/** The underlying height generator. */
cTerrainHeightGenPtr m_TerrainHeightGen;
/** How many blocks below the terrain level do we accept on minimum. */
int m_MinBlocksBelow;
/** How many blocks below the terrain level do we accept on maximum. */
int m_MaxBlocksBelow;
};
////////////////////////////////////////////////////////////////////////////////
/** Limit that accepts heights that are a specified number of blocks below terrain or sealevel, whichever is higher. */
class cVerticalLimitBelowTerrainOrOcean:
public cPiece::cVerticalLimit
{
public:
virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override
{
int terrainHeight = m_TerrainHeightGen->GetHeightAt(a_BlockX, a_BlockZ);
auto compareHeight = std::max(terrainHeight, m_SeaLevel) - a_Height;
return (
(compareHeight >= m_MinBlocksBelow) &&
(compareHeight <= m_MaxBlocksBelow)
);
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Parameters: "<MinBlocksBelow>|<MaxBlocksBelow>", both optional
m_MinBlocksBelow = 0;
m_MaxBlocksBelow = 0;
return ParseRange(a_Params, m_MinBlocksBelow, m_MaxBlocksBelow, a_LogWarnings);
}
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_TerrainHeightGen, int a_SeaLevel) override
{
m_TerrainHeightGen = a_TerrainHeightGen;
m_SeaLevel = a_SeaLevel;
}
protected:
/** The underlying height generator. */
cTerrainHeightGenPtr m_TerrainHeightGen;
/** The sealevel for the current world. */
int m_SeaLevel;
/** How many blocks below the terrain level do we accept on minimum. */
int m_MinBlocksBelow;
/** How many blocks below the terrain level do we accept on maximum. */
int m_MaxBlocksBelow;
};
////////////////////////////////////////////////////////////////////////////////
// CreateVerticalLimitFromString:
cPiece::cVerticalLimitPtr CreateVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings)
{
// Break apart the limit class, the first parameter before the first pipe char:
auto idxPipe = a_LimitDesc.find('|');
if (idxPipe == AString::npos)
{
idxPipe = a_LimitDesc.length();
}
AString LimitClass = a_LimitDesc.substr(0, idxPipe);
// Create a strategy class based on the class string:
cPiece::cVerticalLimitPtr Limit;
if ((LimitClass == "") || (NoCaseCompare(LimitClass, "None") == 0))
{
Limit = std::make_shared<cVerticalLimitNone>();
}
else if (NoCaseCompare(LimitClass, "Above") == 0)
{
Limit = std::make_shared<cVerticalLimitAbove>();
}
else if (NoCaseCompare(LimitClass, "AboveTerrain") == 0)
{
Limit = std::make_shared<cVerticalLimitAboveTerrain>();
}
else if (NoCaseCompare(LimitClass, "AboveTerrainAndOcean") == 0)
{
Limit = std::make_shared<cVerticalLimitAboveTerrainAndOcean>();
}
else if (NoCaseCompare(LimitClass, "Below") == 0)
{
Limit = std::make_shared<cVerticalLimitBelow>();
}
else if (NoCaseCompare(LimitClass, "BelowTerrain") == 0)
{
Limit = std::make_shared<cVerticalLimitBelowTerrain>();
}
else if (NoCaseCompare(LimitClass, "BelowTerrainOrOcean") == 0)
{
Limit = std::make_shared<cVerticalLimitBelowTerrainOrOcean>();
}
else
{
return nullptr;
}
// Initialize the limit's parameters:
AString Params;
if (idxPipe < a_LimitDesc.length())
{
Params = a_LimitDesc.substr(idxPipe + 1);
}
if (!Limit->InitializeFromString(Params, a_LogWarnings))
{
return nullptr;
}
return Limit;
}

View File

@ -0,0 +1,26 @@
// VerticalLimit.h
// Declares the public interface for cPiece's cVerticalLimit implementations
#pragma once
#include "PieceGenerator.h"
/** Returns a new cPiece::cVerticalLimit descendant based on the specified description.
a_LimitDesc is in the format "<LimitClass>|<Params>". The params and the pipe may be omitted.
If an unknown class is requested or the param parsing fails, nullptr is returned.
If a_LogWarnings is true, any problem is reported into the server console. */
cPiece::cVerticalLimitPtr CreateVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings);

View File

@ -0,0 +1,342 @@
// VerticalStrategy.cpp
// Implements the various classes descending from cPiece::cVerticalStrategy
#include "Globals.h"
#include "VerticalStrategy.h"
// Constant that is added to random seed
static const int SEED_OFFSET = 135;
// Emit a warning if the first param is true
#define CONDWARNING(ShouldLog, Fmt, ...) \
if (ShouldLog) \
{ \
LOGWARNING(Fmt, __VA_ARGS__); \
}
////////////////////////////////////////////////////////////////////////////////
// Globals:
/** Parses a string containing a range in which both values are optional ("<MinHeight>|<MaxHeight>") into Min, Range.
Returns true if successful, false on failure.
If a_LogWarnings is true, outputs failure reasons to console.
The range is returned in a_Min and a_Range, they are left unchanged if the range value is not present in the string. */
static bool ParseRange(const AString & a_Params, int & a_Min, int & a_Range, bool a_LogWarnings)
{
auto params = StringSplitAndTrim(a_Params, "|");
if (params.size() == 0)
{
// No params, generate directly on top:
return true;
}
if (!StringToInteger(params[0], a_Min))
{
// Failed to parse the min rel height:
CONDWARNING(a_LogWarnings, "Cannot parse minimum height from string \"%s\"!", params[0].c_str());
return false;
}
if (params.size() == 1)
{
// Only one param was given, there's no range
return true;
}
int maxHeight = a_Min;
if (!StringToInteger(params[1], maxHeight))
{
CONDWARNING(a_LogWarnings, "Cannot parse maximum height from string \"%s\"!", params[1].c_str());
return false;
}
if (maxHeight < a_Min)
{
std::swap(maxHeight, a_Min);
}
a_Range = maxHeight - a_Min + 1;
return true;
}
////////////////////////////////////////////////////////////////////////////////
/** A vertical strategy that places the piece at a predefined height. */
class cVerticalStrategyFixed:
public cPiece::cVerticalStrategy
{
public:
cVerticalStrategyFixed(void):
m_Height(-1000) // Default to "unassigned" height
{
}
virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) override
{
return m_Height;
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Params: "<Height>", compulsory
if (!StringToInteger(a_Params, m_Height))
{
CONDWARNING(a_LogWarnings, "Cannot parse the fixed height from string \"%s\"!", a_Params.c_str());
return false;
}
return true;
}
protected:
/** Height at which the pieces are placed.
Note that this height may be outside the world, so that only a part of the piece is generated. */
int m_Height;
};
////////////////////////////////////////////////////////////////////////////////
/** A vertical strategy that places the piece in a random height between two heights. */
class cVerticalStrategyRange:
public cPiece::cVerticalStrategy
{
public:
cVerticalStrategyRange(void):
m_Seed(0),
m_Min(-1), // Default to "unassigned" height
m_Range(1)
{
}
virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) override
{
cNoise Noise(m_Seed);
return m_Min + (Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7) % m_Range;
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Params: "<MinHeight>|<MaxHeight>", all compulsory
auto params = StringSplitAndTrim(a_Params, "|");
if (params.size() != 2)
{
CONDWARNING(a_LogWarnings, "Cannot parse the range parameters from string \"%s\"!", a_Params.c_str());
return false;
}
int Max = 0;
if (!StringToInteger(params[0], m_Min) || !StringToInteger(params[1], Max))
{
CONDWARNING(a_LogWarnings, "Cannot parse the minimum or maximum height from string \"%s\"!", a_Params.c_str());
return false;
}
if (m_Min > Max)
{
std::swap(m_Min, Max);
}
m_Range = Max - m_Min + 1;
return true;
}
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_TerrainHeightGen, int a_SeaLevel) override
{
m_Seed = a_Seed + SEED_OFFSET;
}
protected:
/** Seed for the random generator. Received in AssignGens(). */
int m_Seed;
/** Range for the random generator. Received in InitializeFromString(). */
int m_Min, m_Range;
};
////////////////////////////////////////////////////////////////////////////////
/** A vertical strategy that places the piece in a specified range relative to the top of the terrain. */
class cVerticalStrategyTerrainTop:
public cPiece::cVerticalStrategy
{
public:
virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) override
{
ASSERT(m_HeightGen != nullptr);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::HeightMap HeightMap;
m_HeightGen->GenHeightMap(ChunkX, ChunkZ, HeightMap);
cNoise noise(m_Seed);
int rel = m_MinRelHeight + (noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7) % m_RelHeightRange + 1;
return cChunkDef::GetHeight(HeightMap, a_BlockX - ChunkX * cChunkDef::Width, a_BlockZ - ChunkZ * cChunkDef::Width) + rel;
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Params: "<MinRelativeHeight>|<MaxRelativeHeight>", all optional
m_MinRelHeight = 0;
m_RelHeightRange = 1;
return ParseRange(a_Params, m_MinRelHeight, m_RelHeightRange, a_LogWarnings);
}
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_HeightGen, int a_SeaLevel) override
{
m_Seed = a_Seed + SEED_OFFSET;
m_HeightGen = a_HeightGen;
}
protected:
/** Seed for the random generator. */
int m_Seed;
/** Height generator from which the top of the terrain is read. */
cTerrainHeightGenPtr m_HeightGen;
/** Minimum relative height at which the prefab is placed. */
int m_MinRelHeight;
/** Range of the relative heights at which the prefab can be placed above the minimum. */
int m_RelHeightRange;
};
////////////////////////////////////////////////////////////////////////////////
/** A vertical strategy that places the piece within a range on top of the terrain or ocean, whichever's higher. */
class cVerticalStrategyTerrainOrOceanTop:
public cPiece::cVerticalStrategy
{
public:
virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) override
{
ASSERT(m_HeightGen != nullptr);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::HeightMap HeightMap;
m_HeightGen->GenHeightMap(ChunkX, ChunkZ, HeightMap);
int terrainHeight = static_cast<int>(cChunkDef::GetHeight(HeightMap, a_BlockX - ChunkX * cChunkDef::Width, a_BlockZ - ChunkZ * cChunkDef::Width));
terrainHeight = std::max(1 + terrainHeight, m_SeaLevel);
cNoise noise(m_Seed);
int rel = m_MinRelHeight + (noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7) % m_RelHeightRange + 1;
return terrainHeight + rel;
}
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
{
// Params: "<MinRelativeHeight>|<MaxRelativeHeight>", all optional
m_MinRelHeight = 0;
m_RelHeightRange = 1;
return ParseRange(a_Params, m_MinRelHeight, m_RelHeightRange, a_LogWarnings);
}
virtual void AssignGens(int a_Seed, cBiomeGenPtr & a_BiomeGen, cTerrainHeightGenPtr & a_HeightGen, int a_SeaLevel) override
{
m_Seed = a_Seed + SEED_OFFSET;
m_HeightGen = a_HeightGen;
m_SeaLevel = a_SeaLevel;
}
protected:
/** Seed for the random generator. */
int m_Seed;
/** Height generator from which the top of the terrain is read. */
cTerrainHeightGenPtr m_HeightGen;
/** The sea level used by the world. */
int m_SeaLevel;
/** Minimum relative height at which the prefab is placed. */
int m_MinRelHeight;
/** Range of the relative heights at which the prefab can be placed above the minimum. */
int m_RelHeightRange;
};
////////////////////////////////////////////////////////////////////////////////
// CreateVerticalStrategyFromString:
cPiece::cVerticalStrategyPtr CreateVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings)
{
// Break apart the strategy class, the first parameter before the first pipe char:
auto idxPipe = a_StrategyDesc.find('|');
if (idxPipe == AString::npos)
{
idxPipe = a_StrategyDesc.length();
}
AString StrategyClass = a_StrategyDesc.substr(0, idxPipe);
// Create a strategy class based on the class string:
cPiece::cVerticalStrategyPtr Strategy;
if (NoCaseCompare(StrategyClass, "Fixed") == 0)
{
Strategy = std::make_shared<cVerticalStrategyFixed>();
}
else if (NoCaseCompare(StrategyClass, "Range") == 0)
{
Strategy = std::make_shared<cVerticalStrategyRange>();
}
else if (NoCaseCompare(StrategyClass, "TerrainTop") == 0)
{
Strategy = std::make_shared<cVerticalStrategyTerrainTop>();
}
else if (NoCaseCompare(StrategyClass, "TerrainOrOceanTop") == 0)
{
Strategy = std::make_shared<cVerticalStrategyTerrainOrOceanTop>();
}
else
{
return nullptr;
}
// Initialize the strategy's parameters:
AString Params;
if (idxPipe < a_StrategyDesc.length())
{
Params = a_StrategyDesc.substr(idxPipe + 1);
}
if (!Strategy->InitializeFromString(Params, a_LogWarnings))
{
return nullptr;
}
return Strategy;
}

View File

@ -0,0 +1,25 @@
// VerticalStrategy.h
// Declares the public interface for cPiece's cVerticalStrategy implementations
#pragma once
#include "PieceGenerator.h"
/** Returns a new cPiece::cVerticalStrategy descendant based on the specified description.
a_StrategyDesc is in the format "<StrategyClass>|<Params>". The params and the pipe may be omitted.
If an unknown class is requested or the param parsing fails, nullptr is returned. */
cPiece::cVerticalStrategyPtr CreateVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings);

View File

@ -14,8 +14,8 @@
/*
How village generating works:
By descending from a cGridStructGen, a semi-random (jitter) grid is generated. A village may be generated for each
of the grid's cells. Each cell checks the biomes in an entire chunk around it, only generating a village if all
biomes are village-friendly. If yes, the entire village structure is built for that cell. If not, the cell
of the grid's cells. Each cell checks the biomes in an entire chunk around its center, only generating a village if
all biomes are village-friendly. If yes, the entire village structure is built for that cell. If not, the cell
is left village-less.
A village is generated using the regular BFS piece generator. The well piece is used as the starting piece,
@ -28,7 +28,7 @@ both types' opposites, type "-2" at the far ends and type "1" on the long edges.
type "2" connectors along the long edges of the roads as well, so that the roads create T junctions.
When the village is about to be drawn into a chunk, it queries the heights for each piece intersecting the
chunk. The pieces are shifted so that their pivot points lie on the surface, and the roads are drawn
chunk. The pieces are shifted so that their first connector lies on the surface, and the roads are drawn
directly by turning the surface blocks into gravel / sandstone.
The village prefabs are stored in global piecepools (one pool per village type). In order to support
@ -134,21 +134,11 @@ public:
{
// Generate the pieces for this village; don't care about the Y coord:
cBFSPieceGenerator pg(*this, a_Seed);
pg.PlacePieces(a_OriginX, 0, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces);
pg.PlacePieces(a_OriginX, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces);
if (m_Pieces.empty())
{
return;
}
// If the central piece should be moved to ground, move it, and
// check all of its dependents and move those that are strictly connector-driven based on its new Y coord:
if (static_cast<const cPrefab &>(m_Pieces[0]->GetPiece()).ShouldMoveToGround())
{
int OrigPosY = m_Pieces[0]->GetCoords().y;
PlacePieceOnGround(*m_Pieces[0]);
int NewPosY = m_Pieces[0]->GetCoords().y;
MoveAllDescendants(m_Pieces, 0, NewPosY - OrigPosY);
}
}
~cVillage()
@ -206,8 +196,8 @@ protected:
Prefab.Draw(a_Chunk, *itr);
} // for itr - m_PlacedPieces[]
}
/** Adjusts the Y coord of the given piece so that the piece is on the ground.
Ground level is assumed to be represented by the first connector in the piece. */
void PlacePieceOnGround(cPlacedPiece & a_Piece)
@ -345,6 +335,7 @@ cVillageGen::cVillageGen(
int a_MaxDensity,
cBiomeGenPtr a_BiomeGen,
cTerrainHeightGenPtr a_HeightGen,
int a_SeaLevel,
const AStringVector & a_PrefabsToLoad
) :
super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 100),
@ -368,6 +359,7 @@ cVillageGen::cVillageGen(
fileName.c_str(), prefabs->GetIntendedUse().c_str()
);
}
prefabs->AssignGens(a_Seed, m_BiomeGen, m_HeightGen, a_SeaLevel);
m_Pools.push_back(std::move(prefabs));
}
}

View File

@ -38,6 +38,7 @@ public:
int a_MinDensity, int a_MaxDensity,
cBiomeGenPtr a_BiomeGen,
cTerrainHeightGenPtr a_HeightGen,
int a_SeaLevel,
const AStringVector & a_PrefabsToLoad
);

43
src/Stopwatch.h Normal file
View File

@ -0,0 +1,43 @@
// Stopwatch.h
// Implements the cStopwatch class that measures and logs time between its creation and destruction
#pragma once
#include <chrono>
class cStopwatch
{
public:
cStopwatch(const AString & a_Name):
m_Name(a_Name),
m_StartTime(std::chrono::high_resolution_clock::now())
{
}
~cStopwatch()
{
#ifdef _DEBUG
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_StartTime).count();
LOGD("Stopwatch: %s took %.03f sec", m_Name.c_str(), static_cast<double>(duration) / 1000);
#endif // _DEBUG
}
protected:
AString m_Name;
std::chrono::high_resolution_clock::time_point m_StartTime;
};

View File

@ -17,6 +17,10 @@ typedef std::string AString;
typedef std::vector<AString> AStringVector;
typedef std::list<AString> AStringList;
/** A string dictionary, used for key-value pairs. */
typedef std::map<AString, AString> AStringMap;
@ -129,6 +133,10 @@ extern AStringVector MergeStringVectors(const AStringVector & a_Strings1, const
/** Concatenates the specified strings into a single string, separated by the specified separator. */
extern AString StringsConcat(const AStringVector & a_Strings, char a_Separator);
/** Parses any integer type. Checks bounds and returns errors out of band. */
template <class T>
bool StringToInteger(const AString & a_str, T & a_Num)
@ -197,6 +205,35 @@ bool StringToInteger(const AString & a_str, T & a_Num)
return true;
}
/** Returns an integer from a key-value string map.
Returns a_Default if the key is not present or the value is not an int. */
template <typename T>
int GetStringMapInteger(const AStringMap & a_Map, const AString & a_Key, T a_Default)
{
// Try to locate the key:
auto itr = a_Map.find(a_Key);
if (itr == a_Map.end())
{
return a_Default;
}
// Try to convert the value to a number:
T res = a_Default;
if (!StringToInteger<T>(itr->second, res))
{
return a_Default;
}
return res;
}
// If you have any other string helper functions, declare them here

View File

@ -22,6 +22,8 @@ set (SHARED_SRCS
${CMAKE_SOURCE_DIR}/src/Generating/PieceGenerator.cpp
${CMAKE_SOURCE_DIR}/src/Generating/Prefab.cpp
${CMAKE_SOURCE_DIR}/src/Generating/PrefabPiecePool.cpp
${CMAKE_SOURCE_DIR}/src/Generating/VerticalLimit.cpp
${CMAKE_SOURCE_DIR}/src/Generating/VerticalStrategy.cpp
${CMAKE_SOURCE_DIR}/src/Noise/Noise.cpp
@ -50,6 +52,8 @@ set (SHARED_HDRS
${CMAKE_SOURCE_DIR}/src/Generating/PieceGenerator.h
${CMAKE_SOURCE_DIR}/src/Generating/Prefab.h
${CMAKE_SOURCE_DIR}/src/Generating/PrefabPiecePool.h
${CMAKE_SOURCE_DIR}/src/Generating/VerticalLimit.h
${CMAKE_SOURCE_DIR}/src/Generating/VerticalStrategy.h
${CMAKE_SOURCE_DIR}/src/Noise/Noise.h