From db9fc956f320273b0dc05c077349b9aff6ed6117 Mon Sep 17 00:00:00 2001 From: EltamGit Date: Mon, 10 Feb 2014 09:48:44 +0100 Subject: [PATCH] extended mob spawn detection to spawn inside transparent blocks With Minecraft spawning it is possible to spawn on top of blocks with solid top surface and 2 blocks clear space above. Up to now the clear space was tested only with air, but also other transparent blocks allow mobs to spawn inside (e.g. button, flower or thin snow). Now both cases are handled correctly. --- blockidentifier.cpp | 7 +++++ blockidentifier.h | 1 + definitions/readme.txt | 36 +++++++++++++++------- definitions/vanilla_ids.json | 51 ++++++++++++++++++++++++++----- mapview.cpp | 58 ++++++++++++++++++++++++++---------- 5 files changed, 120 insertions(+), 33 deletions(-) diff --git a/blockidentifier.cpp b/blockidentifier.cpp index 5c5e284d..dcfd5300 100755 --- a/blockidentifier.cpp +++ b/blockidentifier.cpp @@ -36,6 +36,7 @@ BlockInfo::BlockInfo() , liquid(false) , rendernormal(true) , providepower(false) +, spawninside(false) {} bool BlockInfo::isOpaque() @@ -218,16 +219,21 @@ void BlockIdentifier::parseDefinition(JSONObject *b, BlockInfo *parent, int pack block->rendernormal=false; // for most cases except the following if (b->has("rendercube")) block->rendernormal=b->at("rendercube")->asBool(); + block->spawninside=false; // for most cases except the following + if (b->has("spawninside")) + block->spawninside=b->at("spawninside")->asBool(); } else if (parent!=NULL) { block->transparent=parent->transparent; block->rendernormal=parent->rendernormal; + block->spawninside=parent->spawninside; } else { block->transparent=false; block->rendernormal=true; + block->spawninside=false; } if (b->has("liquid")) @@ -302,6 +308,7 @@ void BlockIdentifier::parseDefinition(JSONObject *b, BlockInfo *parent, int pack block->mask=b->at("mask")->asNumber(); else block->mask=0xff; + if (b->has("variants")) { JSONArray *variants=dynamic_cast(b->at("variants")); diff --git a/blockidentifier.h b/blockidentifier.h index f22d7918..bebdb0d5 100755 --- a/blockidentifier.h +++ b/blockidentifier.h @@ -64,6 +64,7 @@ class BlockInfo bool liquid; bool rendernormal; bool providepower; + bool spawninside; quint32 colors[16]; }; diff --git a/definitions/readme.txt b/definitions/readme.txt index d5f7e3d9..e70befa1 100755 --- a/definitions/readme.txt +++ b/definitions/readme.txt @@ -4,6 +4,11 @@ to the Minecraft source code. The Minecraft Wiki is not correct in all cases. In the Minecraft source code some major flags are defined for all blocks: isOpaque renderAsNormalBlock isLiquid and canProvidePower +Additionally mobs can spawn inside/through some transparent blocks which is +checked with hit box collision. As this is not possible to check in Minutor +a special flag "spawninside" has to be set for that blocks. + + isLiquid: is obvious and true for still and flowing water and lava @@ -25,19 +30,30 @@ isOpaque and renderAsNormalBlock "transparent": true, "rendercube": true - all other transparent blocks have to be flagged only with + all other transparent blocks have to be tagged only with "transparent": true List of tranparent blocks: Anvil, PressurePlate(s), Beacon, Bed, Ice, BrewingStand, Button(s), Cactus, - Cake, Carpet(s), Cauldron, Chest(s), Cocoa, DaylightDetector, Door(s), DragonEgg, - EnchantmentTable, EnderChest, EndPortal, EndPortalFrame, Farmland, Fence, - FenceGate, Fire, Flower(s), FlowerPot, Fluid = Water/Lava, Glass, HalfSlab(s), - Hopper, Ladder, Leave(s), Lever, MobSpawner, Pane(s), PistonBase, PistonExtension, - PistonMoving, Portal, Rail(s), Repeater, Comperator, RedstoneWire, Reed, Sign, - Skull, Snow, Stair(s), Torch, TrapDoor, TripWire, TripWireSource, Vine, Wall, Web - -All this information is gathered from the 1.6.4 source code. -As at the moment no deobfuscated 1.7.x code is available. + Cake, Carpet(s), Cauldron, Chest(s), Cocoa, DaylightDetector, Door(s), + DragonEgg, EnchantmentTable, EnderChest, EndPortal, EndPortalFrame, Farmland, + Fence, FenceGate, Fire, Flower(s), FlowerPot, Fluid = Water/Lava, Glass, + HalfSlab(s), Hopper, Ladder, Leave(s), Lever, MobSpawner, Pane(s), PistonBase, + PistonExtension, PistonMoving, Portal, Rail(s), Repeater, Comperator, + RedstoneWire, Reed, Sign, Skull, Snow, Stair(s), Torch, TrapDoor, TripWire, + TripWireSource, Vine, Wall, Web + + +List of blocks that mobs can spawn inside: + PressurePlate(s), Button(s), Cocoa, (single block) Flower(s), Ladder, Lever, + Rail(s), Reed, Sign, Snow, Vine +to be flagged with + "spawninside": true + + +All this information is gathered directly from the 1.6.4 source code or special +test setup per block in 1.8 snapshots. As at the moment deobfuscated 1.7.x or +1.8.x code is not available. + [EtlamGit] \ No newline at end of file diff --git a/definitions/vanilla_ids.json b/definitions/vanilla_ids.json index 6d46aa5b..8ae0734b 100755 --- a/definitions/vanilla_ids.json +++ b/definitions/vanilla_ids.json @@ -6,7 +6,8 @@ { "id": 0, "name": "Air", - "transparent": true + "transparent": true, + "spawninside": true }, { "id": 1, @@ -98,6 +99,7 @@ "color": "1f6519", "mask": 7, "transparent": true, + "spawninside": true, "variants": [ { "data": 1, @@ -294,13 +296,15 @@ "id": 27, "name": "Powered Rail", "color": "ab0301", - "transparent": true + "transparent": true, + "spawninside": true }, { "id": 28, "name": "Detector Rail", "color": "7d7171", "transparent": true, + "spawninside": true, "canProvidePower": true }, { @@ -320,6 +324,7 @@ "name": "Dead Shrub", "color": "946428", "transparent": true, + "spawninside": true, "variants": [ { "data": 1, @@ -339,6 +344,7 @@ "name": "Dead Bush", "color": "946428", "transparent": true, + "spawninside": true, "alpha": 0.3 }, { @@ -439,6 +445,7 @@ "name": "Dandelion", "color": "f1f902", "transparent": true, + "spawninside": true, "alpha": 0.3 }, { @@ -446,6 +453,7 @@ "name": "Poppy", "color": "ba050b", "transparent": true, + "spawninside": true, "alpha": 0.3, "variants": [ { @@ -495,6 +503,7 @@ "name": "Brown Mushroom", "color": "916d55", "transparent": true, + "spawninside": true, "alpha": 0.3 }, { @@ -502,6 +511,7 @@ "name": "Red Mushroom", "color": "e21212", "transparent": true, + "spawninside": true, "alpha": 0.3 }, { @@ -727,7 +737,8 @@ "id": 63, "name": "Sign Post", "color": "9f844d", - "transparent": true + "transparent": true, + "spawninside": true }, { "id": 64, @@ -739,13 +750,15 @@ "id": 65, "name": "Ladder", "color": "8e733c", - "transparent": true + "transparent": true, + "spawninside": true }, { "id": 66, "name": "Rail", "color": "a4a4a4", - "transparent": true + "transparent": true, + "spawninside": true }, { "id": 67, @@ -757,13 +770,15 @@ "id": 68, "name": "Wall Sign", "color": "b4905a", - "transparent": true + "transparent": true, + "spawninside": true }, { "id": 69, "name": "Lever", "color": "735e39", "transparent": true, + "spawninside": true, "canProvidePower": true }, { @@ -771,6 +786,7 @@ "name": "Stone Pressure Plate", "color": "8f8f8f", "transparent": true, + "spawninside": true, "canProvidePower": true }, { @@ -784,6 +800,7 @@ "name": "Wooden Pressure Plate", "color": "bc9862", "transparent": true, + "spawninside": true, "canProvidePower": true }, { @@ -815,12 +832,14 @@ "name": "Stone Button", "color": "a8a8a8", "transparent": true, + "spawninside": true, "canProvidePower": true }, { "id": 78, "name": "Snow", "color": "eeffff", + "spawninside": true, "transparent": true }, { @@ -851,6 +870,7 @@ "id": 83, "name": "Sugar Cane", "color": "aadb74", + "spawninside": true, "transparent": true }, { @@ -1162,7 +1182,8 @@ "id": 106, "name": "Vines", "color": "6cc44a", - "transparent": true + "transparent": true, + "spawninside": true }, { "id": 107, @@ -1353,6 +1374,8 @@ "id": 127, "name": "Immature Cocoa Pod", "color": "929943", + "transparent": true, + "spawninside": true, "mask": 12, "variants": [ { @@ -1384,6 +1407,7 @@ "name": "Tripwire Hook", "color": "6e6e6e", "transparent": true, + "spawninside": true, "canProvidePower": true }, { @@ -1525,6 +1549,7 @@ "name": "Wooden Button", "color": "b4905a", "transparent": true, + "spawninside": true, "canProvidePower": true }, { @@ -1551,6 +1576,7 @@ "name": "Weighted Pressure Plate (Light)", "color": "fdfb4f", "transparent": true, + "spawninside": true, "canProvidePower": true }, { @@ -1558,6 +1584,7 @@ "name": "Weighted Pressure Plate (Heavy)", "color": "e6e6e6", "transparent": true, + "spawninside": true, "canProvidePower": true }, { @@ -1636,7 +1663,8 @@ "id": 157, "name": "Activator Rail", "color": "ab0301", - "transparent": true + "transparent": true, + "spawninside": true }, { "id": 158, @@ -1854,6 +1882,12 @@ "name": "Slime Block", "color": "608756" }, + { + "id": 166, + "name": "Barrier", + "color": "00000000", + "alpha": 0.0 + }, { "id": 170, "name": "Hay Bale", @@ -1961,6 +1995,7 @@ "id": 175, "name": "Sunflower", "transparent": true, + "spawninside": true, "variants": [ { "data": 1, diff --git a/mapview.cpp b/mapview.cpp index 36d19806..c336974b 100755 --- a/mapview.cpp +++ b/mapview.cpp @@ -377,7 +377,7 @@ void MapView::renderChunk(Chunk *chunk) ChunkSection *section1 = chunk->sections[(y+1)>>4]; if (section1) light = section1->getLight(x,y+1,z); - int mlight = light; + int light1 = light; if (!(flags & flgLighting)) light = 12; if (alpha==0.0) @@ -401,27 +401,55 @@ void MapView::renderChunk(Chunk *chunk) colg = colg * (256 - (depth - y)) / 256; colb = colb * (256 - (depth - y)) / 256; } - if ( (flags & flgMobSpawn) && (mlight<8) && - block.doesBlockHaveSolidTopSurface(data) && - !block.name.contains("Bedrock") ) + if (flags & flgMobSpawn) { - // check for 2 air blocks above - // to be correct we would have to test for: - // block1: !isBlockNormalCube && !isLiquid - // block2: !isBlockNormalCube - // and then check the bounding box of the mob... - quint16 block1 = 0; // default to air - quint16 block2 = 0; // default to air + // get block info from 1 and 2 above and 1 below + quint16 blid1(0), blid2(0), blidB(0); // default to air + int data1(0), data2(0), dataB(0); // default variant ChunkSection *section2=chunk->sections[(y+2)>>4]; + ChunkSection *sectionB=chunk->sections[(y-1)>>4]; if (section1) - block1 = section1->getBlock(x,y+1,z); + { + blid1 = section1->getBlock(x,y+1,z); + data1 = section1->getData(x,y+1,z); + } if (section2) - block2 = section2->getBlock(x,y+2,z); - if ( (block1==0) && (block2==0) ) + { + blid2 = section2->getBlock(x,y+2,z); + data2 = section2->getData(x,y+2,z); + } + if (sectionB) + { + blidB = sectionB->getBlock(x,y-1,z); + dataB = sectionB->getData(x,y-1,z); + } + BlockInfo &block2=blocks->getBlock(blid2,data2); + BlockInfo &block1=blocks->getBlock(blid1,data1); + BlockInfo &block0=block; + BlockInfo &blockB=blocks->getBlock(blidB,dataB); + int light0 = section->getLight(x,y,z); + + // spawn check #1: on top of solid block + if ( block0.doesBlockHaveSolidTopSurface(data) && + !block0.name.contains("Bedrock") && + (light1<8) && + !block1.isBlockNormalCube() && block1.spawninside && !block1.isLiquid() && + !block2.isBlockNormalCube() && block2.spawninside ) { colr = (colr+256)/2; colg = (colg+0)/2; - colb = (colb+0)/2; + colb = (colb+192)/2; + } + // spawn check #2: current block is transparent, but mob can spawn through (e.g. snow) + if ( blockB.doesBlockHaveSolidTopSurface(dataB) && + !blockB.name.contains("Bedrock") && + (light0<8) && + !block0.isBlockNormalCube() && block0.spawninside && !block0.isLiquid() && + !block1.isBlockNormalCube() && block1.spawninside ) + { + colr = (colr+192)/2; + colg = (colg+0)/2; + colb = (colb+256)/2; } } if (alpha==0.0)