diff --git a/data/data_symbols.csv b/data/data_symbols.csv index 0fe1d7e5..45cad553 100644 --- a/data/data_symbols.csv +++ b/data/data_symbols.csv @@ -1,3 +1,12 @@ +0x0000007101091690,_ZTI9SavedData +0x00000071010c6538,_ZTV16StructureFeature +0x00000071010c65b8,_ZTV25StructureFeatureSavedData +0x00000071010C65E8,_ZN16StructureManager15s_resourceNamesE +0x00000071010C6978,_ZTV16StructureManager +0x00000071010c69c8,_ZTV14StructurePiece +0x00000071010c6b30,_ZTV14StructureStart +0x00000071010C6B98,_ZTV17StructureTemplate +0x00000071010df050,_ZTI25StructureFeatureSavedData 0x0000007101781BBC,AABB__sThreadStorageCount 0x0000007101781BC0,AABB__sDefaultThreadStorage 0x0000007101781BE0,_ZN6Blocks8RegistryE @@ -804,6 +813,8 @@ 0x000000710178CAF0,_ZN13MaterialColor14TERRACOTTA_REDE 0x000000710178CAF8,_ZN13MaterialColor16TERRACOTTA_BLACKE 0x000000710178CD28,_ZN13ParticleTypes5SMOKEE +0x000000710178cd30,_ZN6Mirror4NONEE +0x000000710178cd38,_ZN6Mirror10LEFT_RIGHTE 0x000000710178CD68,_ZN11MobCategory7MONSTERE 0x000000710178CD70,_ZN11MobCategory8CREATUREE 0x000000710178CD78,_ZN11MobCategory7AMBIENTE @@ -838,6 +849,7 @@ 0x00000071017A1958,_ZN11PlanksBlock7Variant8VARIANTSE 0x00000071017A1988,_ZN11PlanksBlock9PREDICATEE 0x00000071017A1A30,_ZN15RangedAttribute12ATTACK_SPEEDE +0x00000071017a1a40,_ZN14DataFixerUpper16DATA_VERSION_KEYE 0x00000071017A1BB0,_ZN9Direction4Axis9PREDICATEE 0x00000071017A1E70,_ZN15PrismarineBlock7VARIANTE 0x00000071017A1E78,_ZN15PrismarineBlock7Variant8VARIANTSE @@ -871,6 +883,8 @@ 0x00000071017A2220,_ZN17RedSandStoneBlock7Variant6SMOOTHE 0x00000071017A2390,_ZN10ReedsBlock12sAgePropertyE 0x00000071017A2448,_ZN18RotatedPillarBlock4AXISE +0x00000071017a2450,_ZN8Rotation4NONEE +0x00000071017a2458,_ZN8Rotation12CLOCKWISE_90E 0x00000071017A2490,_ZN9SandBlock7VARIANTE 0x00000071017A2498,_ZN9SandBlock7Variant7DEFAULTE 0x00000071017A24A0,_ZN9SandBlock7Variant8VARIANTSE @@ -901,6 +915,9 @@ 0x00000071017A42E8,SoundType::GRASS 0x00000071017A42F0,SoundType::STONE 0x00000071017A4318,SoundType::SNOW +0x00000071017a4410,_ZN18SparseLightStorage15sRetirementSlotE +0x00000071017a4418,_ZN18SparseLightStorage8sRetiredE +0x00000071017a44c0,gSparseLightAllocatedBytes 0x00000071017A4AC0,_ZN10StoneBlock7VARIANTE 0x00000071017A4AC8,_ZN10StoneBlock7Variant5STONEE 0x00000071017A4AD0,_ZN10StoneBlock7Variant7GRANITEE @@ -919,7 +936,9 @@ 0x00000071017A4BD8,_ZN15StoneBrickBlock7Variant5MOSSYE 0x00000071017A4BE0,_ZN15StoneBrickBlock7Variant7CRACKEDE 0x00000071017A4BE8,_ZN15StoneBrickBlock7Variant8CHISELEDE +0x00000071017a5260,_ZN25StructureFeatureSavedData12FEATURES_KEYE 0x00000071017A53F8,SynchedEntityData__sIdMap +0x00000071017A58E8,_ZN4Vec34ZEROE 0x00000071017A5ED8,_ZZN10StoneBlock26createBlockStateDefinitionEvE10properties 0x00000071017A8380,_ZN3fui9sInstanceE 0x00000071017AA788,CGameNetworkManager__sInstance diff --git a/data/mcswitch_functions.csv b/data/mcswitch_functions.csv index 186c2e38..0c251ded 100644 --- a/data/mcswitch_functions.csv +++ b/data/mcswitch_functions.csv @@ -1799,13 +1799,13 @@ Address,Quality,Size,Name 0x00000071000441a4,U,000424,_ZN14BiomeDecoratorC2Ev 0x000000710004434c,U,000052,_ZN12ReedsFeatureC1Ev 0x0000007100044380,U,000052,_ZN13CactusFeatureC1Ev -0x00000071000443b4,O,000052,_ZN16WaterlilyFeatureC1Ev +0x00000071000443b4,O,000052,_ZN16WaterlilyFeatureC2Ev 0x00000071000443e8,U,000484,_ZN14BiomeDecoratorD2Ev 0x00000071000445cc,U,000036,_ZN14BiomeDecoratorD0Ev 0x00000071000445f0,U,001040,_ZN14BiomeDecorator8decorateEP5LevelR6RandomP5BiomeRK8BlockPos 0x0000007100044a00,O,000096,_ZNK10BlockState8setValueIPN10StoneBlock7VariantEEEPKS_P8PropertyT_ 0x0000007100044a60,U,004100,_ZN14BiomeDecorator8decorateEP5BiomeP5LevelR6Random -0x0000007100045a64,O,000052,_ZN14PumpkinFeatureC1Ev +0x0000007100045a64,O,000052,_ZN14PumpkinFeatureC2Ev 0x0000007100045a98,U,000416,_ZN14BiomeDecorator12decorateOresEP5LevelR6Random 0x0000007100045c38,U,000300, 0x0000007100045d64,U,000268, @@ -2574,26 +2574,26 @@ Address,Quality,Size,Name 0x000000710006f0b0,U,000128,_ZN10BottleItem13GetUseTooltipERK21ItemToolTipDataHolder 0x000000710006f130,U,000028,_ZN10BottleItem7getIconEi 0x000000710006f14c,U,000004,_ZN10BottleItem13registerIconsEP12IconRegister -0x000000710006f150,U,000012, -0x000000710006f15c,U,000068, -0x000000710006f1a0,U,000328, -0x000000710006f2e8,U,000140, -0x000000710006f374,U,000052, +0x000000710006f150,O,000012,_ZN11BoundingBoxC1Ev +0x000000710006f15c,O,000068,_ZN11BoundingBox13getUnknownBoxEv +0x000000710006f1a0,M,000328,_ZN11BoundingBox9orientBoxEiiiiiiiiiPK9Direction +0x000000710006f2e8,O,000140,_ZN11BoundingBox12createProperEiiiiii +0x000000710006f374,O,000052,_ZN11BoundingBoxC1EPS_ 0x000000710006f3a8,O,000016,_ZN11BoundingBoxC1Eiiiiii -0x000000710006f3b8,U,000024, -0x000000710006f3d0,U,000140, -0x000000710006f45c,U,000212, -0x000000710006f530,U,000076, -0x000000710006f57c,U,000128, -0x000000710006f5fc,U,000056, -0x000000710006f634,U,000204, -0x000000710006f700,U,000020, -0x000000710006f714,U,000020, -0x000000710006f728,U,000020, -0x000000710006f73c,U,000116, +0x000000710006f3b8,O,000024,_ZN11BoundingBoxC1Eiiii +0x000000710006f3d0,O,000140,_ZN11BoundingBox10intersectsEPS_ +0x000000710006f45c,O,000212,_ZN11BoundingBox10intersectsE5Vec3iS0_ +0x000000710006f530,O,000076,_ZN11BoundingBox10intersectsEiiii +0x000000710006f57c,O,000128,_ZN11BoundingBox6expandEPS_ +0x000000710006f5fc,O,000056,_ZN11BoundingBox4moveEiii +0x000000710006f634,O,000204,_ZN11BoundingBox8isInsideE5Vec3i +0x000000710006f700,O,000020,_ZN11BoundingBox8getXSpanEv +0x000000710006f714,O,000020,_ZN11BoundingBox8getYSpanEv +0x000000710006f728,O,000020,_ZN11BoundingBox8getZSpanEv +0x000000710006f73c,O,000116,_ZN11BoundingBox9getCenterEv 0x000000710006f7b0,U,000012, -0x000000710006f7bc,U,000148, -0x000000710006f850,U,000152, +0x000000710006f7bc,O,000148,_ZN11BoundingBox5writeEP16DataOutputStream +0x000000710006f850,O,000152,_ZN11BoundingBox4readEP15DataInputStream 0x000000710006f8e8,O,000300,_ZN7BowItemC1Ev 0x000000710006fa14,U,000048,_ZN33BowItem_Pull_ItemPropertyFunctionC1Ev 0x000000710006fa44,U,000048,_ZN36BowItem_Pulling_ItemPropertyFunctionC1Ev @@ -4201,7 +4201,7 @@ Address,Quality,Size,Name 0x00000071000b49f0,O,000024,_ZNSt3__113unordered_mapI16ResourceLocation11eINSTANCEOFNS_4hashIS1_EENS_8equal_toIS1_EENS_9allocatorINS_4pairIKS1_S2_EEEEE2atERS9_ 0x00000071000b4a08,M,000300,_ZNSt3__112__hash_tableINS_17__hash_value_typeI16ResourceLocation11eINSTANCEOFEENS_22__unordered_map_hasherIS2_S4_NS_4hashIS2_EELb1EEENS_21__unordered_map_equalIS2_S4_NS_8equal_toIS2_EELb1EEENS_9allocatorIS4_EEE4findIS2_EENS_15__hash_iteratorIPNS_11__hash_nodeIS4_PvEEEERKT_ 0x00000071000b4b34,M,000008,_ZNKSt3__14hashI16ResourceLocationEclERKS1_ -0x00000071000b4b3c,M,000012,_ZNK16ResourceLocationeqERKS_ +0x00000071000b4b3c,M,000012,_ZNKSt3__18equal_toI16ResourceLocationEclERKS1_S4_ 0x00000071000b4b48,U,000604, 0x00000071000b4da4,O,000108,_ZNSt3__112__hash_tableINS_17__hash_value_typeI16ResourceLocation11eINSTANCEOFEENS_22__unordered_map_hasherIS2_S4_NS_4hashIS2_EELb1EEENS_21__unordered_map_equalIS2_S4_NS_8equal_toIS2_EELb1EEENS_9allocatorIS4_EEE21__construct_node_hashIRKNS_21piecewise_construct_tEJNS_5tupleIJRKS2_EEENSK_IJEEEEEENS_10unique_ptrINS_11__hash_nodeIS4_PvEENS_22__hash_node_destructorINSD_ISS_EEEEEEmOT_DpOT0_ 0x00000071000b4e10,U,000932, @@ -4741,7 +4741,7 @@ Address,Quality,Size,Name 0x00000071000c1da4,O,000008,_ZN10TypedBoxedIPN10StoneBlock7VariantEE8getValueEv 0x00000071000c1dac,U,000092, 0x00000071000c1e08,U,000044, -0x00000071000c1e34,U,000036,_ZNSt3__119basic_istringstreamIwNS_11char_traitsIwEENS_9allocatorIwEEED0Ev +0x00000071000c1e34,O,000036,_ZNSt3__119basic_istringstreamIwNS_11char_traitsIwEENS_9allocatorIwEEED0Ev 0x00000071000c1e58,U,000016, 0x00000071000c1e68,U,000016, 0x00000071000c1e78,U,000068, @@ -12633,7 +12633,7 @@ Address,Quality,Size,Name 0x00000071001b0fa4,U,000048, 0x00000071001b0fd4,U,000096, 0x00000071001b1034,U,000008,_ZNK15IntegerProperty15getUnboxedValueERKNSt3__112basic_stringIwNS0_11char_traitsIwEENS0_9allocatorIwEEEE -0x00000071001b103c,U,000204,_ZNSt3__115basic_stringbufIwNS_11char_traitsIwEENS_9allocatorIwEEEC_gen6 +0x00000071001b103c,O,000204,_Z11_fromStringIiET_RKNSt3__112basic_stringIwNS1_11char_traitsIwEENS1_9allocatorIwEEEE 0x00000071001b1108,U,000008, 0x00000071001b1110,U,000016, 0x00000071001b1120,U,000032, @@ -13020,8 +13020,8 @@ Address,Quality,Size,Name 0x00000071001cd888,U,000008, 0x00000071001cd890,U,000808, 0x00000071001cdbb8,U,000036, -0x00000071001cdbdc,U,000012, -0x00000071001cdbe8,U,000012, +0x00000071001cdbdc,O,000012,_Z14boundingBoxMaxii +0x00000071001cdbe8,O,000012,_Z14boundingBoxMinii 0x00000071001cdbf4,U,000088, 0x00000071001cdc4c,U,000032, 0x00000071001cdc6c,U,000004, @@ -14686,7 +14686,7 @@ Address,Quality,Size,Name 0x0000007100206114,O,000004,_ZN5Level20broadcastEntityEventENSt3__110shared_ptrI6EntityEEji 0x0000007100206118,O,000008,_ZN5Level14getChunkSourceEv 0x0000007100206120,U,000084,_ZN5Level10blockEventERK8BlockPosP5Blockii -0x0000007100206174,U,000008, +0x0000007100206174,O,000008,_ZN5Level15getLevelStorageEv 0x000000710020617c,O,000004,_ZN5Level24updateSleepingPlayerListEv 0x0000007100206180,U,000012, 0x000000710020618c,U,000012,setRainLevel__5LevelFf @@ -14696,9 +14696,9 @@ Address,Quality,Size,Name 0x0000007100206220,O,000036,_ZN5Level9isHumidAtERK8BlockPos 0x0000007100206244,U,000008,setSavedDataStorage__5LevelFP16SavedDataStorage 0x000000710020624c,U,000008,getSavedDataStorage__5LevelFv -0x0000007100206254,U,000104, +0x0000007100206254,U,000104,_ZN5Level12setSavedDataERKNSt3__112basic_stringIwNS0_11char_traitsIwEENS0_9allocatorIwEEEENS0_10shared_ptrI9SavedDataEE 0x00000071002062bc,O,000016,_ZNSt3__110shared_ptrI9SavedDataED2Ev -0x00000071002062cc,U,000016, +0x00000071002062cc,U,000016,_ZN5Level12getSavedDataERKSt9type_infoRKNSt3__112basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEE 0x00000071002062dc,U,000016, 0x00000071002062ec,U,000068,_ZN5Level17getAuxValueForMapE9PlayerUIDiiii 0x0000007100206330,U,000200, @@ -16936,8 +16936,8 @@ Address,Quality,Size,Name 0x000000710026ab1c,O,000324,_ZN21NetherFlatLevelSource11createChunkEii 0x000000710026ac60,O,000016,_ZN21NetherFlatLevelSource10lightChunkEP10LevelChunk 0x000000710026ac70,M,000604,_ZN21NetherFlatLevelSource11postProcessEii -0x000000710026aecc,O,000052,_ZN15HellFireFeatureC1Ev -0x000000710026af00,O,000052,_ZN15LightGemFeatureC1Ev +0x000000710026aecc,O,000052,_ZN15HellFireFeatureC2Ev +0x000000710026af00,O,000052,_ZN15LightGemFeatureC2Ev 0x000000710026af34,O,000068,_ZN21NetherFlatLevelSource9getMobsAtEP11MobCategoryRK8BlockPos 0x000000710026af78,O,000008,_ZN21NetherFlatLevelSource22postProcessLoadedChunkEP10LevelChunkii 0x000000710026af80,O,000008,_ZN21NetherFlatLevelSource21findNearestMapFeatureEP5LevelRKNSt3__112basic_stringIwNS2_11char_traitsIwEENS2_9allocatorIwEEEERK8BlockPosb @@ -23328,10 +23328,10 @@ Address,Quality,Size,Name 0x000000710033eef0,U,000024,_ZNSt3__120__shared_ptr_pointerIP8VillagesNS_14default_deleteIS1_EENS_9allocatorIS1_EEE16__on_zero_sharedEv 0x000000710033ef08,U,000028,_ZNKSt3__120__shared_ptr_pointerIP8VillagesNS_14default_deleteIS1_EENS_9allocatorIS1_EEE13__get_deleterERKSt9type_info 0x000000710033ef24,U,000004,_ZNSt3__120__shared_ptr_pointerIP8VillagesNS_14default_deleteIS1_EENS_9allocatorIS1_EEE21__on_zero_shared_weakEv -0x000000710033ef28,U,000036,_ZNSt3__120__shared_ptr_pointerIP25StructureFeatureSavedDataNS_14default_deleteIS1_EENS_9allocatorIS1_EEED0Ev -0x000000710033ef4c,U,000024,_ZNSt3__120__shared_ptr_pointerIP25StructureFeatureSavedDataNS_14default_deleteIS1_EENS_9allocatorIS1_EEE16__on_zero_sharedEv -0x000000710033ef64,U,000028,_ZNKSt3__120__shared_ptr_pointerIP25StructureFeatureSavedDataNS_14default_deleteIS1_EENS_9allocatorIS1_EEE13__get_deleterERKSt9type_info -0x000000710033ef80,U,000004,_ZNSt3__120__shared_ptr_pointerIP25StructureFeatureSavedDataNS_14default_deleteIS1_EENS_9allocatorIS1_EEE21__on_zero_shared_weakEv +0x000000710033ef28,O,000036,_ZNSt3__120__shared_ptr_pointerIP25StructureFeatureSavedDataNS_14default_deleteIS1_EENS_9allocatorIS1_EEED0Ev +0x000000710033ef4c,O,000024,_ZNSt3__120__shared_ptr_pointerIP25StructureFeatureSavedDataNS_14default_deleteIS1_EENS_9allocatorIS1_EEE16__on_zero_sharedEv +0x000000710033ef64,O,000028,_ZNKSt3__120__shared_ptr_pointerIP25StructureFeatureSavedDataNS_14default_deleteIS1_EENS_9allocatorIS1_EEE13__get_deleterERKSt9type_info +0x000000710033ef80,O,000004,_ZNSt3__120__shared_ptr_pointerIP25StructureFeatureSavedDataNS_14default_deleteIS1_EENS_9allocatorIS1_EEE21__on_zero_shared_weakEv 0x000000710033ef84,U,000108, 0x000000710033eff0,U,000056, 0x000000710033f028,U,000200, @@ -23999,30 +23999,30 @@ Address,Quality,Size,Name 0x000000710035bb34,U,000012, 0x000000710035bb40,U,000012, 0x000000710035bb4c,U,000004, -0x000000710035bb50,U,000052,_ZN18SparseLightStorage10staticCtorEv -0x000000710035bb84,U,000148,__ct__18SparseLightStorageFb -0x000000710035bc18,U,000056, -0x000000710035bc50,U,000096,__ct__18SparseLightStorageFbT1 -0x000000710035bcb0,U,000056, -0x000000710035bce8,U,000016, -0x000000710035bcf8,U,000052, -0x000000710035bd2c,U,000076, -0x000000710035bd78,U,000400, -0x000000710035bf08,U,000040, -0x000000710035bf30,U,000304, -0x000000710035c060,U,000024, -0x000000710035c078,U,000148, -0x000000710035c10c,U,000260, -0x000000710035c210,U,000380, -0x000000710035c38c,U,000068, -0x000000710035c3d0,U,000468, -0x000000710035c5a4,U,000280, -0x000000710035c6bc,U,000032, -0x000000710035c6dc,U,000156,_ZN18SparseLightStorage4tickEv -0x000000710035c778,U,000408,_ZN18SparseLightStorage8compressEv -0x000000710035c910,U,000020,isCompressed__18SparseLightStorageFv -0x000000710035c924,U,000120,SparseLightStorage__write -0x000000710035c99c,U,000148, +0x000000710035bb50,O,000052,_ZN18SparseLightStorage10staticCtorEv +0x000000710035bb84,O,000148,_ZN18SparseLightStorageC1Eb +0x000000710035bc18,O,000056,_ZN18SparseLightStorage8allocateEj +0x000000710035bc50,O,000096,_ZN18SparseLightStorageC1Ebb +0x000000710035bcb0,O,000056,_ZN18SparseLightStorageD2Ev +0x000000710035bce8,O,000016,_ZN18SparseLightStorage10bufferSizeEy +0x000000710035bcf8,O,000052,_ZN18SparseLightStorage10freeBufferEPhi +0x000000710035bd2c,O,000076,_ZN18SparseLightStorageC1ERKS_ +0x000000710035bd78,M,000400,_ZN18SparseLightStorage11fromNibblesE15arrayWithLengthIhEi +0x000000710035bf08,O,000040,_ZN18SparseLightStorage7replaceEy +0x000000710035bf30,M,000304,_ZN18SparseLightStorage9toNibblesE15arrayWithLengthIhEj +0x000000710035c060,O,000024,_ZN18SparseLightStorage10getBuffersEPPhS1_ +0x000000710035c078,O,000148,_ZN18SparseLightStorage8getLightEiii +0x000000710035c10c,O,000260,_ZN18SparseLightStorage8setLightEiiii +0x000000710035c210,M,000380,_ZN18SparseLightStorage12expandLayersERNSt3__16vectorIiNS0_9allocatorIiEEEE +0x000000710035c38c,O,000068,_ZN18SparseLightStorage13setFullBrightEv +0x000000710035c3d0,O,000468,_ZN18SparseLightStorage13setDataRegionE15arrayWithLengthIhEiiiiiii +0x000000710035c5a4,O,000280,_ZN18SparseLightStorage13getDataRegionE15arrayWithLengthIhEiiiiiii +0x000000710035c6bc,O,000032,_ZN18SparseLightStorage6retireEPh +0x000000710035c6dc,O,000156,_ZN18SparseLightStorage4tickEv +0x000000710035c778,M,000408,_ZN18SparseLightStorage8compressEv +0x000000710035c910,O,000020,_ZN18SparseLightStorage12isCompressedEv +0x000000710035c924,O,000120,_ZN18SparseLightStorage5writeEP16DataOutputStream +0x000000710035c99c,O,000148,_ZN18SparseLightStorage4readEP15DataInputStream 0x000000710035ca30,U,000148,_ZN9SpawnDataC_gen 0x000000710035cac4,U,000292,_ZN9SpawnDataC_gen2 0x000000710035cbe8,U,000072,_ZN9SpawnDataC_gen3 @@ -24486,7 +24486,7 @@ Address,Quality,Size,Name 0x000000710036e5c8,U,000012,_ZN9StringTag11getAsStringEv 0x000000710036e5d4,U,000232, 0x000000710036e6bc,U,000068,_ZN17StrongholdFeatureC_gen -0x000000710036e700,U,000108,_ZN16StructureFeatureC_gen +0x000000710036e700,O,000108,_ZN16StructureFeatureC2Ev 0x000000710036e76c,U,000272,_ZN17StrongholdFeatureC_gen2 0x000000710036e87c,U,000128,_ZN17StrongholdFeatureD2Ev 0x000000710036e8fc,U,000056, @@ -24497,16 +24497,16 @@ Address,Quality,Size,Name 0x000000710036ed18,U,000088,distSqr_vec3i 0x000000710036ed70,U,000192,vtbl_71010C4E18_func_12 0x000000710036ee30,U,000104, -0x000000710036ee98,U,000184,vtbl_71010C4E18_func_9 +0x000000710036ee98,U,000184,_ZN17StrongholdFeature31getGuesstimatedFeaturePositionsEv 0x000000710036ef50,U,000172,vtbl_71010C4E18_func_13 -0x000000710036effc,U,000008, +0x000000710036effc,O,000008,_ZN14StructureStart9getPiecesEv 0x000000710036f004,U,000048,_ZN17StrongholdFeature15StrongholdStartC_gen -0x000000710036f034,U,000036,_ZN14StructureStartC_gen +0x000000710036f034,O,000036,_ZN14StructureStartC2Ev 0x000000710036f058,U,000384,_ZN17StrongholdFeature15StrongholdStartC_gen2 -0x000000710036f1d8,U,000040,_ZN14StructureStartC_gen2 +0x000000710036f1d8,O,000040,_ZN14StructureStartC2Eii 0x000000710036f200,U,000624, -0x000000710036f470,U,000108, -0x000000710036f4dc,U,000164, +0x000000710036f470,O,000108,_ZN14StructureStart20calculateBoundingBoxEv +0x000000710036f4dc,O,000164,_ZN14StructureStart17moveBelowSeaLevelEP5LevelR6Randomi 0x000000710036f580,U,000004, 0x000000710036f584,U,000916, 0x000000710036f918,U,000092, @@ -24547,22 +24547,22 @@ Address,Quality,Size,Name 0x0000007100370b0c,U,000384, 0x0000007100370c8c,U,000552, 0x0000007100370eb4,U,000052,_ZN16StrongholdPieces15StrongholdPieceC_gen -0x0000007100370ee8,U,000068,_ZN14StructurePieceC_gen +0x0000007100370ee8,O,000068,_ZN14StructurePieceC2Ev 0x0000007100370f2c,U,000052,_ZN16StrongholdPieces15StrongholdPieceC_gen2 -0x0000007100370f60,U,000072,_ZN14StructurePieceC_gen2 +0x0000007100370f60,O,000072,_ZN14StructurePieceC2Ei 0x0000007100370fa8,U,000024, 0x0000007100370fc0,U,000048, 0x0000007100370ff0,U,001876, 0x0000007100371744,U,000060, 0x0000007100371780,U,000332, -0x00000071003718cc,U,000008, +0x00000071003718cc,O,000008,_ZN14StructurePiece14getOrientationEv 0x00000071003718d4,U,000008, 0x00000071003718dc,U,000296, 0x0000007100371a04,U,000296, 0x0000007100371b2c,U,000212, 0x0000007100371c00,U,000052,_ZN16StrongholdPieces14FillerCorridorC_gen 0x0000007100371c34,U,000136,_ZN16StrongholdPieces14FillerCorridorC_gen2 -0x0000007100371cbc,U,000204, +0x0000007100371cbc,O,000204,_ZN14StructurePiece14setOrientationEPK9Direction 0x0000007100371d88,U,000052, 0x0000007100371dbc,U,000056, 0x0000007100371df4,U,000128, @@ -24577,7 +24577,7 @@ Address,Quality,Size,Name 0x0000007100372700,U,001236, 0x0000007100372bd4,U,000072,_ZN16StrongholdPieces10StartPieceC_gen 0x0000007100372c1c,U,000032, -0x0000007100372c3c,U,000080, +0x0000007100372c3c,O,000080,_ZN14StructurePiece18getLocatorPositionEv 0x0000007100372c8c,U,000048,_ZN16StrongholdPieces8StraightC_gen 0x0000007100372cbc,U,000144,_ZN16StrongholdPieces8StraightC_gen2 0x0000007100372d4c,U,000072, @@ -24590,10 +24590,10 @@ Address,Quality,Size,Name 0x000000710037321c,U,000060, 0x0000007100373258,U,000012, 0x0000007100373264,U,001016, -0x000000710037365c,U,000132, -0x00000071003736e0,U,000056, -0x0000007100373718,U,000132, -0x000000710037379c,U,000012, +0x000000710037365c,O,000132,_ZN14StructurePiece9getWorldXEii +0x00000071003736e0,O,000056,_ZN14StructurePiece9getWorldYEi +0x0000007100373718,O,000132,_ZN14StructurePiece9getWorldZEii +0x000000710037379c,O,000012,_ZN14StructurePiece8setDirtyEv 0x00000071003737a8,U,000048,_ZN16StrongholdPieces18StraightStairsDownC_gen 0x00000071003737d8,U,000096,_ZN16StrongholdPieces18StraightStairsDownC_gen2 0x0000007100373838,U,000012, @@ -24641,26 +24641,26 @@ Address,Quality,Size,Name 0x0000007100377e04,U,000004,_ZN14StructureBlock14spawnResourcesEP5LevelRK8BlockPosPK10BlockStatefi 0x0000007100377e08,U,000008,_ZN14StructureBlock19mayReplaceWithPlaceEP11LevelSourceRK8BlockPos 0x0000007100377e10,U,000004, -0x0000007100377e14,U,000036,_ZN16StructureFeatureD0Ev -0x0000007100377e38,U,000296,vtbl_71010C6548_func_3 +0x0000007100377e14,O,000036,_ZN16StructureFeatureD0Ev +0x0000007100377e38,O,000296,_ZN16StructureFeature10addFeatureEP5LeveliiiiP11ChunkPrimer 0x0000007100377f60,U,000556, -0x000000710037818c,U,000400,vtbl_71010C4E18_func_5 -0x000000710037831c,U,000008, -0x0000007100378324,U,000008, -0x000000710037832c,U,000008, -0x0000007100378334,U,000008, -0x000000710037833c,U,000224,vtbl_71010C4E18_func_6 -0x000000710037841c,U,000084,vtbl_71010C4E18_func_7 -0x0000007100378470,U,000220, -0x000000710037854c,U,000140,isInsideBoundingFeature__16StructureFeatureFP5LevelRC8BlockPos -0x00000071003785d8,U,000008, -0x00000071003785e0,U,000604,vtbl_71010C4E18_func_10 -0x000000710037883c,U,000008, -0x0000007100378844,U,000272, -0x0000007100378954,U,000120,vtbl_71010C4E18_func_11 -0x00000071003789cc,U,000096, -0x0000007100378a2c,U,000008, -0x0000007100378a34,U,001032, +0x000000710037818c,O,000400,_ZN16StructureFeature11postProcessEP5LevelR6RandomP8ChunkPos +0x000000710037831c,O,000008,_ZN14StructureStart14getBoundingBoxEv +0x0000007100378324,O,000008,_ZN14StructureStart7isDirtyEv +0x000000710037832c,O,000008,_ZN14StructureStart9getChunkXEv +0x0000007100378334,O,000008,_ZN14StructureStart9getChunkZEv +0x000000710037833c,O,000224,_ZN16StructureFeature14isIntersectionEii +0x000000710037841c,O,000084,_ZN16StructureFeature15isInsideFeatureERK8BlockPos +0x0000007100378470,M,000220,_ZN16StructureFeature14getStructureAtERK8BlockPos +0x000000710037854c,O,000140,_ZN16StructureFeature23isInsideBoundingFeatureEP5LevelRK8BlockPos +0x00000071003785d8,O,000008,_ZN16StructureFeature31getGuesstimatedFeaturePositionsEv +0x00000071003785e0,M,000604,_ZN16StructureFeature16restoreSavedDataEP5Level +0x000000710037883c,O,000008,_ZN25StructureFeatureSavedData10getFullTagEv +0x0000007100378844,U,000272,_ZN18StructureFeatureIO15loadStaticStartEP12ByteArrayTagP5Level +0x0000007100378954,O,000120,_ZN16StructureFeature11saveFeatureEiiP14StructureStart +0x00000071003789cc,O,000096,_ZN25StructureFeatureSavedData13putFeatureTagE15arrayWithLengthIhEii +0x0000007100378a2c,O,000008,_ZN14StructureStart10clearDirtyEv +0x0000007100378a34,M,001032,_ZN16StructureFeature35findNearestFeaturePositionBySpacingEP5LevelPS_RK8BlockPosiiibib 0x0000007100378e3c,U,000004, 0x0000007100378e40,U,000004, 0x0000007100378e44,U,000004, @@ -24679,71 +24679,71 @@ Address,Quality,Size,Name 0x00000071003798b8,U,000916, 0x0000007100379c4c,U,000096, 0x0000007100379cac,U,000016, -0x0000007100379cbc,U,000128, -0x0000007100379d3c,U,000128, -0x0000007100379dbc,U,000144, -0x0000007100379e4c,U,000068,_ZN25StructureFeatureSavedDataC2ERKNSt3__112basic_stringIwNS0_11char_traitsIwEENS0_9allocatorIwEEEE -0x0000007100379e90,U,000068,_ZN25StructureFeatureSavedDataD2Ev -0x0000007100379ed4,U,000036,_ZN25StructureFeatureSavedDataD0Ev -0x0000007100379ef8,U,000116, -0x0000007100379f6c,U,000068, -0x0000007100379fb0,U,000332, -0x000000710037a0fc,U,000004,_ZN16StructureManager10staticCtorEv -0x000000710037a100,U,000040,_ZN16StructureManagerC_gen -0x000000710037a128,U,000088,_ZN16StructureManagerD2Ev -0x000000710037a180,U,000036,_ZN16StructureManagerD0Ev -0x000000710037a1a4,U,000092, -0x000000710037a200,U,000140, +0x0000007100379cbc,U,000128,_ZN18StructureFeatureIO11getEncodeIdEP14StructureStart +0x0000007100379d3c,U,000128,_ZN18StructureFeatureIO11getEncodeIdEP14StructurePiece +0x0000007100379dbc,U,000144,_ZN18StructureFeatureIO15loadStaticPieceEP15DataInputStreamP5Level +0x0000007100379e4c,O,000068,_ZN25StructureFeatureSavedDataC2ERKNSt3__112basic_stringIwNS0_11char_traitsIwEENS0_9allocatorIwEEEE +0x0000007100379e90,O,000068,_ZN25StructureFeatureSavedDataD2Ev +0x0000007100379ed4,O,000036,_ZN25StructureFeatureSavedDataD0Ev +0x0000007100379ef8,O,000116,_ZN25StructureFeatureSavedData4loadEP11CompoundTag +0x0000007100379f6c,O,000068,_ZN25StructureFeatureSavedData4saveEP11CompoundTag +0x0000007100379fb0,O,000332,_ZN25StructureFeatureSavedData18createFeatureTagIdEii +0x000000710037a0fc,O,000004,_ZN16StructureManager10staticCtorEv +0x000000710037a100,O,000040,_ZN16StructureManagerC1EP14DataFixerUpper +0x000000710037a128,M,000088,_ZN16StructureManagerD2Ev +0x000000710037a180,O,000036,_ZN16StructureManagerD0Ev +0x000000710037a1a4,M,000092,_ZN16StructureManager11getOrCreateEi +0x000000710037a200,M,000140,_ZN16StructureManager3getEi 0x000000710037a28c,U,000556, -0x000000710037a4b8,U,000200, -0x000000710037a580,U,000264, -0x000000710037a688,U,000184, -0x000000710037a740,U,001448, +0x000000710037a4b8,O,000200,_ZN16StructureManager11loadArchiveEi +0x000000710037a580,M,000264,_ZN16StructureManager14getArchivePathEi +0x000000710037a688,M,000184,_ZN16StructureManager14loadFromStreamEiP11InputStream +0x000000710037a740,M,001448,_ZN17StructureTemplate7loadTagEP11CompoundTag 0x000000710037ace8,U,000064,_ZN14StructurePiece13BlockSelectorC_gen 0x000000710037ad28,U,000004,_ZN14StructurePiece13BlockSelectorD0Ev 0x000000710037ad2c,U,000004, -0x000000710037ad30,U,000008, -0x000000710037ad38,U,000036, -0x000000710037ad5c,U,000048, -0x000000710037ad8c,U,000044, -0x000000710037adb8,U,000176, -0x000000710037ae68,U,000212, -0x000000710037af3c,U,000004, -0x000000710037af40,U,000008, -0x000000710037af48,U,000008, -0x000000710037af50,U,000344, -0x000000710037b0a8,U,000208, -0x000000710037b178,U,000200, -0x000000710037b240,U,000232, -0x000000710037b328,U,000596, -0x000000710037b57c,U,000080, -0x000000710037b5cc,U,000612, -0x000000710037b830,U,000080, -0x000000710037b880,U,000700, -0x000000710037bb3c,U,000168, -0x000000710037bbe4,U,000588, -0x000000710037be30,U,000792, -0x000000710037c148,U,000296, -0x000000710037c270,U,000168, -0x000000710037c318,U,000372, -0x000000710037c48c,U,000176, +0x000000710037ad30,O,000008,_ZN14StructurePiece13BlockSelector7getNextEv +0x000000710037ad38,O,000036,_ZN14StructurePieceD0Ev +0x000000710037ad5c,O,000048,_ZN14StructurePiece14setBoundingBoxEP11BoundingBox +0x000000710037ad8c,O,000044,_ZN14StructurePiece9createTagEv +0x000000710037adb8,O,000176,_ZN14StructurePiece5writeEP16DataOutputStream +0x000000710037ae68,O,000212,_ZN14StructurePiece4loadEP5LevelP15DataInputStream +0x000000710037af3c,O,000004,_ZN14StructurePiece11addChildrenEPS_PNSt3__16vectorIS0_NS1_9allocatorIS0_EEEER6Random +0x000000710037af40,O,000008,_ZN14StructurePiece14getBoundingBoxEv +0x000000710037af48,O,000008,_ZN14StructurePiece11setGenDepthEi +0x000000710037af50,O,000344,_ZN14StructurePiece10placeBlockEP5LevelPK10BlockStateiiiP11BoundingBox +0x000000710037b0a8,O,000208,_ZN14StructurePiece8getBlockEP5LeveliiiP11BoundingBox +0x000000710037b178,O,000200,_ZN14StructurePiece16getSkyBrightnessEP5LeveliiiP11BoundingBox +0x000000710037b240,O,000232,_ZN14StructurePiece14generateAirBoxEP5LevelP11BoundingBoxiiiiii +0x000000710037b328,O,000596,_ZN14StructurePiece11generateBoxEP5LevelP11BoundingBoxiiiiiiPK10BlockStateS6_b +0x000000710037b57c,O,000080,_ZN14StructurePiece11generateBoxEP5LevelP11BoundingBoxS3_PK10BlockStateS6_b +0x000000710037b5cc,O,000612,_ZN14StructurePiece11generateBoxEP5LevelP11BoundingBoxiiiiiibR6RandomPNS_13BlockSelectorE +0x000000710037b830,O,000080,_ZN14StructurePiece11generateBoxEP5LevelP11BoundingBoxS3_bR6RandomPNS_13BlockSelectorE +0x000000710037b880,O,000700,_ZN14StructurePiece16generateMaybeBoxEP5LevelP11BoundingBoxR6RandomfiiiiiiPK10BlockStateS8_bi +0x000000710037bb3c,O,000168,_ZN14StructurePiece18maybeGenerateBlockEP5LevelP11BoundingBoxR6RandomfiiiPK10BlockState +0x000000710037bbe4,O,000588,_ZN14StructurePiece23generateUpperHalfSphereEP5LevelP11BoundingBoxiiiiiiPK10BlockStateb +0x000000710037be30,O,000792,_ZN14StructurePiece18generateFullSphereEP5LevelP11BoundingBoxiiiiPK10BlockStateS6_b +0x000000710037c148,O,000296,_ZN14StructurePiece19generateAirColumnUpEP5LeveliiiP11BoundingBox +0x000000710037c270,O,000168,_ZN14StructurePiece16generateAirBoxUpEP5LeveliiiiiP11BoundingBox +0x000000710037c318,O,000372,_ZN14StructurePiece14fillColumnDownEP5LevelPK10BlockStateiiiP11BoundingBox +0x000000710037c48c,O,000176,_ZN14StructurePiece11fillBoxDownEP5LevelPK10BlockStateiiiiiP11BoundingBox 0x000000710037c53c,U,000208, 0x000000710037c60c,U,000332, 0x000000710037c758,U,000424, -0x000000710037c900,U,000244, +0x000000710037c900,O,000244,_ZN14StructurePiece25addStructurePieceSaveDataEP16DataOutputStreamNSt3__16vectorIbNS2_9allocatorIbEEEES6_NS3_IiNS4_IiEEEES8_ 0x000000710037c9f4,U,000096, -0x000000710037ca54,U,000240, -0x000000710037cb44,U,000284, -0x000000710037cc60,U,000244, -0x000000710037cd54,U,000204,_ZNSt3__115basic_stringbufIwNS_11char_traitsIwEENS_9allocatorIwEEEC_gen15 -0x000000710037ce20,U,000264, -0x000000710037cf28,U,000272, +0x000000710037ca54,O,000240,_ZN14StructurePiece26readStructurePieceSaveDataEP15DataInputStreamRNSt3__16vectorIbNS2_9allocatorIbEEEES7_RNS3_IiNS4_IiEEEESA_ +0x000000710037cb44,O,000284,_ZN14StructurePiece15addBoolSaveDataEP16DataOutputStreamNSt3__16vectorIbNS2_9allocatorIbEEEE +0x000000710037cc60,O,000244,_ZN14StructurePiece16readBoolSaveDataEP15DataInputStream +0x000000710037cd54,O,000204,_Z11_fromStringIbET_RKNSt3__112basic_stringIwNS1_11char_traitsIwEENS1_9allocatorIwEEEE +0x000000710037ce20,O,000264,_ZN14StructurePiece14addIntSaveDataEP16DataOutputStreamNSt3__16vectorIiNS2_9allocatorIiEEEE +0x000000710037cf28,O,000272,_ZN14StructurePiece15readIntSaveDataEP15DataInputStream 0x000000710037d038,U,000256, -0x000000710037d138,U,000008, -0x000000710037d140,U,000008, -0x000000710037d148,U,000008, -0x000000710037d150,U,000008, -0x000000710037d158,U,000008, +0x000000710037d138,O,000008,_ZN14StructurePiece4moveEiii +0x000000710037d140,O,000008,_ZN14StructurePiece11getRotationEv +0x000000710037d148,O,000008,_ZN14StructurePiece9getMirrorEv +0x000000710037d150,O,000008,_ZN14StructurePiece10clearDirtyEv +0x000000710037d158,O,000008,_ZN14StructurePiece7isDirtyEv 0x000000710037d160,U,000088,_ZN22StructurePlaceSettingsC_gen 0x000000710037d1b8,U,000076,_ZN22StructurePlaceSettingsC_gen2 0x000000710037d204,U,000036,_ZN22StructurePlaceSettingsD0Ev @@ -24769,25 +24769,25 @@ Address,Quality,Size,Name 0x000000710037d71c,U,000008, 0x000000710037d724,U,000008, 0x000000710037d72c,U,004432, -0x000000710037e87c,U,000036,_ZN14StructureStartD0Ev -0x000000710037e8a0,U,000260, -0x000000710037e9a4,U,000012, -0x000000710037e9b0,U,000264, -0x000000710037eab8,U,000004, -0x000000710037eabc,U,000256, -0x000000710037ebbc,U,000004, -0x000000710037ebc0,U,000168, -0x000000710037ec68,U,000008, -0x000000710037ec70,U,000008, -0x000000710037ec78,U,000004, -0x000000710037ec7c,U,000112,_ZN17StructureTemplateC_gen -0x000000710037ecec,U,000224,_ZN17StructureTemplateD2Ev -0x000000710037edcc,U,000024, -0x000000710037ede4,U,000068, +0x000000710037e87c,O,000036,_ZN14StructureStartD0Ev +0x000000710037e8a0,O,000260,_ZN14StructureStart11postProcessEP5LevelR6RandomP11BoundingBox +0x000000710037e9a4,O,000012,_ZN14StructureStart8setDirtyEv +0x000000710037e9b0,O,000264,_ZN14StructureStart9createTagEii +0x000000710037eab8,O,000004,_ZN14StructureStart21addAdditionalSaveDataEP16DataOutputStream +0x000000710037eabc,O,000256,_ZN14StructureStart4loadEP5LevelP15DataInputStream +0x000000710037ebbc,O,000004,_ZN14StructureStart22readAdditionalSaveDataEP15DataInputStream +0x000000710037ebc0,O,000168,_ZN14StructureStart17moveInsideHeightsEP5LevelR6Randomii +0x000000710037ec68,O,000008,_ZN14StructureStart7isValidEv +0x000000710037ec70,O,000008,_ZN14StructureStart21isValidForPostProcessEP8ChunkPos +0x000000710037ec78,O,000004,_ZN14StructureStart19notifyPostProcessAtEP8ChunkPos +0x000000710037ec7c,O,000112,_ZN17StructureTemplateC1Ev +0x000000710037ecec,M,000224,_ZN17StructureTemplateD2Ev +0x000000710037edcc,O,000024,_ZN17StructureTemplate9BlockInfoD2Ev +0x000000710037ede4,O,000068,_ZN17StructureTemplate10EntityInfoD2Ev 0x000000710037ee28,U,000056, 0x000000710037ee60,U,000056, -0x000000710037ee98,U,000036,_ZN17StructureTemplateD0Ev -0x000000710037eebc,U,000016, +0x000000710037ee98,O,000036,_ZN17StructureTemplateD0Ev +0x000000710037eebc,O,000016,_ZN17StructureTemplate7getSizeEv 0x000000710037eecc,U,000780, 0x000000710037f1d8,U,000076, 0x000000710037f224,U,000008, @@ -24799,14 +24799,14 @@ Address,Quality,Size,Name 0x000000710037fc50,U,000684, 0x000000710037fefc,U,000252, 0x000000710037fff8,U,000024,_ZN4Vec33addEddd -0x0000007100380010,U,000148, +0x0000007100380010,M,000148,_ZN17StructureTemplate7getSizeEP8Rotation 0x00000071003800a4,U,000140, 0x0000007100380130,U,000240, 0x0000007100380220,U,000060,_ZN17StructureTemplate10addWalkersEP14DataFixerUpper 0x000000710038025c,U,000048,_ZN19AnonymousDataWalkerC_gen -0x000000710038028c,U,000072, +0x000000710038028c,O,000072,_ZN17StructureTemplate9BlockInfoC1ERK8BlockPosPK10BlockStateP11CompoundTag 0x00000071003802d4,U,000084,_ZN4Vec312newPermanentEddd -0x0000007100380328,U,000080, +0x0000007100380328,O,000080,_ZN17StructureTemplate10EntityInfoC1EP4Vec3RK8BlockPosP11CompoundTag 0x0000007100380378,U,000064,_ZN18StructureVoidBlockC_gen 0x00000071003803b8,U,000008,_ZN18StructureVoidBlock14getRenderShapeEPK10BlockState 0x00000071003803c0,U,000008,_ZN18StructureVoidBlock11getClipAABBEPK10BlockStateP11LevelSourceRK8BlockPos @@ -26779,7 +26779,7 @@ Address,Quality,Size,Name 0x00000071003d8d68,U,000008, 0x00000071003d8d70,U,000036,_ZN16StrongholdPieces12RoomCrossingD0Ev 0x00000071003d8d94,U,000008, -0x00000071003d8d9c,U,000032,_ZN14StructurePieceC_gen3 +0x00000071003d8d9c,O,000032,_ZN14StructurePieceD2Ev 0x00000071003d8dbc,U,000036,_ZN16StrongholdPieces10PrisonHallD0Ev 0x00000071003d8de0,U,000008, 0x00000071003d8de8,U,000036,_ZN16StrongholdPieces7LibraryD0Ev @@ -26882,7 +26882,7 @@ Address,Quality,Size,Name 0x00000071003d9990,U,000036,_ZN3Vex17VexRandomMoveGoalD0Ev 0x00000071003d99b4,U,000036,_ZN3Vex22VexCopyOwnerTargetGoalD0Ev 0x00000071003d99d8,U,000036,_ZN14VillageFeatureD0Ev -0x00000071003d99fc,U,000132,_ZN14StructureStartC_gen3 +0x00000071003d99fc,O,000132,_ZN14StructureStartD2Ev 0x00000071003d9a80,U,000036,_ZN14VillageFeature12VillageStartD0Ev 0x00000071003d9aa4,U,000008, 0x00000071003d9aac,U,000004,_ZN13VillagePieces19CobbleStoneSelectorD0Ev @@ -26983,7 +26983,7 @@ Address,Quality,Size,Name 0x00000071003da4f0,U,000008, 0x00000071003da4f8,U,000036,_ZN4Wolf19WolfAvoidEntityGoalD0Ev 0x00000071003da51c,U,000036,_ZN15WoodButtonBlockD0Ev -0x00000071003da540,U,000112,_ZN16StructureFeatureC_gen2 +0x00000071003da540,O,000112,_ZN16StructureFeatureD2Ev 0x00000071003da5b0,U,000036,_ZN22WoodlandMansionFeatureD0Ev 0x00000071003da5d4,U,000036,_ZN22WoodlandMansionFeature20WoodlandMansionStartD0Ev 0x00000071003da5f8,U,000008, @@ -41914,7 +41914,7 @@ Address,Quality,Size,Name 0x00000071006910c8,O,000004,_Z16PIXEndNamedEventv 0x00000071006910cc,U,000044,_Z22PIXSetMarkerDeprecatedfPKcz 0x00000071006910f8,U,000004,_Z7XMemCpyPvPKvj -0x00000071006910fc,U,000004, +0x00000071006910fc,O,000004,_Z17sparseLightMemSetPvim 0x0000007100691100,O,000004,_Z10XMemSet128Pvim 0x0000007100691104,O,000004,_Z14XPhysicalAllocmmmj 0x0000007100691108,O,000004,_Z13XPhysicalFreePv diff --git a/src/4JLibraries_Source/NX/Render/C4JRender.h b/src/4JLibraries_Source/NX/Render/C4JRender.h index 46ba7dc4..f40622f1 100644 --- a/src/4JLibraries_Source/NX/Render/C4JRender.h +++ b/src/4JLibraries_Source/NX/Render/C4JRender.h @@ -1,6 +1,6 @@ #pragma once -#include "arm_neon.h" +#include class _XSOCIAL_PREVIEWIMAGE; class ImageFileBuffer; @@ -41,7 +41,7 @@ class C4JRender { virtual void MatrixPop() = 0; virtual void MatrixPush() = 0; virtual float32x4_t MatrixMult(float*) = 0; - virtual void MatrixGet(int) = 0; + virtual float* MatrixGet(int) = 0; virtual void Set_matrixDirty() = 0; virtual void Initialise() = 0; virtual void InitialiseContext() = 0; diff --git a/src/4JLibraries_Source/NX/Render/RendererCore.cpp b/src/4JLibraries_Source/NX/Render/RendererCore.cpp index 44bcdeea..8d540923 100644 --- a/src/4JLibraries_Source/NX/Render/RendererCore.cpp +++ b/src/4JLibraries_Source/NX/Render/RendererCore.cpp @@ -15,12 +15,66 @@ #include __thread Renderer::Context* sContext; +static __thread MatrixStruct sMatrixResult; + +extern "C" Renderer::Context* Renderer__getContext() { + return sContext; +} + +static const MatrixStruct identityMatrix = { + {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}}; unsigned int textureWidths[6] = {1920, 1280, 512, 256, 128, 64}; unsigned int textureHeights[6] = {1080, 720, 512, 256, 128, 64}; nn::os::MutexType someRendererMutex; -Renderer::Context::Context(Renderer*, bool a2) { - this->m_filler[0] = a2; +// NON_MATCHING: the original also creates an unused temporary state object. +Renderer::Context::Context(Renderer*, bool creationFlag) { + m_ptr1DE0 = nullptr; + m_ptr1DE8 = nullptr; + m_ptr1DF0 = nullptr; + m_creationFlag = creationFlag; + // Only the base entries are initialized; stack storage and matrix-dirty flags are preserved. + m_matrixDepth[0] = 0; + m_matrixStacks[0][0] = identityMatrix; + m_matrixDepth[1] = 0; + m_matrixDepth[2] = 0; + m_matrixDepth[3] = 0; + m_matrixMode = 0; + m_matrixStacks[1][0] = identityMatrix; + m_matrixStacks[2][0] = identityMatrix; + m_matrixStacks[3][0] = identityMatrix; + m_byte1040 = false; + m_float1044 = 1.0f; + m_lightingEnabled = false; + for (int i = 0; i < 4; i++) { + m_textureBindings[i] = 0; + m_textureBindingDirty[i] = false; + m_textureFlags[i] = false; + } + m_fogEnabled = false; + m_byte1DD8 = false; + m_commandBuffer = nullptr; + m_dword1CE0 = -1; + memset(m_data1CE8, 0, sizeof(m_data1CE8)); + m_byte1CDC = false; + m_byte1D38 = false; + m_fogDirty = false; + m_byte1CE4 = false; + m_textureScaleUI[0] = 1.0f; + m_textureScaleUI[1] = 1.0f; + m_textureScaleUI[2] = 0.0f; + m_textureScaleUI[3] = 0.0f; + nvnBlendStateSetDefaults(&m_blendState); + nvnDepthStencilStateSetDefaults(&m_depthStencilState); + nvnDepthStencilStateSetDepthTestEnable(&m_depthStencilState, true); + nvnDepthStencilStateSetDepthFunc(&m_depthStencilState, NVN_DEPTH_FUNC_LEQUAL); + nvnColorStateSetDefaults(&m_colorState); + nvnPolygonStateSetDefaults(&m_polygonState); + nvnChannelMaskStateSetDefaults(&m_channelMaskState); + m_depthFunc = NVN_DEPTH_FUNC_LEQUAL; + for (int i = 0; i < 6; i++) + m_stateDirty[i] = true; + m_dword1CC0 = 0; } Renderer::Renderer() : C4JRender() { @@ -429,3 +483,115 @@ float32x4_t Renderer::MatrixMult(float* matrix) { void Renderer::UpdateGamma(unsigned short gamma) { this->m_gammaIntensity = gamma; } + +void Renderer::MatrixMode(int mode) { + Renderer__getContext()->m_matrixMode = mode; +} + +void Renderer::MatrixSetIdentity() { + Context* context = Renderer__getContext(); + int mode = context->m_matrixMode; + MatrixStruct& top = context->m_matrixStacks[mode][context->m_matrixDepth[mode]]; + top.m__[0] = identityMatrix.m__[0]; + top.m__[1] = identityMatrix.m__[1]; + top.m__[2] = identityMatrix.m__[2]; + top.m__[3] = identityMatrix.m__[3]; + context->m_matrixDirty[context->m_matrixMode] = true; +} + +float32x4_t Renderer::MultWithStack(MatrixStruct input) { + Context* context = Renderer__getContext(); + int mode = context->m_matrixMode; + MatrixStruct& top = context->m_matrixStacks[mode][context->m_matrixDepth[mode]]; + float32x4_t a = top.m__[0]; + float32x4_t b = top.m__[1]; + float32x4_t c = top.m__[2]; + float32x4_t d = top.m__[3]; + float32x4_t result; + for (int i = 0; i < 4; i++) { + float32x4_t column = vmulq_laneq_f32(a, input.m__[i], 0); + column = vfmaq_laneq_f32(column, b, input.m__[i], 1); + column = vfmaq_laneq_f32(column, c, input.m__[i], 2); + result = vfmaq_laneq_f32(column, d, input.m__[i], 3); + top.m__[i] = result; + } + context->m_matrixDirty[context->m_matrixMode] = true; + return result; +} + +void Renderer::MatrixTranslate(float x, float y, float z) { + MatrixStruct matrix = identityMatrix; + matrix.m__[3] = (float32x4_t){x, y, z, 1.0f}; + MultWithStack(matrix); +} + +void Renderer::MatrixScale(float x, float y, float z) { + MatrixStruct matrix + = {{{x, 0.0f, 0.0f, 0.0f}, {0.0f, y, 0.0f, 0.0f}, {0.0f, 0.0f, z, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}}; + MultWithStack(matrix); +} + +void Renderer::MatrixOrthogonal(float left, float right, float bottom, float top, float near, float far) { + float x = 1.0f / (right - left); + float y = 1.0f / (top - bottom); + float z = -1.0f / (far - near); + MatrixStruct matrix = {{{x + x, 0.0f, 0.0f, 0.0f}, + {0.0f, y + y, 0.0f, 0.0f}, + {0.0f, 0.0f, z, 0.0f}, + {-(left + right) * x, -(bottom + top) * y, z * near, 1.0f}}}; + MultWithStack(matrix); +} + +void Renderer::MatrixPush() { + Context* context = Renderer__getContext(); + int mode = context->m_matrixMode; + MatrixStruct* top = &context->m_matrixStacks[mode][context->m_matrixDepth[mode]]; + memcpy(top + 1, top, sizeof(MatrixStruct)); + context->m_matrixDepth[context->m_matrixMode]++; +} + +void Renderer::MatrixPop() { + Context* context = Renderer__getContext(); + context->m_matrixDepth[context->m_matrixMode]--; + context->m_matrixDirty[context->m_matrixMode] = true; +} + +float* Renderer::MatrixGet(int mode) { + Context* context = Renderer__getContext(); + MatrixStruct& top = context->m_matrixStacks[mode][context->m_matrixDepth[mode]]; + float32x4_t a = top.m__[0]; + float32x4_t b = top.m__[1]; + float32x4_t c = top.m__[2]; + float32x4_t d = top.m__[3]; + sMatrixResult.m__[0] = a; + sMatrixResult.m__[1] = b; + sMatrixResult.m__[2] = c; + sMatrixResult.m__[3] = d; + return reinterpret_cast(&sMatrixResult); +} + +void Renderer::Set_matrixDirty() { + Context* context = Renderer__getContext(); + context->m_matrixStacks[0][0].m__[0] = identityMatrix.m__[0]; + context->m_matrixStacks[0][0].m__[1] = identityMatrix.m__[1]; + context->m_matrixStacks[0][0].m__[2] = identityMatrix.m__[2]; + context->m_matrixStacks[0][0].m__[3] = identityMatrix.m__[3]; + context->m_matrixStacks[1][0].m__[0] = identityMatrix.m__[0]; + context->m_matrixStacks[1][0].m__[1] = identityMatrix.m__[1]; + context->m_matrixStacks[1][0].m__[2] = identityMatrix.m__[2]; + context->m_matrixStacks[1][0].m__[3] = identityMatrix.m__[3]; + context->m_matrixStacks[3][0].m__[0] = identityMatrix.m__[0]; + context->m_matrixStacks[3][0].m__[1] = identityMatrix.m__[1]; + context->m_matrixStacks[3][0].m__[2] = identityMatrix.m__[2]; + context->m_matrixStacks[3][0].m__[3] = identityMatrix.m__[3]; + context->m_matrixStacks[2][0].m__[0] = identityMatrix.m__[0]; + context->m_matrixStacks[2][0].m__[1] = identityMatrix.m__[1]; + context->m_matrixStacks[2][0].m__[2] = identityMatrix.m__[2]; + context->m_matrixStacks[2][0].m__[3] = identityMatrix.m__[3]; + context->m_matrixDirty[0] = true; + context->m_matrixDirty[1] = true; + context->m_matrixDirty[3] = true; + context->m_matrixDirty[2] = true; + m_dword29C0 = -1; + m_dword29C4 = -1; +} diff --git a/src/4JLibraries_Source/NX/Render/RendererCore.h b/src/4JLibraries_Source/NX/Render/RendererCore.h index c69dea81..81c408af 100644 --- a/src/4JLibraries_Source/NX/Render/RendererCore.h +++ b/src/4JLibraries_Source/NX/Render/RendererCore.h @@ -34,7 +34,49 @@ class Renderer : public C4JRender { public: Context(Renderer*, bool); - char m_filler[0x1F30]; + char m_gap0[0x10]; + MatrixStruct m_matrixStacks[4][16]; + bool m_matrixDirty[4]; + int m_matrixDepth[4]; + int m_matrixMode; + int m_textureBindings[4]; + bool m_textureBindingDirty[4]; + bool m_textureFlags[4]; + bool m_byte1040; + float m_float1044; + NVNblendState m_blendState; + NVNdepthStencilState m_depthStencilState; + NVNcolorState m_colorState; + NVNpolygonState m_polygonState; + NVNchannelMaskState m_channelMaskState; + int m_depthFunc; + bool m_stateDirty[6]; + char m_gap106E[0xC52]; + int m_dword1CC0; + bool m_fogEnabled; + char m_gap1CC5[0x13]; + bool m_fogDirty; + bool m_lightingEnabled; + char m_gap1CDA[2]; + bool m_byte1CDC; + char m_gap1CDD[3]; + int m_dword1CE0; + bool m_byte1CE4; + bool m_creationFlag; + char m_gap1CE6[2]; + char m_data1CE8[0x50]; + bool m_byte1D38; + char m_gap1D39[0x87]; + void* m_commandBuffer; + char m_gap1DC8[0x10]; + bool m_byte1DD8; + char m_gap1DD9[7]; + void* m_ptr1DE0; + void* m_ptr1DE8; + void* m_ptr1DF0; + char m_gap1DF8[0x28]; + float m_textureScaleUI[4]; + char m_gap1E30[0x100]; }; Renderer(); @@ -58,8 +100,7 @@ class Renderer : public C4JRender { virtual void Tick(); virtual void UpdateGamma(unsigned short gamma); - // see OpenGL for more info (modes starts from 0 and ends in 2, they are in the same order as they are in - // OpenGL) + // NX maintains four independently selected matrix stacks, each with sixteen entries. virtual void MatrixMode(int); virtual void MatrixSetIdentity(); virtual void MatrixTranslate(float, float, float); @@ -70,7 +111,7 @@ class Renderer : public C4JRender { virtual void MatrixPop(); virtual void MatrixPush(); virtual float32x4_t MatrixMult(float* matrix); - virtual void MatrixGet(int); + virtual float* MatrixGet(int); virtual void Set_matrixDirty(); // unused params were probably used in Xbox One virtual void Initialise(); @@ -343,3 +384,13 @@ class Renderer : public C4JRender { int m_elo; int m_elo22; }; + +static_assert(sizeof(MatrixStruct) == 0x40, "Matrix size"); +static_assert(alignof(MatrixStruct) == 0x10, "Matrix alignment"); +static_assert(sizeof(Renderer::Context) == 0x1F30, "Renderer context size"); +static_assert(offsetof(Renderer::Context, m_matrixStacks) == 0x10, "Matrix stack offset"); +static_assert(offsetof(Renderer::Context, m_matrixDirty) == 0x1010, "Matrix dirty offset"); +static_assert(offsetof(Renderer::Context, m_matrixMode) == 0x1024, "Matrix mode offset"); +static_assert(offsetof(Renderer::Context, m_blendState) == 0x1048, "Blend state offset"); +static_assert(offsetof(Renderer::Context, m_creationFlag) == 0x1CE5, "Context flag offset"); +static_assert(offsetof(Renderer::Context, m_textureScaleUI) == 0x1E20, "UI texture scale offset"); diff --git a/src/4JLibraries_Source/XLockFreeStack.h b/src/4JLibraries_Source/XLockFreeStack.h index 303fb5c0..3cc4964e 100644 --- a/src/4JLibraries_Source/XLockFreeStack.h +++ b/src/4JLibraries_Source/XLockFreeStack.h @@ -6,16 +6,18 @@ #include -// wtf is this +// The original implementation serializes a pointer vector with a mutex. template class XLockFreeStack { public: XLockFreeStack(); + ~XLockFreeStack(); void doSomething() {} + void Push(T*); T* Pop(); - std::vector m_vector; + std::vector m_vector; nn::os::MutexType m_mutex; }; diff --git a/src/4JLibraries_Source/fui/fui.cpp b/src/4JLibraries_Source/fui/fui.cpp index 703cd822..18051b8c 100644 --- a/src/4JLibraries_Source/fui/fui.cpp +++ b/src/4JLibraries_Source/fui/fui.cpp @@ -96,7 +96,7 @@ void fui::render(fuiFile* file, float a1, float a2, float a3, float a4, float a5 } void fui::dispatchKeyboardEvent(fuiFile* file, bool state, int c) { - FJ_FuiNode* node = file->m_data.m_fuiSymbol->m_stage; // ??? + FJ_FuiNode* node = file->m_renderNodeStage->m_fuiNodeStage; if (FJ_FuiNode* focus = static_cast(node)->getFocus()) node = focus; @@ -106,7 +106,7 @@ void fui::dispatchKeyboardEvent(fuiFile* file, bool state, int c) { // param names guessed void fui::dispatchMouseMoveEvent(fuiFile* file, float x, float y) { - FJ_FuiNode* node = file->m_data.m_fuiSymbol->m_stage; + FJ_FuiNode* node = file->m_renderNodeStage->m_fuiNodeStage; if (FJ_FuiNode* focus = static_cast(node)->getFocus()) node = focus; diff --git a/src/4JLibraries_Source/fui/fuiFile.h b/src/4JLibraries_Source/fui/fuiFile.h index e234f508..a948ba41 100644 --- a/src/4JLibraries_Source/fui/fuiFile.h +++ b/src/4JLibraries_Source/fui/fuiFile.h @@ -3,6 +3,7 @@ #include "fui/fuiSymbol.h" #include "net/minecraft/world/ArrayWithLength.h" #include "types.h" +#include // Most structs derived from // https://github.com/NessieHax/fui-research-repo/blob/main/DOCUMENTATION.md @@ -46,47 +47,107 @@ struct fuiMatrix { static void mul(const fuiMatrix& lhs, const fuiMatrix& rhs, fuiMatrix& out); }; struct fuiColorTransform { - float m_redMultTerm; - float m_greenMultTerm; - float m_blueMultTerm; - float m_alphaMultTerm; float m_redAddTerm; float m_greenAddTerm; float m_blueAddTerm; float m_alphaAddTerm; + float m_redMultTerm; + float m_greenMultTerm; + float m_blueMultTerm; + float m_alphaMultTerm; }; struct fuiTimeline { int m_symbolIndex; - short m_frameIndex; - short m_frameCount; - short m_actionIndex; - short m_actionCount; + uint16_t m_frameIndex; + uint16_t m_frameCount; + uint16_t m_actionIndex; + uint16_t m_actionCount; fuiRect m_rect; }; -struct fuiTimelineAction; -struct fuiShape; -struct fuiShapeComponent; -struct fuiVert; -struct fuiTimelineFrame; -struct fuiTimelineEvent; -struct timelineEventName; +struct fuiTimelineAction { + uint16_t m_type; + int16_t m_frame; + char m_argument0[64]; + char m_argument1[64]; +}; +struct fuiShape { + int m_symbolIndex; + int m_componentIndex; + int m_componentCount; + fuiRect m_rect; +}; +struct fuiFillStyle { + int m_type; + fuiRGBA m_colour; + int m_bitmapIndex; + fuiMatrix m_matrix; +}; +struct fuiShapeComponent { + fuiFillStyle m_fill; + int m_vertexIndex; + int m_vertexCount; +}; +struct fuiVert { + float m_x, m_y; +}; +struct fuiTimelineFrame { + char m_name[64]; + int m_eventIndex; + int m_eventCount; +}; +struct fuiTimelineEvent { + uint16_t m_type; + uint8_t m_objectType; + uint8_t m_flags; + int16_t m_depth; + int16_t m_objectIndex; + int16_t m_unknown; + int16_t m_nameIndex; + fuiMatrix m_matrix; + fuiColorTransform m_colourTransform; + fuiRGBA m_colour; +}; +struct timelineEventName { + char m_name[64]; +}; struct fuiReference { int m_symbolIndex; char m_name[64]; int m_index; }; -struct fuiEdittext; -struct fuiBitmap; -struct fuiFontName; -struct fuiImportAsset; +struct fuiEdittext { + int m_symbolIndex; + fuiRect m_rect; + int m_fontId; + float m_fontSize; + fuiRGBA m_colour; + int m_flags[6]; + char m_text[256]; +}; +struct fuiBitmap { + int m_symbolIndex; + int m_format; + int m_width; + int m_height; + int m_offset; + int m_size; + int m_alphaOffset; + int m_texture; +}; +struct fuiFontName { + int m_id; + char m_name[256]; +}; +struct fuiImportAsset { + char m_name[64]; +}; class FJ_FuiNode; struct fuiHeader { - bool m_field0; + unsigned char m_signature[8]; int m_contentSize; - int m_field8; - char m_fileName[60]; + char m_fileName[64]; int m_timelineCount; int m_timelineEventNameCount; int m_timelineActionCount; @@ -97,12 +158,11 @@ struct fuiHeader { int m_timelineEventCount; int m_referenceCount; int m_editTextCount; + int m_symbolCount; int m_bitmapCount; int m_imagesSize; - int m_field7C; int m_fontNameCount; int m_importAssetCount; - int m_unk; fuiRect m_stageSize; int m_index; }; @@ -123,7 +183,7 @@ struct fuiData { fuiReference* m_fuiReference; fuiEdittext* m_fuiEdittext; fuiSymbol* m_fuiSymbol; - fuiBitmapFont* m_fuiBitmap; + fuiBitmap* m_fuiBitmap; void* m_imageMaybe; fuiFontName* m_fuiFontName; fuiImportAsset* m_fuiImportAsset; @@ -132,10 +192,10 @@ struct fuiData { struct fuiFile { fuiFile(); ~fuiFile(); - // NOTE: HAD TO CHANGE THE SIGNATURE BECAUSE OF THE METHOD BEING DIFFERENT - // ORIG HAD A CALLBACK METHOD INSTEAD OF DATA + // Retain the recovered symbol's ABI; its third argument is a byte stride, + // despite the old unsigned-char** declaration in the symbol map. static uint64_t addDataRegion(uint a1, uint a2, uchar** ptr, uint64_t* callbackData); - void load(arrayWithLength, int); + bool load(arrayWithLength, int); bool resolveReferences(fuiFile*); void dumpUnresolvedReferences(); void initialiseRenderTexture(fuiBitmap*, bool); @@ -159,3 +219,15 @@ struct fuiFile { void* m_callbackData; void* m_field138; }; + +static_assert(sizeof(fuiHeader) == 0x9c, "FUI header including runtime file index"); +static_assert(offsetof(fuiHeader, m_contentSize) == 8, "FUI content size"); +static_assert(offsetof(fuiHeader, m_stageSize) == 0x88, "FUI stage rectangle"); +static_assert(sizeof(fuiTimeline) == 0x1c && sizeof(fuiTimelineAction) == 0x84); +static_assert(sizeof(fuiShape) == 0x1c && sizeof(fuiShapeComponent) == 0x2c); +static_assert(sizeof(fuiTimelineFrame) == 0x48 && sizeof(fuiTimelineEvent) == 0x48); +static_assert(sizeof(fuiReference) == 0x48 && sizeof(fuiEdittext) == 0x138); +static_assert(sizeof(fuiBitmap) == 0x20 && sizeof(fuiFontName) == 0x104); +static_assert(offsetof(fuiFile, m_data) == 0xa0); +static_assert(offsetof(fuiFile, m_renderNodeStage) == 0x118); +static_assert(offsetof(fuiFile, m_field138) == 0x138); diff --git a/src/4JLibraries_Source/fui/fuiSymbol.h b/src/4JLibraries_Source/fui/fuiSymbol.h index a880d1e0..33e1c08d 100644 --- a/src/4JLibraries_Source/fui/fuiSymbol.h +++ b/src/4JLibraries_Source/fui/fuiSymbol.h @@ -1,9 +1,9 @@ #pragma once -class FJ_FuiNodeStage; - struct fuiSymbol { - char m_padding[0xf8]; - FJ_FuiNodeStage* - m_stage; // not sure if this is meant to be stage but fui::dispatchKeyboardEvent likes it sooo + char m_name[64]; + int m_objectType; + int m_objectIndex; }; + +static_assert(sizeof(fuiSymbol) == 0x48, "FUI on-disk symbol layout"); diff --git a/src/Minecraft.Client/com/mojang/nbt/CompoundTag.h b/src/Minecraft.Client/com/mojang/nbt/CompoundTag.h index 096796a5..7549e926 100644 --- a/src/Minecraft.Client/com/mojang/nbt/CompoundTag.h +++ b/src/Minecraft.Client/com/mojang/nbt/CompoundTag.h @@ -5,6 +5,9 @@ #include "nn/types.h" #include "types.h" #include +#include + +class ListTag; class CompoundTag : public Tag { public: @@ -21,6 +24,9 @@ class CompoundTag : public Tag { void stripEmptyChildren() override; bool isEmpty() const override; void remove(const std::wstring&); + // Caller owns the returned vector; entries are copies of child names. + std::vector* getAllKeys(); + std::unordered_map* getAllTags(); /** Gets a child `Compound Tag` * @@ -64,27 +70,25 @@ class CompoundTag : public Tag { */ float getFloat(const std::wstring& name); - /** Gets a child `List Tag` (but returns void???) + /** Gets a child `List Tag` * * @param name The name of the child tag - * @param length The length of the list (unconfirmed) + * @param length The element tag type */ - void getList(const std::wstring& name, int length); + ListTag* getList(const std::wstring& name, int length); /** Gets a child `Tag` with the provided name * * @param name The name of the tag that you want to get. */ - CompoundTag* get(const std::wstring& name); + Tag* get(const std::wstring& name); - /** Gets a child `List Tag` (Safe) - * - * Why does this return void + /** Gets a child `List Tag` without allocating * * @param name The name of the child tag - * @param length The length of the list (unconfirmed) + * @param length The element tag type */ - void fjSafeGetListTag(const std::wstring& name, int length); + const ListTag* fjSafeGetListTag(const std::wstring& name, int type) const; /** Checks if a child with the provided name exists * @@ -98,6 +102,7 @@ class CompoundTag : public Tag { * @param type Type of the child tag */ bool contains(const std::wstring& name, int type); + u8 getTagType(const std::wstring& name) const; /** Adds a `Tag` * diff --git a/src/Minecraft.Client/com/mojang/nbt/ListTag.h b/src/Minecraft.Client/com/mojang/nbt/ListTag.h index d3a79141..b7bfba21 100644 --- a/src/Minecraft.Client/com/mojang/nbt/ListTag.h +++ b/src/Minecraft.Client/com/mojang/nbt/ListTag.h @@ -3,6 +3,8 @@ #include "com/mojang/nbt/Tag.h" #include +class CompoundTag; + class ListTag : public Tag { public: ListTag(); @@ -20,6 +22,14 @@ class ListTag : public Tag { bool isEmpty() const override; void add(Tag* tag); + // Replaces an accepted element and deletes its previous owner. Rejected + // replacements remain caller-owned; assigning the same pointer is a no-op. + void set(int index, Tag* tag); + size_t size() const; + int getElementType() const { return m_tagId; } + CompoundTag* getCompound(int) const; + int getInt(int) const; + double getDouble(int) const; private: std::vector m_data; diff --git a/src/Minecraft.Client/com/mojang/nbt/NbtUtils.h b/src/Minecraft.Client/com/mojang/nbt/NbtUtils.h new file mode 100644 index 00000000..c61677bd --- /dev/null +++ b/src/Minecraft.Client/com/mojang/nbt/NbtUtils.h @@ -0,0 +1,10 @@ +#pragma once + +class BlockState; +class CompoundTag; + +class NbtUtils { +public: + // Switch registry/property decoder at 0x71006ef4b0. + static const BlockState* readBlockState(CompoundTag*); +}; diff --git a/src/Minecraft.Client/com/mojang/nbt/Tag.h b/src/Minecraft.Client/com/mojang/nbt/Tag.h index 0abd8c0f..1620d8b8 100644 --- a/src/Minecraft.Client/com/mojang/nbt/Tag.h +++ b/src/Minecraft.Client/com/mojang/nbt/Tag.h @@ -1,5 +1,6 @@ #pragma once +#include "java/io/DataInput.h" #include "nn/types.h" #include #include @@ -23,11 +24,17 @@ class Tag { virtual bool isEmpty() const; virtual std::wstring getAsString(); + // The exported DataInput vtable is still incomplete on Switch. Host NBT uses + // the one-byte reader explicitly; readChar reads two bytes in Java streams. + static u8 readType(DataInput* input) { return input->readChar(); } static Tag* newTag(u8 id); static const wchar_t* getTagTypeName(u8 id); template - static void deleteElements(const std::vector&); + static void deleteElements(const std::vector& data) { + for (T tag : data) + delete tag; + } static const u8 TAG_End = 0; static const u8 TAG_Byte = 1; diff --git a/src/Minecraft.Client/net/minecraft/client/CMinecraftApp.h b/src/Minecraft.Client/net/minecraft/client/CMinecraftApp.h index ab70ffe7..3cec5bda 100644 --- a/src/Minecraft.Client/net/minecraft/client/CMinecraftApp.h +++ b/src/Minecraft.Client/net/minecraft/client/CMinecraftApp.h @@ -71,6 +71,8 @@ class CMinecraftApp { bool IsAppPaused(); void SetAction(int, eXuiAction, void*); void setLevelGenerationOptions(LevelGenerationOptions* options); + // Inferred name: records a unique (type, x, z) generation marker. + void addGeneratedFeature(int type, int x, int z); void SetGameHostOption(eGameHostOption option, unsigned int value); void UpdateTrialPausedTimer(); diff --git a/src/Minecraft.Client/net/minecraft/client/color/ColourTable.h b/src/Minecraft.Client/net/minecraft/client/color/ColourTable.h index f1bfa74b..6dacdef0 100644 --- a/src/Minecraft.Client/net/minecraft/client/color/ColourTable.h +++ b/src/Minecraft.Client/net/minecraft/client/color/ColourTable.h @@ -1,9 +1,24 @@ #pragma once #include "net/minecraft/world/level/material/MaterialColor.h" +#include +#include class ColourTable { public: + ColourTable(unsigned char*, unsigned int); + ColourTable(const ColourTable&, unsigned char*, unsigned int); static void staticCtor(); unsigned int getColour(eMinecraftColour); + void read(unsigned char*, unsigned int); + void setColour(const std::wstring&, unsigned int); + + static constexpr unsigned int COLOUR_COUNT = 486; + unsigned int m_colours[COLOUR_COUNT]; + +private: + static const wchar_t* const s_colourNames[COLOUR_COUNT]; + static std::unordered_map s_nameToColour; }; + +static_assert(sizeof(ColourTable) == 0x798, "Original colour table contains 486 words"); diff --git a/src/Minecraft.Client/net/minecraft/client/multiplayer/ClientChunkCache.h b/src/Minecraft.Client/net/minecraft/client/multiplayer/ClientChunkCache.h index 6ed5841d..afc6c1f0 100644 --- a/src/Minecraft.Client/net/minecraft/client/multiplayer/ClientChunkCache.h +++ b/src/Minecraft.Client/net/minecraft/client/multiplayer/ClientChunkCache.h @@ -23,7 +23,7 @@ class ClientChunkCache : public ChunkSource { void save(bool, ProgressListener*) override; bool shouldSave() override; ChunkSource* getCache() override; - std::vector* getMobsAt(MobCategory*, const BlockPos&) override; + std::vector* getMobsAt(MobCategory*, const BlockPos&) override; void findNearestMapFeature(Level*, const std::wstring&, const BlockPos&, bool) override; int getLoadedChunks() override; void recreateLogicStructuresForChunk(LevelChunk*, int, int) override; diff --git a/src/Minecraft.Client/net/minecraft/client/renderer/texture/TextureAtlasSprite.h b/src/Minecraft.Client/net/minecraft/client/renderer/texture/TextureAtlasSprite.h index 35ca2881..0a26f298 100644 --- a/src/Minecraft.Client/net/minecraft/client/renderer/texture/TextureAtlasSprite.h +++ b/src/Minecraft.Client/net/minecraft/client/renderer/texture/TextureAtlasSprite.h @@ -33,5 +33,16 @@ class TextureAtlasSprite { void adjustUV(float&, float&); void initUVs(float u0, float v0, float u1, float v1); - char m_filler[0x90 - 8]; + char m_filler[0x60 - 8]; + int m_x; + int m_y; + int m_width; + int m_height; + float m_u0; + float m_u1; + float m_v0; + float m_v1; + char m_gap80[0x10]; }; + +static_assert(sizeof(TextureAtlasSprite) == 0x90, "TextureAtlasSprite size"); diff --git a/src/Minecraft.Client/net/minecraft/core/BlockPos.h b/src/Minecraft.Client/net/minecraft/core/BlockPos.h index 7a3aacad..dcbca8ba 100644 --- a/src/Minecraft.Client/net/minecraft/core/BlockPos.h +++ b/src/Minecraft.Client/net/minecraft/core/BlockPos.h @@ -23,9 +23,12 @@ class BlockPos : public Vec3i { static BlockPosIterator* between(const BlockPos&, const BlockPos&); bool equals(const BlockPos& pos) const; + bool operator!=(const BlockPos& pos) const; bool equals(const BlockPos* pos) const; BlockPos offset(int x, int y, int z) const; + BlockPos offset(double x, double y, double z) const; + BlockPos offset(const Vec3i&) const; BlockPos relative(const Direction*) const; BlockPos relative(const Direction*, int) const; @@ -44,7 +47,7 @@ class BlockPos : public Vec3i { BlockPos east(int) const; long long compressBlockPos() const; - void decompressBlockPos(long long); + static BlockPos decompressBlockPos(long long); }; ASSERT_SIZEOF(BlockPos, 0xC) diff --git a/src/Minecraft.Client/net/minecraft/core/Direction.h b/src/Minecraft.Client/net/minecraft/core/Direction.h index 7f2dc9de..cc7a77e7 100644 --- a/src/Minecraft.Client/net/minecraft/core/Direction.h +++ b/src/Minecraft.Client/net/minecraft/core/Direction.h @@ -1,6 +1,7 @@ #pragma once #include "net/minecraft/core/StringRepresentable.h" +#include "net/minecraft/world/ArrayWithLength.h" #include "net/minecraft/world/level/block/state/properties/AbstractProperty.h" #include #include @@ -20,6 +21,7 @@ class Direction : public StringRepresentable { bool apply(const Direction*) const override; const Direction* getRandomDirection(Random&); + arrayWithLength iterator(); }; class AxisDirection { public: @@ -44,6 +46,11 @@ class Direction : public StringRepresentable { std::wstring toString() const override; std::wstring getSerializedName() const override; + + private: + std::wstring m_name; + Plane* m_plane; + int m_id; }; static const Direction* DOWN; @@ -62,6 +69,7 @@ class Direction : public StringRepresentable { static void staticCtor(); static const Direction* from3DDataValue(int value); + static const Direction* from2DDataValue(int value); Direction(int, int, int, const std::wstring&, Direction::AxisDirection*, Direction::Axis*, Vec3i*, unsigned char); @@ -75,6 +83,8 @@ class Direction : public StringRepresentable { int get2DDataValue() const; Axis* getAxis() const; + Vec3i getNormal() const; + AxisDirection* getAxisDirection() const; std::wstring getName() const; @@ -93,3 +103,6 @@ class Direction : public StringRepresentable { int m_y; int m_z; }; + +static_assert(sizeof(Direction::Axis) == 0x38, "Direction::Axis Switch layout"); +static_assert(sizeof(Direction) == 0x58, "Direction Switch layout"); diff --git a/src/Minecraft.Client/net/minecraft/core/MutableBlockPos.h b/src/Minecraft.Client/net/minecraft/core/MutableBlockPos.h index 11777a7c..12f0b268 100644 --- a/src/Minecraft.Client/net/minecraft/core/MutableBlockPos.h +++ b/src/Minecraft.Client/net/minecraft/core/MutableBlockPos.h @@ -4,6 +4,7 @@ class MutableBlockPos : public BlockPos { public: + MutableBlockPos(); MutableBlockPos(int, int, int); MutableBlockPos(const BlockPos&); @@ -19,4 +20,6 @@ class MutableBlockPos : public BlockPos { } void set(const BlockPos&); + MutableBlockPos* set(const Vec3i&); + MutableBlockPos* move(const Direction*, int amount); }; diff --git a/src/Minecraft.Client/net/minecraft/core/NonNullList.h b/src/Minecraft.Client/net/minecraft/core/NonNullList.h index 06262f7e..88564e0b 100644 --- a/src/Minecraft.Client/net/minecraft/core/NonNullList.h +++ b/src/Minecraft.Client/net/minecraft/core/NonNullList.h @@ -5,7 +5,37 @@ template class NonNullList : arrayWithLength { public: - static NonNullList withSize(int, const T&); + NonNullList() = default; + + // Copies are views of the same array. The owner must delete the backing data; + // destroying a view only releases its default value, as in the executable. + static NonNullList withSize(int size, const T& defaultValue) { + NonNullList list; + if (size > 0) { + list.m_data = new T[size]; + list.m_length = size; + for (unsigned int i = 0; i < list.m_length; ++i) + list.m_data[i] = defaultValue; + } + list.m_baseNotNull = defaultValue; + return list; + } + + unsigned int size() const { return this->m_length; } + T& operator[](unsigned int index) { return this->m_data[index]; } + const T& operator[](unsigned int index) const { return this->m_data[index]; } + void set(unsigned int index, const T& value) { this->m_data[index] = value; } + + void clear() { + for (unsigned int i = 0; i < size(); ++i) + set(i, m_baseNotNull); + } + + void deleteData() { + delete[] this->m_data; + this->m_data = nullptr; + this->m_length = 0; + } T m_baseNotNull; // idk if this should be not_null_ptr by default or specified in template, so decided it // not to be for a while diff --git a/src/Minecraft.Client/net/minecraft/core/System.h b/src/Minecraft.Client/net/minecraft/core/System.h index fca8e4c7..ef334a3e 100644 --- a/src/Minecraft.Client/net/minecraft/core/System.h +++ b/src/Minecraft.Client/net/minecraft/core/System.h @@ -1,5 +1,9 @@ #pragma once +#include "java/io/JavaLong.h" +#include +#include + #include "net/minecraft/world/ArrayWithLength.h" #include "net/minecraft/world/level/biome/Biome.h" #include "nn/os/os_MutexTypes.h" @@ -12,7 +16,8 @@ class Node; // TODO: Find locations void InitializeCriticalSection(nn::os::MutexType* mutexType); void InitializeCriticalSectionAndSpinCount(nn::os::MutexType* mutexType, unsigned long spinCount); -long InterlockedCompareExchangeRelease(volatile long*, long, long); +void DeleteCriticalSection(nn::os::MutexType* mutexType); +std::intptr_t InterlockedCompareExchangeRelease(volatile std::intptr_t*, std::intptr_t, std::intptr_t); template const std::wstring _toString(T type) { std::wstringstream ss; @@ -30,14 +35,14 @@ class System { public: enum ETimeGranularity { MILLISECONDS, MICROSECONDS, NANOSECONDS }; - static long currentRealTimeMillis(); - static long currentUnixEpochTimeSeconds(); + static JavaLong currentRealTimeMillis(); + static JavaLong currentUnixEpochTimeSeconds(); - static long processTimeInSeconds(); - static long processTimeInMilliSecs(); - static long processTimeInNanoSecs(); - static long processTimeInMicroSecs(); - static long processTime(System::ETimeGranularity); + static JavaLong processTimeInSeconds(); + static JavaLong processTimeInMilliSecs(); + static JavaLong processTimeInNanoSecs(); + static JavaLong processTimeInMicroSecs(); + static JavaLong processTime(System::ETimeGranularity); template static void arraycopy(arrayWithLength src, unsigned int srcOff, arrayWithLength* dest, diff --git a/src/Minecraft.Client/net/minecraft/core/Vec3i.h b/src/Minecraft.Client/net/minecraft/core/Vec3i.h index 5b383dd9..ca111e86 100644 --- a/src/Minecraft.Client/net/minecraft/core/Vec3i.h +++ b/src/Minecraft.Client/net/minecraft/core/Vec3i.h @@ -9,7 +9,9 @@ class Vec3i { int getX() const; int getY() const; int getZ() const; + Vec3i multiply(int) const; double distSqr(const Vec3i&) const; + double distSqr(double x, double y, double z) const; int m_x; int m_y; diff --git a/src/Minecraft.Client/net/minecraft/resources/ResourceLocation.h b/src/Minecraft.Client/net/minecraft/resources/ResourceLocation.h index 30b79d90..6e525283 100644 --- a/src/Minecraft.Client/net/minecraft/resources/ResourceLocation.h +++ b/src/Minecraft.Client/net/minecraft/resources/ResourceLocation.h @@ -13,6 +13,7 @@ class ResourceLocation { ResourceLocation(); ResourceLocation(const std::wstring&); ResourceLocation(const ResourceLocation&); + ResourceLocation& operator=(const ResourceLocation&); ~ResourceLocation(); bool operator==(const ResourceLocation* other) const; @@ -22,6 +23,7 @@ class ResourceLocation { const std::wstring& getNamespace() const; const std::wstring& getPath() const; + std::int64_t hashCode() const; virtual std::wstring toString() const; @@ -31,10 +33,15 @@ class ResourceLocation { char m_byte48; }; -// this is actually ResourceLocation::hashCode template <> -struct std::hash { - std::size_t operator()(const ResourceLocation& rl) const { - return std::hash()(rl.getPath()) ^ (std::hash()(rl.getNamespace()) << 1); +struct std::equal_to { + bool operator()(const ResourceLocation& lhs, const ResourceLocation& rhs) const { + return lhs.operator==(&rhs); } }; + +// Uses the original LCE resource-key hash. +template <> +struct std::hash { + std::size_t operator()(const ResourceLocation& rl) const { return rl.hashCode(); } +}; diff --git a/src/Minecraft.Client/net/minecraft/server/level/ServerChunkCache.cpp b/src/Minecraft.Client/net/minecraft/server/level/ServerChunkCache.cpp index 8e44a8e8..262f34f7 100644 --- a/src/Minecraft.Client/net/minecraft/server/level/ServerChunkCache.cpp +++ b/src/Minecraft.Client/net/minecraft/server/level/ServerChunkCache.cpp @@ -1,5 +1,7 @@ #include "net/minecraft/server/level/ServerChunkCache.h" +#include + #include "NX/Platform.h" #include "net/minecraft/core/BlockPos.h" @@ -58,7 +60,7 @@ ServerChunkCache::~ServerChunkCache() { delete *it; } - nn::os::FinalizeMutex(&m_mutex); + DeleteCriticalSection(&m_mutex); } LevelChunk* ServerChunkCache::getChunkIfLoaded(int chunkX, int chunkZ) { @@ -154,8 +156,9 @@ LevelChunk* ServerChunkCache::updateCacheAndPostProcess(int chunkX, int chunkZ, int idx = computeIdx(chunkX, chunkZ); - if (InterlockedCompareExchangeRelease((volatile long*)&m_chunks[idx], (long)newChunk, (long)oldChunk) - == (long)oldChunk) { + if (InterlockedCompareExchangeRelease((volatile intptr_t*)&m_chunks[idx], (intptr_t)newChunk, + (intptr_t)oldChunk) + == (intptr_t)oldChunk) { EnterCriticalSection(&m_mutex); PIXBeginNamedEvent(0.0, "Lighting chunk"); @@ -440,7 +443,7 @@ std::wstring ServerChunkCache::gatherStats() { return L"ServerChunkCache: "; } -std::vector* ServerChunkCache::getMobsAt(MobCategory* category, const BlockPos& pos) { +std::vector* ServerChunkCache::getMobsAt(MobCategory* category, const BlockPos& pos) { return m_chunkGenerator->getMobsAt(category, pos); } diff --git a/src/Minecraft.Client/net/minecraft/server/level/ServerChunkCache.h b/src/Minecraft.Client/net/minecraft/server/level/ServerChunkCache.h index ffad2af7..f1dfa15c 100644 --- a/src/Minecraft.Client/net/minecraft/server/level/ServerChunkCache.h +++ b/src/Minecraft.Client/net/minecraft/server/level/ServerChunkCache.h @@ -37,7 +37,7 @@ class ServerChunkCache : public ChunkSource { void save(bool, ProgressListener*) override; bool shouldSave() override; ChunkSource* getCache() override; - std::vector* getMobsAt(MobCategory* category, const BlockPos& pos) override; + std::vector* getMobsAt(MobCategory* category, const BlockPos& pos) override; void findNearestMapFeature(Level* level, const std::wstring& name, const BlockPos& pos, bool unk) override; int getLoadedChunks() override; diff --git a/src/Minecraft.World/java/io/ByteArrayInputStream.h b/src/Minecraft.World/java/io/ByteArrayInputStream.h index 49bfdb02..8b3c0f7e 100644 --- a/src/Minecraft.World/java/io/ByteArrayInputStream.h +++ b/src/Minecraft.World/java/io/ByteArrayInputStream.h @@ -13,6 +13,7 @@ class ByteArrayInputStream : public InputStream { int read(arrayWithLength) override; int read(arrayWithLength, unsigned int, unsigned int) override; void close() override; + void reset(); long long skip(long long) override; arrayWithLength m_buffer; diff --git a/src/Minecraft.World/java/io/DataInput.h b/src/Minecraft.World/java/io/DataInput.h index eb87b6a9..8b2bd53b 100644 --- a/src/Minecraft.World/java/io/DataInput.h +++ b/src/Minecraft.World/java/io/DataInput.h @@ -1,5 +1,7 @@ #pragma once +#include "java/io/JavaLong.h" + #include "net/minecraft/world/ArrayWithLength.h" #include "net/minecraft/world/PlayerUID.h" @@ -12,13 +14,13 @@ class DataInput { virtual int readUnsignedShort() = 0; virtual wchar_t readChar() = 0; // is this correct? i swapped the two readFully methods for a match in ByteArrayTag::load - virtual void readFully(arrayWithLength) = 0; - virtual void readFully(arrayWithLength) = 0; - virtual void readBytes(arrayWithLength) = 0; + virtual bool readFully(arrayWithLength) = 0; + virtual bool readFully(arrayWithLength) = 0; + virtual bool readBytes(arrayWithLength) = 0; virtual double readDouble() = 0; virtual float readFloat() = 0; virtual int readInt() = 0; - virtual long readLong() = 0; + virtual JavaLong readLong() = 0; virtual short readShort() = 0; virtual std::wstring readUTF() = 0; virtual int readUTFChar() = 0; diff --git a/src/Minecraft.World/java/io/DataInputStream.h b/src/Minecraft.World/java/io/DataInputStream.h index c4dcf4e5..b076ca76 100644 --- a/src/Minecraft.World/java/io/DataInputStream.h +++ b/src/Minecraft.World/java/io/DataInputStream.h @@ -25,13 +25,13 @@ class DataInputStream : public InputStream, public DataInput { int readUnsignedShort() override; wchar_t readChar() override; // todo: wrong order likely, need to maintain matching tho - void readBytes(arrayWithLength) override; - void readFully(arrayWithLength) override; - void readFully(arrayWithLength) override; + bool readBytes(arrayWithLength) override; + bool readFully(arrayWithLength) override; + bool readFully(arrayWithLength) override; double readDouble() override; float readFloat() override; int readInt() override; - long readLong() override; + JavaLong readLong() override; short readShort() override; std::wstring readUTF() override; int readUTFChar() override; @@ -39,11 +39,13 @@ class DataInputStream : public InputStream, public DataInput { void skipBytes(long long) override; int readVarInt(); - long readVarLong(); + JavaLong readVarLong(); BlockPos readBlockPos(); BlockPos* readBlockPosPointer(); not_null_ptr readItem(); CompoundTag* readNbt(); + CompoundTag* readCompressedNbt(); + void deleteChildStream(); InputStream* m_inputStream; }; diff --git a/src/Minecraft.World/java/io/DataOutputStream.h b/src/Minecraft.World/java/io/DataOutputStream.h index 9ca985d5..cb6c49a4 100644 --- a/src/Minecraft.World/java/io/DataOutputStream.h +++ b/src/Minecraft.World/java/io/DataOutputStream.h @@ -3,6 +3,7 @@ #include #include "java/io/DataOutput.h" +#include "java/io/JavaLong.h" #include "java/io/OutputStream.h" #include "java/io/types/Double.h" #include "java/io/types/Float.h" @@ -38,8 +39,8 @@ class DataOutputStream : public OutputStream, public DataOutput { void writePlayerUID(PlayerUID) override; void writeVarInt(int); - void writeVarLong(long); - void writeBlockPos(const BlockPos&) const; + void writeVarLong(JavaLong); + void writeBlockPos(const BlockPos&); void writeItem(not_null_ptr); void writeNbt(CompoundTag*); diff --git a/src/Minecraft.World/java/io/JavaLong.h b/src/Minecraft.World/java/io/JavaLong.h new file mode 100644 index 00000000..25327209 --- /dev/null +++ b/src/Minecraft.World/java/io/JavaLong.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +using JavaLong = long; diff --git a/src/Minecraft.World/net/minecraft/util/Mth.h b/src/Minecraft.World/net/minecraft/util/Mth.h index 97227879..fb1e6cb2 100644 --- a/src/Minecraft.World/net/minecraft/util/Mth.h +++ b/src/Minecraft.World/net/minecraft/util/Mth.h @@ -1,20 +1,25 @@ #pragma once +#include #include class Random; +using MthLong = long; + // Meth class Mth { public: static constexpr float PI = 3.1415927; static float* SIN; + static float* ATAN; static float sin(float); static float cos(float); static int floor(double); static int floor(float); + static int ceil(float); static float sqrt(float v); static float sqrt(double v); static double clamp(double, double, double); @@ -26,15 +31,17 @@ class Mth { static float abs(float i); static double abs(double i); static float wrapDegrees(float); - static void cached_atan_index(int, int); + static double wrapDegrees(double); + static int cached_atan_index(int, int); static void init(); - static long lfloor(double); + static MthLong lfloor(double); + static MthLong round(double); static double clampedLerp(double, double, double); static double frac(double); static int hsvToRgb(float, float, float); static int nextInt(Random* random, int i, int j); static float nextFloat(Random* random, float i, float j); static double nextDouble(Random* random, double i, double j); - static std::wstring createInsecureUUID(Random* random); + static std::wstring createInsecureUUID(Random* random) asm("createInsecureUUID__3MthSFP6Random"); static int64_t getSeed(int, int, int); }; diff --git a/src/Minecraft.World/net/minecraft/util/StringUtils.h b/src/Minecraft.World/net/minecraft/util/StringUtils.h new file mode 100644 index 00000000..3071a8ef --- /dev/null +++ b/src/Minecraft.World/net/minecraft/util/StringUtils.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +// Additional formatting overload supplied by the Switch runtime. +namespace std { +inline namespace __1 { +wstring to_wstring(bool); +} +} // namespace std + +std::wstring replaceAll(const std::wstring&, const std::wstring&, const std::wstring&); + +std::vector& split(const std::wstring&, wchar_t, std::vector&); +std::vector split(const std::wstring&, wchar_t); + +template +T _fromString(const std::wstring& text) { + std::wistringstream stream(text); + T value; + stream >> value; + return value; +} diff --git a/src/Minecraft.World/net/minecraft/util/datafix/DataFixTypes.h b/src/Minecraft.World/net/minecraft/util/datafix/DataFixTypes.h new file mode 100644 index 00000000..ed344804 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/util/datafix/DataFixTypes.h @@ -0,0 +1,6 @@ +#pragma once + +class DataFixTypes { +public: + enum EDataFixTypes { ITEM = 5, STRUCTURE = 7 }; +}; diff --git a/src/Minecraft.World/net/minecraft/util/datafix/DataFixer.h b/src/Minecraft.World/net/minecraft/util/datafix/DataFixer.h new file mode 100644 index 00000000..4210b16f --- /dev/null +++ b/src/Minecraft.World/net/minecraft/util/datafix/DataFixer.h @@ -0,0 +1,11 @@ +#pragma once + +#include "net/minecraft/util/datafix/DataFixTypes.h" + +class CompoundTag; + +class DataFixer { +public: + DataFixer(); + virtual CompoundTag* update(DataFixTypes::EDataFixTypes, CompoundTag*, int version) = 0; +}; diff --git a/src/Minecraft.World/net/minecraft/util/datafix/DataFixerUpper.h b/src/Minecraft.World/net/minecraft/util/datafix/DataFixerUpper.h new file mode 100644 index 00000000..00e312ea --- /dev/null +++ b/src/Minecraft.World/net/minecraft/util/datafix/DataFixerUpper.h @@ -0,0 +1,33 @@ +#pragma once + +#include "net/minecraft/util/datafix/DataFixer.h" +#include +#include +#include + +class CompoundTag; +class DataFix; +class DataWalker; + +class DataFixerUpper : public DataFixer { +public: + explicit DataFixerUpper(int version); + CompoundTag* updateData(DataFixTypes::EDataFixTypes, CompoundTag*); + CompoundTag* update(DataFixTypes::EDataFixTypes, CompoundTag*, int version) override; + CompoundTag* applyFixes(DataFixTypes::EDataFixTypes, CompoundTag*, int version); + CompoundTag* applyWalkers(DataFixTypes::EDataFixTypes, CompoundTag*, int version); + std::vector* getOrCreateWalker(DataFixTypes::EDataFixTypes); + std::vector* getOrCreateFix(DataFixTypes::EDataFixTypes); + void addWalker(DataFixTypes::EDataFixTypes, DataWalker*); + void addFixer(DataFixTypes::EDataFixTypes, DataFix*); + + int m_version; + std::unordered_map*> m_walkers; + std::unordered_map*> m_fixes; + static const std::wstring DATA_VERSION_KEY; +}; + +static_assert(sizeof(DataFixerUpper) == 0x60, "Original fixer-upper allocation"); +static_assert(__builtin_offsetof(DataFixerUpper, m_version) == 8, "Original target-version offset"); +static_assert(__builtin_offsetof(DataFixerUpper, m_walkers) == 0x10, "Original walker registry offset"); +static_assert(__builtin_offsetof(DataFixerUpper, m_fixes) == 0x38, "Original fix registry offset"); diff --git a/src/Minecraft.World/net/minecraft/world/ArrayWithLength.h b/src/Minecraft.World/net/minecraft/world/ArrayWithLength.h index 7bb6b677..aeb474c0 100644 --- a/src/Minecraft.World/net/minecraft/world/ArrayWithLength.h +++ b/src/Minecraft.World/net/minecraft/world/ArrayWithLength.h @@ -18,6 +18,11 @@ class arrayWithLength { this->m_data = initialData; this->m_length = length; } + template + arrayWithLength(T (&initialData)[N]) { + this->m_data = initialData; + this->m_length = N; + } arrayWithLength(unsigned int size, bool a3) { T* temp; if (a3) @@ -29,6 +34,7 @@ class arrayWithLength { } T& operator[](unsigned int i) { return m_data[i]; } + const T& operator[](unsigned int i) const { return m_data[i]; } T& get(unsigned int i) { return m_data[i]; } void resize(unsigned int newSize) { diff --git a/src/Minecraft.World/net/minecraft/world/Difficulty.h b/src/Minecraft.World/net/minecraft/world/Difficulty.h index 8d04280e..54cd9bd0 100644 --- a/src/Minecraft.World/net/minecraft/world/Difficulty.h +++ b/src/Minecraft.World/net/minecraft/world/Difficulty.h @@ -6,7 +6,13 @@ class Difficulty { static const Difficulty* EASY; static const Difficulty* NORMAL; static const Difficulty* HARD; + static Difficulty* DIFFICULTIES[4]; static Difficulty* byId(int id); int getId() const; + +private: + int m_id; }; + +static_assert(sizeof(Difficulty) == 4, "Difficulty ID layout"); diff --git a/src/Minecraft.World/net/minecraft/world/PlayerUID.h b/src/Minecraft.World/net/minecraft/world/PlayerUID.h index ed3d46dd..374ff3c1 100644 --- a/src/Minecraft.World/net/minecraft/world/PlayerUID.h +++ b/src/Minecraft.World/net/minecraft/world/PlayerUID.h @@ -1,7 +1,9 @@ #pragma once +#include "java/io/JavaLong.h" #include "types.h" #include +#include class PlayerUID { public: @@ -16,8 +18,8 @@ class PlayerUID { const std::wstring UuidString() const; const std::wstring toString() const; - long m_gap0; - long m_mostSigBits; // grabbed from JDK, doubt those are correct but yeah, pure guess - long m_leastSigBits; + JavaLong m_gap0; + JavaLong m_mostSigBits; // grabbed from JDK, doubt those are correct but yeah, pure guess + JavaLong m_leastSigBits; char m_byte18; }; diff --git a/src/Minecraft.World/net/minecraft/world/Random.h b/src/Minecraft.World/net/minecraft/world/Random.h index 3ed8670d..61c70544 100644 --- a/src/Minecraft.World/net/minecraft/world/Random.h +++ b/src/Minecraft.World/net/minecraft/world/Random.h @@ -1,5 +1,7 @@ #pragma once +using RandomLong = long; + class Random { public: Random(); @@ -10,12 +12,12 @@ class Random { double nextDouble(); int nextInt(); void setSeed(long long seed); - long nextLong(); + RandomLong nextLong(); bool nextBoolean(); int next(int bits); double nextGaussian(); - long m_val; + RandomLong m_val; bool m_field8; double m_seed3; }; diff --git a/src/Minecraft.World/net/minecraft/world/entity/Entity.h b/src/Minecraft.World/net/minecraft/world/entity/Entity.h index ea148673..ca4b710f 100644 --- a/src/Minecraft.World/net/minecraft/world/entity/Entity.h +++ b/src/Minecraft.World/net/minecraft/world/entity/Entity.h @@ -59,6 +59,7 @@ class Entity : public std::enable_shared_from_this, public CommandSender static int sEntityAmount; static int sTlsIndex; static double sViewScale; + static const float sDegreesToRadians; static void staticCtor(); static int getSmallId(); @@ -294,6 +295,9 @@ class Entity : public std::enable_shared_from_this, public CommandSender Vec3* getPos(float); bool isType(eINSTANCEOF); + void setRot(float, float); + void interpolateTurn(float, float); + bool getSharedFlag(int); void setSharedFlag(int, bool); Vec3* calculateViewVector(float, float); int getId(); diff --git a/src/Minecraft.World/net/minecraft/world/entity/LivingEntity.h b/src/Minecraft.World/net/minecraft/world/entity/LivingEntity.h index 8d0cc489..a81721be 100644 --- a/src/Minecraft.World/net/minecraft/world/entity/LivingEntity.h +++ b/src/Minecraft.World/net/minecraft/world/entity/LivingEntity.h @@ -93,7 +93,7 @@ class LivingEntity : public Entity { virtual void onEffectUpdated(MobEffectInstance*, bool); virtual void onEffectRemoved(MobEffectInstance*); virtual void heal(float); - virtual void getHealth(); + virtual float getHealth(); virtual void setHealth(float); virtual void getLastDamageSource(); virtual void blockUsingShield(const std::shared_ptr&); @@ -119,7 +119,7 @@ class LivingEntity : public Entity { virtual void actuallyHurt(DamageSource, float); virtual void getCombatTracker(); virtual void getKillCredit(); - virtual void getMaxHealth(); + virtual float getMaxHealth(); virtual void getArrowCount(); virtual void setArrowCount(int); virtual void swing(InteractionHand::EInteractionHand); diff --git a/src/Minecraft.World/net/minecraft/world/entity/ai/attributes/AttributeModifier.h b/src/Minecraft.World/net/minecraft/world/entity/ai/attributes/AttributeModifier.h index ce282531..d89dcb53 100644 --- a/src/Minecraft.World/net/minecraft/world/entity/ai/attributes/AttributeModifier.h +++ b/src/Minecraft.World/net/minecraft/world/entity/ai/attributes/AttributeModifier.h @@ -7,6 +7,15 @@ enum eATTRIBUTE_ID { BASE_ATTACK_DAMAGE = 1, BASE_ATTACK_SPEED = 16 }; class AttributeModifier { public: AttributeModifier(eATTRIBUTE_ID, double, int); + AttributeModifier(double, int); + AttributeModifier(eATTRIBUTE_ID, double, int, bool); + void _init(int, std::wstring, double, int); + eATTRIBUTE_ID getId(); + double getAmount(); + int getOperation(); + bool isSerializable(); + void setSerialize(bool); + bool equals(AttributeModifier*); double m_amount; int m_operation; diff --git a/src/Minecraft.World/net/minecraft/world/entity/player/Player.h b/src/Minecraft.World/net/minecraft/world/entity/player/Player.h index 658b7322..513afb99 100644 --- a/src/Minecraft.World/net/minecraft/world/entity/player/Player.h +++ b/src/Minecraft.World/net/minecraft/world/entity/player/Player.h @@ -193,6 +193,13 @@ class Player : public LivingEntity { void setBool7FC(bool); bool isAllowedToAttackPlayers(); bool hasInvisiblePrivilege(); + bool isAllowedToFly(); + bool hasInvulnerablePrivilege(); + // Inferred names for the unnamed entries at 0x71002d0d68 and 0x71002d0e10. + bool usesLegacyFoodHealing(); + bool isHurt(); + void causeFoodExhaustion(float); + FoodData* getFoodData(); int getPlayerGamePrivilege(EPlayerGamePrivileges); bool CheckPowerup(PowerupItems::eGlide_Timed_Powerup_ID); std::shared_ptr drop(not_null_ptr, bool); diff --git a/src/Minecraft.World/net/minecraft/world/item/BlockItem.h b/src/Minecraft.World/net/minecraft/world/item/BlockItem.h index 4421e48b..71339cfa 100644 --- a/src/Minecraft.World/net/minecraft/world/item/BlockItem.h +++ b/src/Minecraft.World/net/minecraft/world/item/BlockItem.h @@ -5,8 +5,15 @@ class BlockItem : public Item { public: BlockItem(Block* block); + ~BlockItem() override; Block* getBlock(); + BlockItem* setDescriptionId(unsigned int); + unsigned int getDescriptionId(int) override; + unsigned int getDescriptionId(not_null_ptr) override; + unsigned int getUseDescriptionId() override; + unsigned int getUseDescriptionId(not_null_ptr) override; - void* m_filler[2]; + Block* m_block; + void* m_unknown88; }; diff --git a/src/Minecraft.World/net/minecraft/world/item/Item.cpp b/src/Minecraft.World/net/minecraft/world/item/Item.cpp index a95d6aa6..4661b26f 100644 --- a/src/Minecraft.World/net/minecraft/world/item/Item.cpp +++ b/src/Minecraft.World/net/minecraft/world/item/Item.cpp @@ -59,8 +59,9 @@ bool Item::canBeDepleted() { return this->m_maxDamage > 0 && (!this->m_stackedByData || this->m_maxStackSize == 1); } -void Item::setIconName(const std::wstring& iconName) { +Item* Item::setIconName(const std::wstring& iconName) { this->m_iconName = iconName; + return this; } not_null_ptr Item::getDefaultInstance() { @@ -102,6 +103,14 @@ int Item::getMaxStackSize() { return this->m_maxStackSize; } +int Item::getMaxDamage() { + return m_maxDamage; +} + +bool Item::isStackedByData() { + return m_stackedByData; +} + int Item::getLevelDataForAuxValue(int) { return 0; } diff --git a/src/Minecraft.World/net/minecraft/world/item/Item.h b/src/Minecraft.World/net/minecraft/world/item/Item.h index 99756a27..9282a70b 100644 --- a/src/Minecraft.World/net/minecraft/world/item/Item.h +++ b/src/Minecraft.World/net/minecraft/world/item/Item.h @@ -73,7 +73,7 @@ class Item { unsigned int getId(); bool canBeDepleted(); std::wstring getIconName(); - void setIconName(const std::wstring&); + Item* setIconName(const std::wstring&); void setMaxDamage(int); int getMaxDamage(); void setStackedByData(bool); @@ -152,6 +152,17 @@ class Item { virtual int GetOverrideCountColour(); virtual TextureAtlasSprite* GetOverrideCountIcon(not_null_ptr itemInstance); + static unsigned int StoneBlockNameResolver(not_null_ptr); + static unsigned int StoneBlockDescResolver(not_null_ptr); + Item* setBaseItemTypeAndMaterial(int, int); + Item* setDescriptionId(int); + Item* setDescriptionId(int, int); + Item* setUseDescriptionId(int); + Item* setCraftingRemainingItem(Item*); + Item* setMaxStackSize(int); + Item* setHandEquipped(); + Item* setFlag78(bool); + static void staticCtor(); static void staticInit(); diff --git a/src/Minecraft.World/net/minecraft/world/item/ItemInstance.h b/src/Minecraft.World/net/minecraft/world/item/ItemInstance.h index 8cfecdab..51bd6942 100644 --- a/src/Minecraft.World/net/minecraft/world/item/ItemInstance.h +++ b/src/Minecraft.World/net/minecraft/world/item/ItemInstance.h @@ -5,6 +5,7 @@ #include #include +#include class Block; class BlockState; @@ -23,7 +24,7 @@ class Random; class Tag; class CensoredString; -class ItemInstance { +class ItemInstance : public std::enable_shared_from_this { public: static not_null_ptr EMPTY; @@ -53,7 +54,7 @@ class ItemInstance { void use(Level*, std::shared_ptr, InteractionHand::EInteractionHand); void finishUsingItem(Level*, std::shared_ptr); CompoundTag* save(CompoundTag*); - void getMaxStackSize(); + int getMaxStackSize(); bool hasTag(); CompoundTag* getTag(); bool isDamageableItem(); @@ -130,8 +131,6 @@ class ItemInstance { bool operator=(const ItemInstance&); private: - void* m_qword0 = nullptr; - void* m_qword8 = nullptr; int m_count; int m_dword14; Item* m_item; @@ -139,11 +138,12 @@ class ItemInstance { bool m_isEmpty; int m_damage; bool m_byte30; - void* m_qword38 = nullptr; - void* m_qword40 = nullptr; - std::shared_ptr m_censoredString; + std::weak_ptr m_frame; + std::shared_ptr m_censoredString; void* m_qword58; bool m_byte60; void* m_qword68; void* m_qword70; }; + +ASSERT_SIZEOF(ItemInstance, 0x78) diff --git a/src/Minecraft.World/net/minecraft/world/item/Items.h b/src/Minecraft.World/net/minecraft/world/item/Items.h index c41514d8..a799a198 100644 --- a/src/Minecraft.World/net/minecraft/world/item/Items.h +++ b/src/Minecraft.World/net/minecraft/world/item/Items.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "net/minecraft/client/resources/MappedRegistry.h" #include diff --git a/src/Minecraft.World/net/minecraft/world/item/LeadItem.h b/src/Minecraft.World/net/minecraft/world/item/LeadItem.h index e29b734f..c670b19d 100644 --- a/src/Minecraft.World/net/minecraft/world/item/LeadItem.h +++ b/src/Minecraft.World/net/minecraft/world/item/LeadItem.h @@ -4,5 +4,7 @@ class LeadItem : public Item { public: + LeadItem(); + ~LeadItem() override; static bool bindPlayerMobsTest(std::shared_ptr player, Level* level, const BlockPos& pos); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/Level.h b/src/Minecraft.World/net/minecraft/world/level/Level.h index 05a2cd92..0f7240e2 100644 --- a/src/Minecraft.World/net/minecraft/world/level/Level.h +++ b/src/Minecraft.World/net/minecraft/world/level/Level.h @@ -149,6 +149,7 @@ class Level : public LevelSource { ChunkSource* getChunkSource(); long long getSeed(); int getSeaLevel(); + bool setBlockAndData(int x, int y, int z, int id, int data, int flags); void setSeaLevel(int); static void enableLightingCache(); void setSpawnPos(const BlockPos&); @@ -173,6 +174,7 @@ class Level : public LevelSource { int getRawBrightness(const BlockPos&, bool); int getHeightmapHeight(int, int); int getHeightmap(int, int); + bool isSolidBlockingBlockInLoadedChunk(const BlockPos&, bool defaultValue); bool isWithinLevelBounds(int, int); int getBrightnessPropagate(LightLayer::variety, const BlockPos&); long getGameTime(); @@ -200,9 +202,13 @@ class Level : public LevelSource { bool hasChunksAt(const BlockPos&, const BlockPos&); int getAuxValueForMap(PlayerUID, int, int, int, int); std::shared_ptr getSavedData(const std::type_info&, const std::wstring&); + LevelStorage* getLevelStorage(); void setSavedData(const std::wstring&, std::shared_ptr); std::vector>* getEntitiesOfClass(const std::type_info&, AABB const*); bool shouldFreezeIgnoreNeighbors(const BlockPos&); + bool shouldFreeze(const BlockPos&, bool checkNeighbors); + bool shouldFreezeWithNeighbors(const BlockPos&); + bool isWaterAt(const BlockPos&); bool shouldSnow(const BlockPos&, bool); bool isFindingSpawn(); unsigned int countInstanceOf(eINSTANCEOF, bool, unsigned int*, unsigned int*); diff --git a/src/Minecraft.World/net/minecraft/world/level/LevelStorageAccess.cpp b/src/Minecraft.World/net/minecraft/world/level/LevelStorageAccess.cpp new file mode 100644 index 00000000..52171815 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/LevelStorageAccess.cpp @@ -0,0 +1,5 @@ +#include "net/minecraft/world/level/Level.h" + +LevelStorage* Level::getLevelStorage() { + return m_levelStorage.get(); +} diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/BeachBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/BeachBiome.h index 55836188..f0cba0b0 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/BeachBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/BeachBiome.h @@ -5,6 +5,7 @@ class BeachBiome : public Biome { public: BeachBiome(EBiomeIDs id, BiomeProperties* properties); + ~BeachBiome() override = default; int getBaseClass() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/Biome.cpp b/src/Minecraft.World/net/minecraft/world/level/biome/Biome.cpp index aa2e74fc..ff573330 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/Biome.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/biome/Biome.cpp @@ -145,10 +145,10 @@ Biome* Biome::getBiome(int id, Biome* biome) { return biome; } -Block* Biome::getRandomFlower(Random& random, const BlockPos* pos) { +FlowerBlock::Flower* Biome::getRandomFlower(Random& random, const BlockPos* pos) { if (random.nextInt(3) > 0) - return (Block*)FlowerBlock::Flower::YELLOW_FLOWER; - return (Block*)FlowerBlock::Flower::RED_FLOWER; + return FlowerBlock::Flower::YELLOW_FLOWER; + return FlowerBlock::Flower::RED_FLOWER; } unsigned int Biome::getSkyColor(float timeOfDay) { diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/Biome.h b/src/Minecraft.World/net/minecraft/world/level/biome/Biome.h index c6bafb07..8ae6617b 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/Biome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/Biome.h @@ -4,6 +4,7 @@ #include #include "net/minecraft/world/WeighedRandomItem.h" +#include "net/minecraft/world/level/block/FlowerBlock.h" #include "net/minecraft/world/level/material/MaterialColor.h" #include "net/minecraft/world/phys/Vec3.h" @@ -16,9 +17,11 @@ class MobCategory; class BiomeDecorator; class Feature; class PerlinSimplexNoise; +class DoublePlantFeature; class Biome { public: + static int getId(Biome*); static Biome* BIOMES[256]; static Biome* OCEAN; @@ -86,6 +89,8 @@ class Biome { static Biome* DEFAULT; // anything that gets a biome will fall back to this once nullptr is hit static PerlinSimplexNoise* TEMPERATURE_NOISE; + static PerlinSimplexNoise* BIOME_INFO_NOISE; + static DoublePlantFeature* DOUBLE_PLANT_FEATURE; enum EBiomeIDs : int { BiomeID_OCEAN = 0, @@ -198,6 +203,9 @@ class Biome { }; class MobSpawnerData : public WeighedRandomItem { + friend class DesertBiome; + friend class IceBiome; + public: MobSpawnerData(int instanceType, int weight, int unk, int unk2) : WeighedRandomItem(weight) { m_instanceType = instanceType; @@ -217,6 +225,15 @@ class Biome { int m_data = 0; }; + static LegacyBlockData STONE; + static LegacyBlockData AIR; + static LegacyBlockData BEDROCK; + static LegacyBlockData GRAVEL; + static LegacyBlockData RED_SANDSTONE; + static LegacyBlockData SANDSTONE; + static LegacyBlockData ICE; + static LegacyBlockData WATER; + Biome(Biome::EBiomeIDs, Biome::BiomeProperties*); static Biome** getBiomes(); static Biome* getBiome(int); @@ -227,8 +244,8 @@ class Biome { virtual ~Biome(); virtual Feature* getTreeFeature(Random&); - virtual void getGrassFeature(Random&); - virtual Block* getRandomFlower(Random&, const BlockPos*); + virtual Feature* getGrassFeature(Random&); + virtual FlowerBlock::Flower* getRandomFlower(Random&, const BlockPos*); virtual unsigned int getSkyColor(float); virtual bool hasSnow(); virtual bool hasRain(); @@ -254,9 +271,10 @@ class Biome { Biome* setNameAndDescription(int name, int desc); Biome* setPreviewColor(eMinecraftColour color); + eMinecraftColour getPreviewColor(); Biome* setWaterSkyColor(eMinecraftColour water, eMinecraftColour sky); - std::vector* getMobs(MobCategory*); + std::vector* getMobs(MobCategory*); std::wstring getName(bool); std::wstring getDescription(); diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/BiomeDecorator.h b/src/Minecraft.World/net/minecraft/world/level/biome/BiomeDecorator.h index 07e18dbf..e49289bd 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/BiomeDecorator.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/BiomeDecorator.h @@ -1,11 +1,13 @@ #pragma once +#include "net/minecraft/core/BlockPos.h" + class Level; class Random; class Biome; -class BlockPos; class Feature; -class ClayFeature; +class FlowerFeature; +class CustomizableSourceSettings; class BiomeDecorator { public: @@ -15,40 +17,47 @@ class BiomeDecorator { virtual void decorate(Biome*, Level*, Random&); virtual void decorateOres(Level*, Random&); -private: - char byte_8; - void* qword_c; - void* qword_18; - ClayFeature* field_20; - void* qword_28; - void* qword_30; - void* qword_38; - void* qword_40; - void* qword_48; - void* qword_50; - void* qword_58; - void* qword_60; - void* qword_68; - void* qword_70; - void* qword_78; - void* qword_80; - void* qword_88; - Feature* field_90; - void* field_98; - void* field_a0; - void* field_a8; - void* field_b0; - void* field_b8; - void* qword_c0; - void* qword_c8; - int dword_d0; - int dword_d4; - void* qword_d8; - void* qword_e0; - int dword_e8; - int dword_ec; - int dword_f0; - int dword_f4; - int dword_f8; - char byte_fc; + void decorateDepthSpan(Level*, Random&, int count, Feature*, int minHeight, int maxHeight); + void decorateDepthAverage(Level*, Random&, int count, Feature*, int centerHeight, int spread); + + bool m_decorating; + BlockPos m_origin; + CustomizableSourceSettings* m_settings; + Feature* m_clay; + Feature* m_sand; + Feature* m_gravelPatch; + Feature* m_dirt; + Feature* m_gravel; + Feature* m_granite; + Feature* m_diorite; + Feature* m_andesite; + Feature* m_coal; + Feature* m_iron; + Feature* m_gold; + Feature* m_redstone; + Feature* m_diamond; + Feature* m_lapis; + FlowerFeature* m_flowers; + Feature* m_brownMushrooms; + Feature* m_redMushrooms; + Feature* m_hugeMushrooms; + Feature* m_reeds; + Feature* m_cactus; + Feature* m_waterlilies; + int m_waterlilyCount; + int m_treeCount; + float m_extraTreeChance; + int m_flowerCount; + int m_grassCount; + int m_deadBushCount; + int m_mushroomCount; + int m_reedCount; + int m_cactusCount; + int m_gravelPatchCount; + int m_sandCount; + int m_clayCount; + int m_hugeMushroomCount; + bool m_generateLiquids; }; + +static_assert(sizeof(BiomeDecorator) == 0x100, "Switch biome decorator layout"); diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/BiomeSource.cpp b/src/Minecraft.World/net/minecraft/world/level/biome/BiomeSource.cpp index e12833b2..d26ceb48 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/BiomeSource.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/biome/BiomeSource.cpp @@ -1,5 +1,7 @@ #include "net/minecraft/world/level/biome/BiomeSource.h" + #include +#include #include "NX/Platform.h" #include "net/minecraft/client/Minecraft.h" @@ -113,7 +115,7 @@ void BiomeSource::LayerOverrideSettings::NullBiomeSection(int x, int z, int widt int end = depth + width; unsigned long len = z * sizeof(Biome*); for (int i = width; i < end; i++) { - memset((void*)&m_biomes[x + m_imageWidth * i], 0, len); + memset((void*)&m_biomes.get(x + m_imageWidth * i), 0, len); } } @@ -198,7 +200,7 @@ Biome* BiomeSource::LayerOverrideSettings::GetBiomeAt(float x, float z) { zPos = zThreshold; unsigned int index = getBiomeIndex(xPos, zPos); - return m_biomes[index]; + return m_biomes.get(index); } BiomeSource::CouldSpawnCache::CouldSpawnCache(BiomeSource* biomeSource, @@ -294,7 +296,7 @@ bool BiomeSource::fjCouldSpawn(const FjFeatureBiomeRequirements* biomeRequiremen } BiomeSource::~BiomeSource() { - nn::os::FinalizeMutex(&m_mutexType); + DeleteCriticalSection(&m_mutexType); delete m_biomeCache; } @@ -322,7 +324,7 @@ void BiomeSource::getRawBiomeBlock(arrayWithLength& biomes, int x, int z PIXBeginNamedEvent(0.0, "Copying values"); for (int i = 0; i < width * depth; i++) { - biomes[i] = Biome::getBiome(area[i], Biome::DEFAULT); + biomes.get(i) = Biome::getBiome(area[i], Biome::DEFAULT); } PIXEndNamedEvent(); } @@ -362,7 +364,7 @@ void BiomeSource::getBiomeBlock(arrayWithLength& biomes, int x, int z, i PIXBeginNamedEvent(0.0, "Copying values"); for (int i = 0; i < width * depth; i++) { - biomes[i] = Biome::getBiome(area[i], Biome::DEFAULT); + biomes.get(i) = Biome::getBiome(area[i], Biome::DEFAULT); } PIXEndNamedEvent(); } diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/DesertBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/DesertBiome.h index 218bf613..a98cf144 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/DesertBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/DesertBiome.h @@ -7,4 +7,5 @@ class DesertBiome : public Biome { DesertBiome(EBiomeIDs id, BiomeProperties* properties); int getBaseClass() override; + void decorate(Level*, Random&, const BlockPos&) override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/ExtremeHillsBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/ExtremeHillsBiome.h index 274f28fe..3d99c95b 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/ExtremeHillsBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/ExtremeHillsBiome.h @@ -2,15 +2,23 @@ #include "net/minecraft/world/level/biome/Biome.h" +class OreFeature; + class ExtremeHillsBiome : public Biome { public: enum EType { DEFAULT = 0, EDGE = 1, M = 2 }; ExtremeHillsBiome(EBiomeIDs id, EType type, BiomeProperties* properties); + ~ExtremeHillsBiome() override; int getBaseClass() override; + Feature* getTreeFeature(Random&) override; + void decorate(Level*, Random&, const BlockPos&) override; + void buildSurfaceAt(Level*, Random&, ChunkPrimer*, int, int, double) override; - char m_padding[0x10]; +private: + OreFeature* m_oreFeature; + EType m_type; }; ASSERT_SIZEOF(ExtremeHillsBiome, 0x158) diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/ForestBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/ForestBiome.h index d4c0d3b0..0803b9de 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/ForestBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/ForestBiome.h @@ -7,6 +7,18 @@ class ForestBiome : public Biome { enum EType { DEFAULT = 0, FLOWER = 1, BIRCH = 2, ROOFED = 3 }; ForestBiome(EBiomeIDs id, EType type, BiomeProperties* properties); + ~ForestBiome() override = default; int getBaseClass() override; + Feature* getTreeFeature(Random&) override; + FlowerBlock::Flower* getRandomFlower(Random&, const BlockPos*) override; + unsigned int getGrassColor(const BlockPos*) override; + void decorate(Level*, Random&, const BlockPos&) override; + void addMushrooms(Level*, Random&, const BlockPos&); + void addDoublePlants(Level*, Random&, const BlockPos&, int); + +private: + EType m_type; }; + +ASSERT_SIZEOF(ForestBiome, 0x148) diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/HellBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/HellBiome.h index 09420259..e6c746e9 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/HellBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/HellBiome.h @@ -5,6 +5,11 @@ class HellBiome : public Biome { public: HellBiome(EBiomeIDs id, BiomeProperties* properties); + ~HellBiome() override = default; int getBaseClass() override; + unsigned int getSkyColor(float) override; + Vec3* getFogColor(float, float) const override; + bool isFoggy() override; + bool isNatural() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/IceBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/IceBiome.h index 5256b041..a482a5d5 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/IceBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/IceBiome.h @@ -6,11 +6,17 @@ class IceBiome : public Biome { public: enum EType { DEFAULT = 0, SPIKES = 1 }; - IceBiome(EBiomeIDs id, EType type, BiomeProperties* properties); + IceBiome(EBiomeIDs id, bool spikes, BiomeProperties* properties); int getBaseClass() override; + float getCreatureProbability() override; + Feature* getTreeFeature(Random&) override; + void decorate(Level*, Random&, const BlockPos&) override; - char m_padding[0x10]; +private: + bool m_spikes; + Feature* m_spikeFeature; + Feature* m_patchFeature; }; ASSERT_SIZEOF(IceBiome, 0x158) diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/JungleBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/JungleBiome.h index 1d503b0b..97f19c49 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/JungleBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/JungleBiome.h @@ -6,7 +6,19 @@ class JungleBiome : public Biome { public: enum EType { DEFAULT = 0, EDGE = 1 }; - JungleBiome(EBiomeIDs id, EType type, BiomeProperties* properties); + JungleBiome(EBiomeIDs id, bool edge, BiomeProperties* properties); + static void staticCtor(); int getBaseClass() override; + Feature* getTreeFeature(Random&) override; + Feature* getGrassFeature(Random&) override; + void decorate(Level*, Random&, const BlockPos&) override; + +private: + static const BlockState* TRUNK; + static const BlockState* LEAVES; + static const BlockState* BUSH_LEAVES; + bool m_edge; }; + +ASSERT_SIZEOF(JungleBiome, 0x148) diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/MesaBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/MesaBiome.h index 1675830c..4b6c5a92 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/MesaBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/MesaBiome.h @@ -1,15 +1,43 @@ #pragma once #include "net/minecraft/world/level/biome/Biome.h" +#include "net/minecraft/world/level/biome/BiomeDecorator.h" #include "types.h" class MesaBiome : public Biome { public: - MesaBiome(EBiomeIDs id, bool, bool, BiomeProperties* properties); + class MesaDecorator : public BiomeDecorator { + public: + MesaDecorator() = default; + void decorateOres(Level*, Random&) override; + }; + static LegacyBlockData COARSE_DIRT; + static LegacyBlockData GRASS; + static LegacyBlockData HARDENED_CLAY; + static LegacyBlockData STAINED_HARDENED_CLAY; + static LegacyBlockData ORANGE_CLAY; + static LegacyBlockData RED_SAND; + static void staticCtor(); + + MesaBiome(EBiomeIDs id, bool bryce, bool forest, BiomeProperties* properties); + ~MesaBiome() override; int getBaseClass() override; + Feature* getTreeFeature(Random&) override; + unsigned int getGrassColor(const BlockPos*) override; + unsigned int getFoliageColor(const BlockPos*) override; + void buildSurfaceAt(Level*, Random&, ChunkPrimer*, int, int, double) override; + + void generateBands(long long seed); + LegacyBlockData getBand(int x, int y, int z); - char m_padding[0x30]; + LegacyBlockData* m_clayBands; + long long m_seed; + PerlinSimplexNoise* m_pillarNoise; + PerlinSimplexNoise* m_pillarRoofNoise; + PerlinSimplexNoise* m_clayBandsOffsetNoise; + bool m_bryce; + bool m_forest; }; ASSERT_SIZEOF(MesaBiome, 0x178) diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/MushroomIslandBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/MushroomIslandBiome.h index d3f665aa..4ffa6c07 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/MushroomIslandBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/MushroomIslandBiome.h @@ -5,6 +5,7 @@ class MushroomIslandBiome : public Biome { public: MushroomIslandBiome(EBiomeIDs id, BiomeProperties* properties); + ~MushroomIslandBiome() override = default; int getBaseClass() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/MutatedForestBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/MutatedForestBiome.h index 03f9c5c5..179221bd 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/MutatedForestBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/MutatedForestBiome.h @@ -1,10 +1,10 @@ #pragma once -#include "net/minecraft/world/level/biome/Biome.h" +#include "net/minecraft/world/level/biome/ForestBiome.h" -class MutatedForestBiome : public Biome { +class MutatedForestBiome : public ForestBiome { public: MutatedForestBiome(EBiomeIDs id, BiomeProperties* properties); - int getBaseClass() override; + Feature* getTreeFeature(Random&) override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/MutatedSavannaBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/MutatedSavannaBiome.h index 2683132f..aef574e4 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/MutatedSavannaBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/MutatedSavannaBiome.h @@ -1,10 +1,11 @@ #pragma once -#include "net/minecraft/world/level/biome/Biome.h" +#include "net/minecraft/world/level/biome/SavannaBiome.h" -class MutatedSavannaBiome : public Biome { +class MutatedSavannaBiome : public SavannaBiome { public: MutatedSavannaBiome(EBiomeIDs id, BiomeProperties* properties); - int getBaseClass() override; + void buildSurfaceAt(Level*, Random&, ChunkPrimer*, int, int, double) override; + void decorate(Level*, Random&, const BlockPos&) override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/OceanBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/OceanBiome.h index 63c22a85..932ec5f7 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/OceanBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/OceanBiome.h @@ -5,6 +5,8 @@ class OceanBiome : public Biome { public: OceanBiome(EBiomeIDs id, BiomeProperties* properties); + ~OceanBiome() override = default; int getBaseClass() override; + int getTemperatureCategory() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/PlainsBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/PlainsBiome.h index 582a3980..ed887a32 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/PlainsBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/PlainsBiome.h @@ -5,6 +5,15 @@ class PlainsBiome : public Biome { public: PlainsBiome(EBiomeIDs id, bool, BiomeProperties* properties); + ~PlainsBiome() override = default; int getBaseClass() override; + Feature* getTreeFeature(Random&) override; + FlowerBlock::Flower* getRandomFlower(Random&, const BlockPos*) override; + void decorate(Level*, Random&, const BlockPos&) override; + +private: + bool m_sunflowers; }; + +ASSERT_SIZEOF(PlainsBiome, 0x148) diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/RiverBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/RiverBiome.h index 716c777f..ef12394b 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/RiverBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/RiverBiome.h @@ -5,6 +5,7 @@ class RiverBiome : public Biome { public: RiverBiome(EBiomeIDs id, BiomeProperties* properties); + ~RiverBiome() override = default; int getBaseClass() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/SavannaBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/SavannaBiome.h index 0736cc5f..c88c4173 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/SavannaBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/SavannaBiome.h @@ -7,4 +7,6 @@ class SavannaBiome : public Biome { SavannaBiome(EBiomeIDs id, BiomeProperties* properties); int getBaseClass() override; + Feature* getTreeFeature(Random&) override; + void decorate(Level*, Random&, const BlockPos&) override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/StoneBeachBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/StoneBeachBiome.h index b8ac5286..49db2bb8 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/StoneBeachBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/StoneBeachBiome.h @@ -5,6 +5,7 @@ class StoneBeachBiome : public Biome { public: StoneBeachBiome(EBiomeIDs id, BiomeProperties* properties); + ~StoneBeachBiome() override = default; int getBaseClass() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/SwampBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/SwampBiome.h index 9e7a3c7d..dda65f28 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/SwampBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/SwampBiome.h @@ -5,8 +5,17 @@ class SwampBiome : public Biome { public: SwampBiome(EBiomeIDs id, BiomeProperties* properties); + ~SwampBiome() override = default; int getBaseClass() override; + Feature* getTreeFeature(Random&) override; + FlowerBlock::Flower* getRandomFlower(Random&, const BlockPos*) override; + unsigned int getGrassColor(const BlockPos*) override; + unsigned int getFoliageColor(const BlockPos*) override; + void decorate(Level*, Random&, const BlockPos&) override; + void buildSurfaceAt(Level*, Random&, ChunkPrimer*, int, int, double) override; + + static LegacyBlockData WATERLILY; void* m_padding; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/TaigaBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/TaigaBiome.h index 3e5a8ed8..bfe6f492 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/TaigaBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/TaigaBiome.h @@ -7,6 +7,16 @@ class TaigaBiome : public Biome { enum EType { DEFAULT = 0, MEGA = 1, MEGA_SPRUCE = 2 }; TaigaBiome(EBiomeIDs id, EType type, BiomeProperties* properties); + ~TaigaBiome() override = default; int getBaseClass() override; + Feature* getTreeFeature(Random&) override; + Feature* getGrassFeature(Random&) override; + void decorate(Level*, Random&, const BlockPos&) override; + void buildSurfaceAt(Level*, Random&, ChunkPrimer*, int, int, double) override; + +private: + EType m_type; }; + +ASSERT_SIZEOF(TaigaBiome, 0x148) diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/TheEndBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/TheEndBiome.h index 1e1876ec..a0df69e3 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/TheEndBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/TheEndBiome.h @@ -5,6 +5,10 @@ class TheEndBiome : public Biome { public: TheEndBiome(EBiomeIDs id, BiomeProperties* properties); + ~TheEndBiome() override = default; int getBaseClass() override; + unsigned int getSkyColor(float) override; + Vec3* getFogColor(float, float) const override; + bool isNatural() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/biome/VoidBiome.h b/src/Minecraft.World/net/minecraft/world/level/biome/VoidBiome.h index 7bac67ec..de318de8 100644 --- a/src/Minecraft.World/net/minecraft/world/level/biome/VoidBiome.h +++ b/src/Minecraft.World/net/minecraft/world/level/biome/VoidBiome.h @@ -7,4 +7,5 @@ class VoidBiome : public Biome { VoidBiome(EBiomeIDs id, BiomeProperties* properties); int getBaseClass() override; + bool isAlwaysValidSpawn() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/Block.cpp b/src/Minecraft.World/net/minecraft/world/level/block/Block.cpp index 0ce58cab..b0d28dcf 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/Block.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/block/Block.cpp @@ -1,5 +1,7 @@ #include "net/minecraft/world/level/block/Block.h" +#include "net/minecraft/world/level/block/BlockBootstrapAllocation.h" + #include "net/minecraft/client/resources/IdMapper.h" #include "net/minecraft/core/Direction.h" #include "net/minecraft/stats/Stats.h" @@ -944,7 +946,7 @@ const Vec3* ZERO = new Vec3(0, 0, 0); Vec3* Block::getOffset(const BlockState* state, LevelSource* levelSource, const BlockPos& pos) { int offsetType = this->getOffsetType(); if (!offsetType) - return Vec3::newTemp(ZERO); + return Vec3::newTemp(Vec3::ZERO); int64_t seed = Mth::getSeed(pos.getX(), 0, pos.getZ()); return Vec3::newTemp((((seed >> 16 & 0xF) / 15.0f) - 0.5) * 0.5, @@ -979,20 +981,10 @@ bool Block::isExceptionBlockForAttachingPlusPiston(Block* block) { return Block::isExceptionBlockForAttaching(block); } -// NON_MATCHING | Score: 333111 (lower is better) -// This is the second-largest method in the entire executable -// I (Dexrn) automated the block registry code, but I'm not sure how well it worked -// Also, there's stuff missing at both the header and the footer... so it won't match until that's done. -// Additionally, it seems that setBaseItemTypeAndMaterial is sometimes called outside of the chain... -// e.g: -// Block *someBlock = new SomeBlock() -// ->setDestroyTime(0) -// ->setExplodeable(10.0); -// someBlock->setBaseItemTypeAndMaterial(14, 2); -// Block::registerBlock(1, L"some_block", someBlock); -// -// The size given in the comments above every block was from the `operator new` call to allocate space for the -// block This gives us the class size of every block that is registered. +// NON_MATCHING: the registration phase now agrees with original ARM64 call +// traces, but the complete initializer still differs in its instructions. +// The original new sizes also cover fields absent from partial block headers; +// BlockBootstrapAllocation preserves those allocations without inventing layouts. void Block::staticCtor() { DEFAULT_FACING = DirectionProperty::create(L"facing"); HORIZONTAL_FACING = DirectionProperty::create(L"facing", Direction::Plane::HORIZONTAL); @@ -1080,7 +1072,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock( 2, L"grass", - (new GrassBlock()) + (new (BlockBootstrapAllocation<0xc8>{}) GrassBlock()) ->setDestroyTime(0.6) ->setSoundType(SoundType::GRASS) ->setIconName(L"grass") @@ -1119,15 +1111,15 @@ void Block::staticCtor() { Block::registerBlock(5, L"planks", planksBlock); - Block* saplingBlock - = (new SaplingBlock()) - ->setDestroyTime(0.0) - ->setSoundType(SoundType::GRASS) - ->setIconName(L"sapling") - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::Sapling, StringIDs::CanBePlantedAndWillEventuallyGrowInto) - ->disableMipmap(); - Block::registerBlock(6, L"sapling", saplingBlock); + Block::registerBlock( + 6, L"sapling", + (new (BlockBootstrapAllocation<0xe0>{}) SaplingBlock()) + ->setDestroyTime(0.0) + ->setSoundType(SoundType::GRASS) + ->setIconName(L"sapling") + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::Sapling, StringIDs::CanBePlantedAndWillEventuallyGrowInto) + ->disableMipmap()); Block::registerBlock(7, L"bedrock", (new BlockImpl(Material::STONE)) @@ -1141,7 +1133,7 @@ void Block::staticCtor() { // Size: 0xF0u Block::registerBlock( 8, L"flowing_water", - (new DynamicLiquidBlock(Material::WATER)) + (new (BlockBootstrapAllocation<0xf0>{}) DynamicLiquidBlock(Material::WATER)) ->setDestroyTime(100.0) ->setLightBlock(3) ->setIconName(L"water_flow") @@ -1152,7 +1144,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 9, L"water", - (new StaticLiquidBlock(Material::WATER)) + (new (BlockBootstrapAllocation<0xb8>{}) StaticLiquidBlock(Material::WATER)) ->setDestroyTime(100.0) ->setLightBlock(3) ->setIconName(L"water_still") @@ -1163,7 +1155,7 @@ void Block::staticCtor() { // Size: 0xF0u Block::registerBlock( 10, L"flowing_lava", - (new DynamicLiquidBlock(Material::LAVA)) + (new (BlockBootstrapAllocation<0xf0>{}) DynamicLiquidBlock(Material::LAVA)) ->setDestroyTime(100.0) ->setLightEmission(1.0) ->setIconName(L"lava_flow") @@ -1175,7 +1167,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 11, L"lava", - (new StaticLiquidBlock(Material::LAVA)) + (new (BlockBootstrapAllocation<0xb8>{}) StaticLiquidBlock(Material::LAVA)) ->setDestroyTime(100.0) ->setLightEmission(1.0) ->setIconName(L"lava_still") @@ -1244,7 +1236,7 @@ void Block::staticCtor() { // Size: 0x110u Block::registerBlock(18, L"leaves", - (new OldLeafBlock()) + (new (BlockBootstrapAllocation<0x110>{}) OldLeafBlock()) ->setIconName(L"leaves") ->sendBlockData(3) ->setNameAndDescriptionId(StringIDs::Leaves, @@ -1253,7 +1245,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 19, L"sponge", - (new SpongeBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) SpongeBlock()) ->setDestroyTime(0.6) ->setSoundType(SoundType::GRASS) ->setIconName(L"sponge") @@ -1294,7 +1286,7 @@ void Block::staticCtor() { // Size: 0xE0u Block::registerBlock( 23, L"dispenser", - (new DispenserBlock()) + (new (BlockBootstrapAllocation<0xe0>{}) DispenserBlock()) ->setDestroyTime(3.5) ->setSoundType(SoundType::STONE) ->setIconName(L"dispenser") @@ -1316,7 +1308,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(25, L"noteblock", - (new NoteBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) NoteBlock()) ->setSoundType(SoundType::WOOD) ->setDestroyTime(0.8) ->setIconName(L"noteblock") @@ -1327,7 +1319,7 @@ void Block::staticCtor() { // Size: 0xE0u Block::registerBlock( 26, L"bed", - (new BedBlock()) + (new (BlockBootstrapAllocation<0xe0>{}) BedBlock()) ->setSoundType(SoundType::WOOD) ->setDestroyTime(0.2) ->setIconName(L"bed") @@ -1338,7 +1330,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 27, L"golden_rail", - (new PoweredRailBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) PoweredRailBlock()) ->setDestroyTime(0.7) ->setSoundType(SoundType::METAL) ->setIconName(L"rail_golden") @@ -1350,7 +1342,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(28, L"detector_rail", - (new DetectorRailBlock()) + (new (BlockBootstrapAllocation<0xb8>{}) DetectorRailBlock()) ->setDestroyTime(0.7) ->setSoundType(SoundType::METAL) ->setIconName(L"rail_detector") @@ -1363,7 +1355,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 29, L"sticky_piston", - (new PistonBaseBlock(true)) + (new (BlockBootstrapAllocation<0xc0>{}) PistonBaseBlock(true)) ->sendBlockData(15) ->setNameAndDescriptionId(StringIDs::StickyPiston, StringIDs::WhenPoweredUsingAButtonALeverARetractsPullsBackBlockTouching) @@ -1383,7 +1375,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock( 31, L"tallgrass", - (new TallGrassBlock()) + (new (BlockBootstrapAllocation<0xc8>{}) TallGrassBlock()) ->setDestroyTime(0.0) ->setSoundType(SoundType::GRASS) ->setIconName(L"tallgrass") @@ -1402,7 +1394,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 33, L"piston", - (new PistonBaseBlock(false)) + (new (BlockBootstrapAllocation<0xc0>{}) PistonBaseBlock(false)) ->sendBlockData(15) ->setNameAndDescriptionId(StringIDs::Piston, StringIDs::WhenPoweredUsingAButtonALeverA) ->setBaseItemTypeAndMaterial(27, 28) @@ -1411,13 +1403,13 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 34, L"piston_head", - (new PistonHeadBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) PistonHeadBlock()) ->setNameAndDescriptionId(StringIDs::Piston, StringIDs::WhenPoweredUsingAButtonALeverA) ->sendBlockData(15)); // Size: 0x128u Block::registerBlock(35, L"wool", - (new ColoredBlock(Material::WOOL)) + (new (BlockBootstrapAllocation<0x128>{}) ColoredBlock(Material::WOOL)) ->setDestroyTime(0.8) ->setSoundType(SoundType::WOOL) ->setIconName(L"wool_colored") @@ -1427,7 +1419,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(36, L"piston_extension", - (new PistonMagicBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) PistonMagicBlock()) ->setIconName(L"pistonBase") ->setNameAndDescriptionId(StringIDs::Piston, 0xFFFFFFFF)); @@ -1494,7 +1486,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(43, L"double_stone_slab", - (new FullStoneSlabBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) FullStoneSlabBlock()) ->setDestroyTime(2.0) ->setExplodeable(10.0) ->setSoundType(SoundType::STONE) @@ -1505,7 +1497,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(44, L"stone_slab", - (new HalfStoneSlabBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) HalfStoneSlabBlock()) ->setDestroyTime(2.0) ->setExplodeable(10.0) ->setSoundType(SoundType::STONE) @@ -1526,7 +1518,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(46, L"tnt", - (new TntBlock()) + (new (BlockBootstrapAllocation<0xb8>{}) TntBlock()) ->setDestroyTime(0.0) ->setSoundType(SoundType::GRASS) ->setIconName(L"tnt") @@ -1593,7 +1585,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(52, L"mob_spawner", - (new MobSpawnerBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) MobSpawnerBlock()) ->setDestroyTime(5.0) ->setSoundType(SoundType::METAL) ->setIconName(L"mob_spawner") @@ -1601,20 +1593,20 @@ void Block::staticCtor() { ->setNameAndDescriptionId(StringIDs::MonsterSpawner, 0x4330c9)); // Size: 0xC0u - const BlockState* stairBlockVariant = planksBlock->defaultBlockState()->setValue( - PlanksBlock::VARIANT, PlanksBlock::Variant::OAK); - Block* stairBlock - = (new StairBlock(stairBlockVariant)) - ->setIconName(L"stairsWood") - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::OakWoodStairs, StringIDs::UsedForCompactStaircases_1) - ->setBaseItemTypeAndMaterial(16, 1); - Block::registerBlock(53, L"oak_stairs", stairBlock); + Block::registerBlock( + 53, L"oak_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(planksBlock->defaultBlockState()->setValue( + PlanksBlock::VARIANT, PlanksBlock::Variant::OAK))) + ->setIconName(L"stairsWood") + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::OakWoodStairs, StringIDs::UsedForCompactStaircases_1) + ->setBaseItemTypeAndMaterial(16, 1)); // Size: 0xB8u Block::registerBlock( 54, L"chest", - (new ChestBlock(0)) + (new (BlockBootstrapAllocation<0xb8>{}) ChestBlock(0)) ->setDestroyTime(2.5) ->setSoundType(SoundType::WOOD) ->setIconName(L"chest") @@ -1625,7 +1617,7 @@ void Block::staticCtor() { // Size: 0xF8u Block::registerBlock( 55, L"redstone_wire", - (new RedStoneWireBlock()) + (new (BlockBootstrapAllocation<0xf8>{}) RedStoneWireBlock()) ->setDestroyTime(0.0) ->setSoundType(SoundType::STONE) ->setIconName(L"redstone_dust") @@ -1657,7 +1649,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(58, L"crafting_table", - (new CraftingTableBlock()) + (new (BlockBootstrapAllocation<0xb8>{}) CraftingTableBlock()) ->setDestroyTime(2.5) ->setSoundType(SoundType::WOOD) ->setIconName(L"crafting_table") @@ -1668,7 +1660,7 @@ void Block::staticCtor() { // Size: 0xF0u Block::registerBlock( 59, L"wheat", - (new CropBlock(false)) + (new (BlockBootstrapAllocation<0xf0>{}) CropBlock(false)) ->setIconName(L"wheat") ->setNotCollectStatistics() ->sendBlockData(15) @@ -1676,7 +1668,7 @@ void Block::staticCtor() { ->disableMipmap()); // Size: 0xB8u - Block* farmBlock = (new FarmBlock()) + Block* farmBlock = (new (BlockBootstrapAllocation<0xb8>{}) FarmBlock()) ->setDestroyTime(0.6) ->setSoundType(SoundType::DIRT) ->setIconName(L"farmland") @@ -1688,7 +1680,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock( 61, L"furnace", - (new FurnaceBlock(false)) + (new (BlockBootstrapAllocation<0xc8>{}) FurnaceBlock(false)) ->setDestroyTime(3.5) ->setSoundType(SoundType::STONE) ->setIconName(L"furnace") @@ -1699,7 +1691,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock( 62, L"lit_furnace", - (new FurnaceBlock(true)) + (new (BlockBootstrapAllocation<0xc8>{}) FurnaceBlock(true)) ->setDestroyTime(3.5) ->setSoundType(SoundType::STONE) ->setIconName(L"furnace") @@ -1710,7 +1702,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 63, L"standing_sign", - (new StandingSignBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) StandingSignBlock()) ->setDestroyTime(1.0) ->setSoundType(SoundType::WOOD) ->setIconName(L"sign") @@ -1720,7 +1712,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock(64, L"wooden_door", - (new DoorBlock(Material::WOOD)) + (new (BlockBootstrapAllocation<0xc8>{}) DoorBlock(Material::WOOD)) ->setDestroyTime(3.0) ->setSoundType(SoundType::WOOD) ->setIconName(L"door_wood") @@ -1742,7 +1734,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(66, L"rail", - (new RailBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) RailBlock()) ->setDestroyTime(0.7) ->setSoundType(SoundType::METAL) ->setIconName(L"rail_normal") @@ -1754,7 +1746,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 67, L"stone_stairs", - (new StairBlock(cobblestoneBlock->defaultBlockState())) + (new (BlockBootstrapAllocation<0xc0>{}) StairBlock(cobblestoneBlock->defaultBlockState())) ->setIconName(L"stairsStone") ->sendBlockData(15) ->setNameAndDescriptionId(StringIDs::CobblestoneStairs, StringIDs::UsedForCompactStaircases_1) @@ -1763,7 +1755,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 68, L"wall_sign", - (new WallSignBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) WallSignBlock()) ->setDestroyTime(1.0) ->setSoundType(SoundType::WOOD) ->setIconName(L"sign") @@ -1784,20 +1776,20 @@ void Block::staticCtor() { ->setBaseItemTypeAndMaterial(45, 1)); // Size: 0xC8u - Block::registerBlock( - 70, L"stone_pressure_plate", - (new PressurePlateBlock(L"stone", Material::STONE, PressurePlateBlock::Sensitivity::STONE)) - ->setDestroyTime(0.5) - ->setSoundType(SoundType::STONE) - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::StonePressurePlate, - StringIDs::APressureSensitivePadThatWillActivateWhen) - ->setBaseItemTypeAndMaterial(15, 2)); + Block::registerBlock(70, L"stone_pressure_plate", + (new (BlockBootstrapAllocation<0xc8>{}) PressurePlateBlock( + L"stone", Material::STONE, PressurePlateBlock::Sensitivity::STONE)) + ->setDestroyTime(0.5) + ->setSoundType(SoundType::STONE) + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::StonePressurePlate, + StringIDs::APressureSensitivePadThatWillActivateWhen) + ->setBaseItemTypeAndMaterial(15, 2)); // Size: 0xC8u Block::registerBlock( 71, L"iron_door", - (new DoorBlock(Material::METAL)) + (new (BlockBootstrapAllocation<0xc8>{}) DoorBlock(Material::METAL)) ->setIconName(L"door_iron") ->setDestroyTime(5.0) ->setSoundType(SoundType::METAL) @@ -1808,7 +1800,8 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock( 72, L"wooden_pressure_plate", - (new PressurePlateBlock(L"planks_oak", Material::WOOD, PressurePlateBlock::Sensitivity::WOOD)) + (new (BlockBootstrapAllocation<0xc8>{}) + PressurePlateBlock(L"planks_oak", Material::WOOD, PressurePlateBlock::Sensitivity::WOOD)) ->setDestroyTime(0.5) ->setSoundType(SoundType::WOOD) ->sendBlockData(15) @@ -1910,7 +1903,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 81, L"cactus", - (new CactusBlock()) + (new (BlockBootstrapAllocation<0xb8>{}) CactusBlock()) ->setIconName(L"cactus") ->setDestroyTime(0.4) ->setSoundType(SoundType::WOOL) @@ -1940,7 +1933,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(84, L"jukebox", - (new JukeboxBlock()) + (new (BlockBootstrapAllocation<0xb8>{}) JukeboxBlock()) ->setIconName(L"jukebox") ->setDestroyTime(2.0) ->setExplodeable(10.0) @@ -1952,7 +1945,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 85, L"fence", - (new FenceBlock(L"planks_oak", Material::WOOD, PlanksBlock::Variant::OAK->getMaterialColor())) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceBlock(L"planks_oak", Material::WOOD, PlanksBlock::Variant::OAK->getMaterialColor())) ->setDestroyTime(2.0) ->setExplodeable(5.0) ->setSoundType(SoundType::WOOD) @@ -1961,7 +1955,7 @@ void Block::staticCtor() { // Size: 0xD8u Block* pumpkinBlock - = (new PumpkinBlock()) + = (new (BlockBootstrapAllocation<0xd8>{}) PumpkinBlock()) ->setIconName(L"pumpkin") ->setDestroyTime(1.0) ->setSoundType(SoundType::WOOD) @@ -2010,7 +2004,7 @@ void Block::staticCtor() { // Size: 0xD8u Block::registerBlock(91, L"lit_pumpkin", - (new PumpkinBlock()) + (new (BlockBootstrapAllocation<0xd8>{}) PumpkinBlock()) ->setIconName(L"pumpkin") ->setDestroyTime(1.0) ->setSoundType(SoundType::WOOD) @@ -2022,7 +2016,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 92, L"cake", - (new CakeBlock()) + (new (BlockBootstrapAllocation<0xc0>{}) CakeBlock()) ->setIconName(L"cake") ->setDestroyTime(0.5) ->setSoundType(SoundType::WOOL) @@ -2059,7 +2053,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 95, L"stained_glass", - (new StainedGlassBlock(Material::GLASS)) + (new (BlockBootstrapAllocation<0xc0>{}) StainedGlassBlock(Material::GLASS)) ->setIconName(L"glass") ->setDestroyTime(0.3) ->setSoundType(SoundType::GLASS) @@ -2103,7 +2097,8 @@ void Block::staticCtor() { // Size: 0xD8u Block::registerBlock( 99, L"brown_mushroom_block", - (new HugeMushroomBlock(Material::WOOD, MaterialColor::DIRT, brownMushroomBlock)) + (new (BlockBootstrapAllocation<0xd8>{}) + HugeMushroomBlock(Material::WOOD, MaterialColor::DIRT, brownMushroomBlock)) ->setIconName(L"mushroom_block") ->setDestroyTime(0.2) ->setSoundType(SoundType::WOOD) @@ -2113,7 +2108,8 @@ void Block::staticCtor() { // Size: 0xD8u Block::registerBlock( 100, L"red_mushroom_block", - (new HugeMushroomBlock(Material::WOOD, MaterialColor::COLOR_RED, redMushroomBlock)) + (new (BlockBootstrapAllocation<0xd8>{}) + HugeMushroomBlock(Material::WOOD, MaterialColor::COLOR_RED, redMushroomBlock)) ->setIconName(L"mushroom_block") ->setDestroyTime(0.2) ->setSoundType(SoundType::WOOD) @@ -2123,7 +2119,8 @@ void Block::staticCtor() { // Size: 0xE0u Block::registerBlock( 101, L"iron_bars", - (new ThinFenceBlock(L"iron_bars", L"iron_bars", Material::METAL, true)) + (new (BlockBootstrapAllocation<0xe0>{}) + ThinFenceBlock(L"iron_bars", L"iron_bars", Material::METAL, true)) ->setDestroyTime(5.0) ->setExplodeable(10.0) ->setSoundType(SoundType::METAL) @@ -2133,7 +2130,8 @@ void Block::staticCtor() { // Size: 0xE0u Block::registerBlock( 102, L"glass_pane", - (new ThinFenceBlock(L"glass", L"glass_pane_top", Material::GLASS, false)) + (new (BlockBootstrapAllocation<0xe0>{}) + ThinFenceBlock(L"glass", L"glass_pane_top", Material::GLASS, false)) ->setDestroyTime(0.3) ->setSoundType(SoundType::GLASS) ->setNameAndDescriptionId(StringIDs::GlassPane, StringIDs::TransparentBlocksThatCanBeUsedAsAn) @@ -2141,7 +2139,7 @@ void Block::staticCtor() { // Size: 0xB0u Block* melonBlock - = (new MelonBlock()) + = (new (BlockBootstrapAllocation<0xb0>{}) MelonBlock()) ->setIconName(L"melon") ->setDestroyTime(1.0) ->setSoundType(SoundType::WOOD) @@ -2150,7 +2148,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock(104, L"pumpkin_stem", - (new StemBlock(pumpkinBlock)) + (new (BlockBootstrapAllocation<0xc0>{}) StemBlock(pumpkinBlock)) ->setIconName(L"pumpkin_stem") ->setDestroyTime(0.0) ->setSoundType(SoundType::WOOD) @@ -2160,7 +2158,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock(105, L"melon_stem", - (new StemBlock(melonBlock)) + (new (BlockBootstrapAllocation<0xc0>{}) StemBlock(melonBlock)) ->setIconName(L"melon_stem") ->setDestroyTime(0.0) ->setSoundType(SoundType::WOOD) @@ -2180,33 +2178,33 @@ void Block::staticCtor() { ->disableMipmap()); // Size: 0xC0u - Block::registerBlock(107, L"fence_gate", - (new FenceGateBlock(L"planks_oak", PlanksBlock::Variant::OAK)) - ->setIconName(L"fenceGate") - ->setDestroyTime(2.0) - ->setExplodeable(5.0) - ->setSoundType(SoundType::WOOD) - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::OakFenceGate, - StringIDs::SimilarToADoorButUsedPrimarilyWithFences) - ->setBaseItemTypeAndMaterial(47, 1)); + Block::registerBlock( + 107, L"fence_gate", + (new (BlockBootstrapAllocation<0xc0>{}) FenceGateBlock(L"planks_oak", PlanksBlock::Variant::OAK)) + ->setIconName(L"fenceGate") + ->setDestroyTime(2.0) + ->setExplodeable(5.0) + ->setSoundType(SoundType::WOOD) + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::OakFenceGate, + StringIDs::SimilarToADoorButUsedPrimarilyWithFences) + ->setBaseItemTypeAndMaterial(47, 1)); // Size: 0xC0u Block::registerBlock( 108, L"brick_stairs", - (new StairBlock(brickBlock->defaultBlockState())) + (new (BlockBootstrapAllocation<0xc0>{}) StairBlock(brickBlock->defaultBlockState())) ->setIconName(L"stairsBrick") ->sendBlockData(15) ->setNameAndDescriptionId(StringIDs::BrickStairs, StringIDs::UsedForCompactStaircases_1) ->setBaseItemTypeAndMaterial(16, 14)); // Size: 0xC0u - const BlockState* stoneBrickStairBlockVariant - = stoneBrickBlock->defaultBlockState()->setValue( - StoneBrickBlock::VARIANT, StoneBrickBlock::Variant::DEFAULT); Block::registerBlock( 109, L"stone_brick_stairs", - (new StairBlock(stoneBrickStairBlockVariant)) + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(stoneBrickBlock->defaultBlockState()->setValue( + StoneBrickBlock::VARIANT, StoneBrickBlock::Variant::DEFAULT))) ->setIconName(L"stairsStoneBrickSmooth") ->sendBlockData(15) ->setNameAndDescriptionId(StringIDs::StoneBrickStairs, StringIDs::UsedForCompactStaircases_1) @@ -2215,7 +2213,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 110, L"mycelium", - (new MyceliumBlock()) + (new (BlockBootstrapAllocation<0xb8>{}) MyceliumBlock()) ->setIconName(L"mycelium") ->setDestroyTime(0.6) ->setSoundType(SoundType::GRASS) @@ -2246,7 +2244,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 113, L"nether_brick_fence", - (new FenceBlock(L"nether_brick", Material::STONE, MaterialColor::NETHER)) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceBlock(L"nether_brick", Material::STONE, MaterialColor::NETHER)) ->setDestroyTime(2.0) ->setExplodeable(10.0) ->setSoundType(SoundType::STONE) @@ -2256,7 +2255,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 114, L"nether_brick_stairs", - (new StairBlock(netherBrickBlock->defaultBlockState())) + (new (BlockBootstrapAllocation<0xc0>{}) StairBlock(netherBrickBlock->defaultBlockState())) ->setIconName(L"stairsNetherBrick") ->sendBlockData(15) ->setNameAndDescriptionId(StringIDs::NetherBrickStairs, StringIDs::UsedForCompactStaircases_1) @@ -2264,7 +2263,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock(115, L"nether_wart", - (new NetherWartBlock()) + (new (BlockBootstrapAllocation<0xc0>{}) NetherWartBlock()) ->setIconName(L"nether_wart") ->sendBlockData(15) ->setNameAndDescriptionId(StringIDs::NetherWart_1, @@ -2274,7 +2273,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 116, L"enchanting_table", - (new EnchantmentTableBlock()) + (new (BlockBootstrapAllocation<0xc0>{}) EnchantmentTableBlock()) ->setIconName(L"enchanting_table") ->setDestroyTime(5.0) ->setExplodeable(2000.0) @@ -2284,7 +2283,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(117, L"brewing_stand", - (new BrewingStandBlock()) + (new (BlockBootstrapAllocation<0xb8>{}) BrewingStandBlock()) ->setIconName(L"brewing_stand") ->setDestroyTime(0.5) ->setLightEmission(0.125) @@ -2296,7 +2295,7 @@ void Block::staticCtor() { // Size: 0xD0u Block::registerBlock( 118, L"cauldron", - (new CauldronBlock()) + (new (BlockBootstrapAllocation<0xd0>{}) CauldronBlock()) ->setIconName(L"cauldron") ->setDestroyTime(2.0) ->sendBlockData(15) @@ -2305,19 +2304,19 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 119, L"end_portal", - (new EndPortalBlock(Material::PORTAL)) - ->setDestroyTime(3.4028e38) + (new (BlockBootstrapAllocation<0xb0>{}) EndPortalBlock(Material::PORTAL)) + ->setDestroyTime(3.4028234663852886e38f) ->setExplodeable(6000000.0) ->setNameAndDescriptionId(StringIDs::EndPortal, StringIDs::ThisCanBeActivatedUsingTwelveEyeOf)); // Size: 0xB8u Block::registerBlock( 120, L"end_portal_frame", - (new EndPortalFrameBlock()) + (new (BlockBootstrapAllocation<0xb8>{}) EndPortalFrameBlock()) ->setIconName(L"endframe") ->setSoundType(SoundType::GLASS) ->setLightEmission(0.125) - ->setDestroyTime(3.4028e38) + ->setDestroyTime(3.4028234663852886e38f) ->sendBlockData(15) ->setExplodeable(6000000.0) ->setNameAndDescriptionId(StringIDs::EndPortalFrame, StringIDs::UsedToFormAnEndPortal)); @@ -2388,7 +2387,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock( 127, L"cocoa", - (new CocoaBlock()) + (new (BlockBootstrapAllocation<0xc8>{}) CocoaBlock()) ->setIconName(L"cocoa") ->setDestroyTime(0.2) ->setExplodeable(5.0) @@ -2397,16 +2396,15 @@ void Block::staticCtor() { ->setNameAndDescriptionId(StringIDs::Cocoa, StringIDs::CanBeFarmedToCollectCocoaBeans)); // Size: 0xC0u - const BlockState* sandStoneStairBlockVariant - = sandStoneBlock->defaultBlockState()->setValue( - SandStoneBlock::TYPE, SandStoneBlock::Variant::DEFAULT); - Block* sandStoneStairBlock - = (new StairBlock(sandStoneStairBlockVariant)) - ->setIconName(L"stairsSandstone") - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::SandstoneStairs, StringIDs::UsedForCompactStaircases_1) - ->setBaseItemTypeAndMaterial(16, 13); - Block::registerBlock(128, L"sandstone_stairs", sandStoneStairBlock); + Block::registerBlock( + 128, L"sandstone_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(sandStoneBlock->defaultBlockState()->setValue( + SandStoneBlock::TYPE, SandStoneBlock::Variant::DEFAULT))) + ->setIconName(L"stairsSandstone") + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::SandstoneStairs, StringIDs::UsedForCompactStaircases_1) + ->setBaseItemTypeAndMaterial(16, 13)); // Size: 0xA8u Block::registerBlock( @@ -2421,7 +2419,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 130, L"ender_chest", - (new EnderChestBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) EnderChestBlock()) ->setDestroyTime(22.5) ->setIconName(L"enderChest") ->setExplodeable(1000.0) @@ -2461,45 +2459,42 @@ void Block::staticCtor() { ->setBaseItemTypeAndMaterial(32, 44)); // Size: 0xC0u - const BlockState* spruceStairBlockVariant - = planksBlock->defaultBlockState()->setValue(PlanksBlock::VARIANT, - PlanksBlock::Variant::SPRUCE); - Block* spruceStairBlock - = (new StairBlock(spruceStairBlockVariant)) - ->setIconName(L"stairsWoodSpruce") - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::SpruceWoodStairs, StringIDs::UsedForCompactStaircases_1) - ->setBaseItemTypeAndMaterial(16, 39); - Block::registerBlock(134, L"spruce_stairs", stairBlock); + Block::registerBlock( + 134, L"spruce_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(planksBlock->defaultBlockState()->setValue( + PlanksBlock::VARIANT, PlanksBlock::Variant::SPRUCE))) + ->setIconName(L"stairsWoodSpruce") + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::SpruceWoodStairs, StringIDs::UsedForCompactStaircases_1) + ->setBaseItemTypeAndMaterial(16, 39)); // Size: 0xC0u - const BlockState* birchStairBlockVariant - = planksBlock->defaultBlockState()->setValue(PlanksBlock::VARIANT, - PlanksBlock::Variant::BIRCH); - Block* birchStairBlock - = (new StairBlock(birchStairBlockVariant)) - ->setIconName(L"stairsWoodBirch") - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::BirchWoodStairs, StringIDs::UsedForCompactStaircases_1) - ->setBaseItemTypeAndMaterial(16, 40); - Block::registerBlock(135, L"birch_stairs", birchStairBlock); + Block::registerBlock( + 135, L"birch_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(planksBlock->defaultBlockState()->setValue( + PlanksBlock::VARIANT, PlanksBlock::Variant::BIRCH))) + ->setIconName(L"stairsWoodBirch") + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::BirchWoodStairs, StringIDs::UsedForCompactStaircases_1) + ->setBaseItemTypeAndMaterial(16, 40)); // Size: 0xC0u - const BlockState* jungleStairBlockVariant - = planksBlock->defaultBlockState()->setValue(PlanksBlock::VARIANT, - PlanksBlock::Variant::JUNGLE); - Block* jungleStairBlock - = (new StairBlock(jungleStairBlockVariant)) - ->setIconName(L"stairsWoodJungle") - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::JungleWoodStairs, StringIDs::UsedForCompactStaircases_1) - ->setBaseItemTypeAndMaterial(16, 41); - Block::registerBlock(136, L"jungle_stairs", jungleStairBlock); + Block::registerBlock( + 136, L"jungle_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(planksBlock->defaultBlockState()->setValue( + PlanksBlock::VARIANT, PlanksBlock::Variant::JUNGLE))) + ->setIconName(L"stairsWoodJungle") + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::JungleWoodStairs, StringIDs::UsedForCompactStaircases_1) + ->setBaseItemTypeAndMaterial(16, 41)); // Size: 0xB0u Block::registerBlock( 138, L"beacon", - (new BeaconBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) BeaconBlock()) ->setIconName(L"beacon") ->setLightEmission(1.0) ->setSoundType(SoundType::GLASS) @@ -2515,7 +2510,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(140, L"flower_pot", - (new FlowerPotBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) FlowerPotBlock()) ->setDestroyTime(0.0) ->setIconName(L"flower_pot") ->setSoundType(SoundType::STONE) @@ -2525,7 +2520,7 @@ void Block::staticCtor() { // Size: 0x110u Block::registerBlock( 141, L"carrots", - (new CarrotBlock()) + (new (BlockBootstrapAllocation<0x110>{}) CarrotBlock()) ->setIconName(L"carrots") ->setNameAndDescriptionId(StringIDs::Carrots, StringIDs::Restores15IconShank01AndCan) ->disableMipmap()); @@ -2533,7 +2528,7 @@ void Block::staticCtor() { // Size: 0x110u Block::registerBlock( 142, L"potatoes", - (new PotatoBlock()) + (new (BlockBootstrapAllocation<0x110>{}) PotatoBlock()) ->setIconName(L"potatoes") ->setNameAndDescriptionId(StringIDs::Potatoes, StringIDs::Restores05IconShank01OrCan) ->disableMipmap()); @@ -2552,7 +2547,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 144, L"skull", - (new SkullBlock()) + (new (BlockBootstrapAllocation<0xc0>{}) SkullBlock()) ->setIconName(L"") ->setDestroyTime(1.0) ->setSoundType(SoundType::STONE) @@ -2561,7 +2556,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 145, L"anvil", - (new AnvilBlock()) + (new (BlockBootstrapAllocation<0xc0>{}) AnvilBlock()) ->setIconName(L"anvil") ->setBaseItemTypeAndMaterial(30, 3) ->setDestroyTime(5.0) @@ -2573,7 +2568,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 146, L"trapped_chest", - (new ChestBlock(true)) + (new (BlockBootstrapAllocation<0xb8>{}) ChestBlock(true)) ->setBaseItemTypeAndMaterial(36, 25) ->setDestroyTime(2.5) ->setSoundType(SoundType::WOOD) @@ -2582,18 +2577,19 @@ void Block::staticCtor() { StringIDs::StoresBlocksAndItemsInsidePlaceTwoChestsATrappedAlsoCreatesRedstone)); // Size: 0xC8u - Block::registerBlock( - 147, L"light_weighted_pressure_plate", - (new WeightedPressurePlateBlock(L"gold_block", Material::METAL, 15, MaterialColor::GOLD)) - ->setBaseItemTypeAndMaterial(15, 4) - ->setDestroyTime(0.5) - ->setSoundType(SoundType::WOOD) - ->setNameAndDescriptionId(StringIDs::WeightedPressurePlateLight, - StringIDs::ProvidesARedstoneChargeTheChargeWillBe_1)); + Block::registerBlock(147, L"light_weighted_pressure_plate", + (new (BlockBootstrapAllocation<0xc8>{}) WeightedPressurePlateBlock( + L"gold_block", Material::METAL, 15, MaterialColor::GOLD)) + ->setBaseItemTypeAndMaterial(15, 4) + ->setDestroyTime(0.5) + ->setSoundType(SoundType::WOOD) + ->setNameAndDescriptionId(StringIDs::WeightedPressurePlateLight, + StringIDs::ProvidesARedstoneChargeTheChargeWillBe_1)); // Size: 0xC8u Block::registerBlock(148, L"heavy_weighted_pressure_plate", - (new WeightedPressurePlateBlock(L"iron_block", Material::METAL, 150, 0)) + (new (BlockBootstrapAllocation<0xc8>{}) + WeightedPressurePlateBlock(L"iron_block", Material::METAL, 150, 0)) ->setBaseItemTypeAndMaterial(15, 3) ->setDestroyTime(0.5) ->setSoundType(SoundType::WOOD) @@ -2602,7 +2598,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(149, L"unpowered_comparator", - (new ComparatorBlock(false)) + (new (BlockBootstrapAllocation<0xb0>{}) ComparatorBlock(false)) ->setIconName(L"comparator_off") ->setDestroyTime(0.0) ->setSoundType(SoundType::WOOD) @@ -2613,7 +2609,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(150, L"powered_comparator", - (new ComparatorBlock(true)) + (new (BlockBootstrapAllocation<0xb0>{}) ComparatorBlock(true)) ->setIconName(L"comparator_on") ->setDestroyTime(0.0) ->setLightEmission(0.625) @@ -2625,7 +2621,7 @@ void Block::staticCtor() { // Size: 0xD0u Block::registerBlock(151, L"daylight_detector", - (new DaylightDetectorBlock(false)) + (new (BlockBootstrapAllocation<0xd0>{}) DaylightDetectorBlock(false)) ->setIconName(L"daylight_detector") ->setNameAndDescriptionId(StringIDs::DaylightSensor, StringIDs::ABlockThatOutputsARedstoneSignalBased)); @@ -2654,7 +2650,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock( 154, L"hopper", - (new HopperBlock()) + (new (BlockBootstrapAllocation<0xc8>{}) HopperBlock()) ->setIconName(L"hopper") ->setDestroyTime(3.0) ->setExplodeable(8.0) @@ -2672,18 +2668,18 @@ void Block::staticCtor() { Block::registerBlock(155, L"quartz_block", quartzBlock); // Size: 0xC0u - const BlockState* variant = quartzBlock->defaultBlockState()->setValue( - QuartzBlock::VARIANT, QuartzBlock::Variant::DEFAULT); - Block* quartzStairsBlock - = (new StairBlock(variant)) - ->setIconName(L"stairsQuartz") - ->setNameAndDescriptionId(StringIDs::QuartzStairs, StringIDs::UsedForCompactStaircases_1) - ->setBaseItemTypeAndMaterial(16, 45); - Block::registerBlock(156, L"quartz_stairs", quartzStairsBlock); + Block::registerBlock( + 156, L"quartz_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(quartzBlock->defaultBlockState()->setValue( + QuartzBlock::VARIANT, QuartzBlock::Variant::DEFAULT))) + ->setIconName(L"stairsQuartz") + ->setNameAndDescriptionId(StringIDs::QuartzStairs, StringIDs::UsedForCompactStaircases_1) + ->setBaseItemTypeAndMaterial(16, 45)); // Size: 0xB0u Block::registerBlock(157, L"activator_rail", - (new PoweredRailBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) PoweredRailBlock()) ->setIconName(L"rail_activator") ->setDestroyTime(0.7) ->setSoundType(SoundType::METAL) @@ -2693,7 +2689,7 @@ void Block::staticCtor() { // Size: 0xE8u Block::registerBlock( 158, L"dropper", - (new DropperBlock()) + (new (BlockBootstrapAllocation<0xe8>{}) DropperBlock()) ->setIconName(L"dropper") ->setDestroyTime(3.5) ->setSoundType(SoundType::STONE) @@ -2702,7 +2698,7 @@ void Block::staticCtor() { // Size: 0x128u Block::registerBlock(159, L"stained_hardened_clay", - (new StainedHardenedClayBlock()) + (new (BlockBootstrapAllocation<0x128>{}) StainedHardenedClayBlock()) ->setIconName(L"hardened_clay_stained") ->setDestroyTime(1.25) ->setExplodeable(7.0) @@ -2714,7 +2710,7 @@ void Block::staticCtor() { // Size: 0xE0u Block::registerBlock( 160, L"stained_glass_pane", - (new StainedGlassPaneBlock()) + (new (BlockBootstrapAllocation<0xe0>{}) StainedGlassPaneBlock()) ->setIconName(L"glass") ->setDestroyTime(0.3) ->setSoundType(SoundType::GLASS) @@ -2724,7 +2720,7 @@ void Block::staticCtor() { // Size: 0x110u Block::registerBlock(161, L"leaves2", - (new NewLeafBlock()) + (new (BlockBootstrapAllocation<0x110>{}) NewLeafBlock()) ->setIconName(L"leaves") ->sendBlockData(3) ->setNameAndDescriptionId(StringIDs::Leaves, @@ -2739,28 +2735,26 @@ void Block::staticCtor() { ->setNameAndDescriptionId(StringIDs::Wood, StringIDs::ChoppedUsingAnAxeAndCanBeCrafted)); // Size: 0xC0u - const BlockState* acaciaStairsBlockVariant - = planksBlock->defaultBlockState()->setValue(PlanksBlock::VARIANT, - PlanksBlock::Variant::ACACIA); - Block* acaciaStairsBlock - = (new StairBlock(acaciaStairsBlockVariant)) - ->setIconName(L"stairsWoodAcacia") - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::AcaciaWoodStairs, StringIDs::UsedForCompactStaircases_1) - ->setBaseItemTypeAndMaterial(16, 42); - Block::registerBlock(163, L"acacia_stairs", acaciaStairsBlock); + Block::registerBlock( + 163, L"acacia_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(planksBlock->defaultBlockState()->setValue( + PlanksBlock::VARIANT, PlanksBlock::Variant::ACACIA))) + ->setIconName(L"stairsWoodAcacia") + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::AcaciaWoodStairs, StringIDs::UsedForCompactStaircases_1) + ->setBaseItemTypeAndMaterial(16, 42)); // Size: 0xC0u - const BlockState* darkOakStairsBlockVariant - = planksBlock->defaultBlockState()->setValue(PlanksBlock::VARIANT, - PlanksBlock::Variant::DARK_OAK); - Block* darkOakStairsBlock - = (new StairBlock(darkOakStairsBlockVariant)) - ->setIconName(L"stairsWoodDarkOak") - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::DarkOakWoodStairs, StringIDs::UsedForCompactStaircases_1) - ->setBaseItemTypeAndMaterial(16, 43); - Block::registerBlock(164, L"dark_oak_stairs", darkOakStairsBlock); + Block::registerBlock( + 164, L"dark_oak_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(planksBlock->defaultBlockState()->setValue( + PlanksBlock::VARIANT, PlanksBlock::Variant::DARK_OAK))) + ->setIconName(L"stairsWoodDarkOak") + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::DarkOakWoodStairs, StringIDs::UsedForCompactStaircases_1) + ->setBaseItemTypeAndMaterial(16, 43)); // Size: 0xC0u Block::registerBlock(165, L"slime", @@ -2863,14 +2857,14 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(175, L"double_plant", - (new DoublePlantBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) DoublePlantBlock()) ->setNameAndDescriptionId(StringIDs::DoublePlantBlock, StringIDs::ALargePlant) ->disableMipmap()); // Size: 0xB0u Block::registerBlock( 176, L"standing_banner", - (new StandingBannerBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) StandingBannerBlock()) ->setIconName(L"planks_oak") ->setDestroyTime(1.0) ->setSoundType(SoundType::WOOD) @@ -2881,7 +2875,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 177, L"wall_banner", - (new WallBannerBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) WallBannerBlock()) ->setIconName(L"planks_oak") ->setDestroyTime(1.0) ->setSoundType(SoundType::WOOD) @@ -2891,7 +2885,7 @@ void Block::staticCtor() { // Size: 0xD0u Block::registerBlock(178, L"daylight_detector_inverted", - (new DaylightDetectorBlock(true)) + (new (BlockBootstrapAllocation<0xd0>{}) DaylightDetectorBlock(true)) ->setIconName(L"daylight_detector") ->setNameAndDescriptionId(StringIDs::DaylightSensor, StringIDs::ABlockThatOutputsARedstoneSignalBased)); @@ -2908,19 +2902,18 @@ void Block::staticCtor() { Block::registerBlock(179, L"red_sandstone", redSandStoneBlock); // Size: 0xC0u - const BlockState* redSandstoneStairsBlockVariant - = redSandStoneBlock->defaultBlockState()->setValue( - RedSandStoneBlock::TYPE, RedSandStoneBlock::Variant::DEFAULT); - Block* redSandstoneStairsBlock - = (new StairBlock(redSandstoneStairsBlockVariant)) - ->setIconName(L"red_sandstone") - ->setNameAndDescriptionId(StringIDs::RedSandstoneStairs, StringIDs::UsedForCompactStaircases_2) - ->setBaseItemTypeAndMaterial(16, 48); - Block::registerBlock(180, L"red_sandstone_stairs", redSandstoneStairsBlock); + Block::registerBlock( + 180, L"red_sandstone_stairs", + (new (BlockBootstrapAllocation<0xc0>{}) + StairBlock(redSandStoneBlock->defaultBlockState()->setValue( + RedSandStoneBlock::TYPE, RedSandStoneBlock::Variant::DEFAULT))) + ->setIconName(L"red_sandstone") + ->setNameAndDescriptionId(StringIDs::RedSandstoneStairs, StringIDs::UsedForCompactStaircases_2) + ->setBaseItemTypeAndMaterial(16, 48)); // Size: 0xB0u Block::registerBlock(181, L"double_stone_slab2", - (new FullNewStoneSlabBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) FullNewStoneSlabBlock()) ->setIconName(L"double_stone_slab2") ->setDestroyTime(2.0) ->setExplodeable(10.0) @@ -2931,7 +2924,7 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock(182, L"stone_slab2", - (new HalfNewStoneSlabBlock()) + (new (BlockBootstrapAllocation<0xb0>{}) HalfNewStoneSlabBlock()) ->setIconName(L"stone_slab2") ->setDestroyTime(2.0) ->setExplodeable(10.0) @@ -2942,7 +2935,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock(183, L"spruce_fence_gate", - (new FenceGateBlock(L"planks_spruce", PlanksBlock::Variant::SPRUCE)) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceGateBlock(L"planks_spruce", PlanksBlock::Variant::SPRUCE)) ->setIconName(L"fenceGate") ->setDestroyTime(2.0) ->setExplodeable(5.0) @@ -2953,20 +2947,22 @@ void Block::staticCtor() { ->setBaseItemTypeAndMaterial(47, 39)); // Size: 0xC0u - Block::registerBlock(184, L"birch_fence_gate", - (new FenceGateBlock(L"planks_birch", PlanksBlock::Variant::BIRCH)) - ->setIconName(L"fenceGate") - ->setDestroyTime(2.0) - ->setExplodeable(5.0) - ->setSoundType(SoundType::WOOD) - ->sendBlockData(15) - ->setNameAndDescriptionId(StringIDs::BirchFenceGate, - StringIDs::SimilarToADoorButUsedPrimarilyWithFences) - ->setBaseItemTypeAndMaterial(47, 40)); + Block::registerBlock( + 184, L"birch_fence_gate", + (new (BlockBootstrapAllocation<0xc0>{}) FenceGateBlock(L"planks_birch", PlanksBlock::Variant::BIRCH)) + ->setIconName(L"fenceGate") + ->setDestroyTime(2.0) + ->setExplodeable(5.0) + ->setSoundType(SoundType::WOOD) + ->sendBlockData(15) + ->setNameAndDescriptionId(StringIDs::BirchFenceGate, + StringIDs::SimilarToADoorButUsedPrimarilyWithFences) + ->setBaseItemTypeAndMaterial(47, 40)); // Size: 0xC0u Block::registerBlock(185, L"jungle_fence_gate", - (new FenceGateBlock(L"planks_jungle", PlanksBlock::Variant::JUNGLE)) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceGateBlock(L"planks_jungle", PlanksBlock::Variant::JUNGLE)) ->setIconName(L"fenceGate") ->setDestroyTime(2.0) ->setExplodeable(5.0) @@ -2978,7 +2974,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock(186, L"dark_oak_fence_gate", - (new FenceGateBlock(L"planks_big_oak", PlanksBlock::Variant::DARK_OAK)) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceGateBlock(L"planks_big_oak", PlanksBlock::Variant::DARK_OAK)) ->setIconName(L"fenceGate") ->setDestroyTime(2.0) ->setExplodeable(5.0) @@ -2990,7 +2987,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock(187, L"acacia_fence_gate", - (new FenceGateBlock(L"planks_acacia", PlanksBlock::Variant::ACACIA)) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceGateBlock(L"planks_acacia", PlanksBlock::Variant::ACACIA)) ->setIconName(L"fenceGate") ->setDestroyTime(2.0) ->setExplodeable(5.0) @@ -3003,7 +3001,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 188, L"spruce_fence", - (new FenceBlock(L"planks_spruce", Material::WOOD, PlanksBlock::Variant::SPRUCE->getMaterialColor())) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceBlock(L"planks_spruce", Material::WOOD, PlanksBlock::Variant::SPRUCE->getMaterialColor())) ->setDestroyTime(2.0) ->setExplodeable(5.0) ->setSoundType(SoundType::WOOD) @@ -3013,7 +3012,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 189, L"birch_fence", - (new FenceBlock(L"planks_birch", Material::WOOD, PlanksBlock::Variant::BIRCH->getMaterialColor())) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceBlock(L"planks_birch", Material::WOOD, PlanksBlock::Variant::BIRCH->getMaterialColor())) ->setDestroyTime(2.0) ->setExplodeable(5.0) ->setSoundType(SoundType::WOOD) @@ -3023,7 +3023,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 190, L"jungle_fence", - (new FenceBlock(L"planks_jungle", Material::WOOD, PlanksBlock::Variant::JUNGLE->getMaterialColor())) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceBlock(L"planks_jungle", Material::WOOD, PlanksBlock::Variant::JUNGLE->getMaterialColor())) ->setDestroyTime(2.0) ->setExplodeable(5.0) ->setSoundType(SoundType::WOOD) @@ -3033,8 +3034,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 191, L"dark_oak_fence", - (new FenceBlock(L"planks_big_oak", Material::WOOD, - PlanksBlock::Variant::DARK_OAK->getMaterialColor())) + (new (BlockBootstrapAllocation<0xc0>{}) FenceBlock( + L"planks_big_oak", Material::WOOD, PlanksBlock::Variant::DARK_OAK->getMaterialColor())) ->setDestroyTime(2.0) ->setExplodeable(5.0) ->setSoundType(SoundType::WOOD) @@ -3044,7 +3045,8 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 192, L"acacia_fence", - (new FenceBlock(L"planks_acacia", Material::WOOD, PlanksBlock::Variant::ACACIA->getMaterialColor())) + (new (BlockBootstrapAllocation<0xc0>{}) + FenceBlock(L"planks_acacia", Material::WOOD, PlanksBlock::Variant::ACACIA->getMaterialColor())) ->setDestroyTime(2.0) ->setExplodeable(5.0) ->setSoundType(SoundType::WOOD) @@ -3053,7 +3055,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock(193, L"spruce_door", - (new DoorBlock(Material::WOOD)) + (new (BlockBootstrapAllocation<0xc8>{}) DoorBlock(Material::WOOD)) ->setIconName(L"door_spruce") ->setDestroyTime(3.0) ->setSoundType(SoundType::WOOD) @@ -3064,7 +3066,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock(194, L"birch_door", - (new DoorBlock(Material::WOOD)) + (new (BlockBootstrapAllocation<0xc8>{}) DoorBlock(Material::WOOD)) ->setIconName(L"door_birch") ->setDestroyTime(3.0) ->setSoundType(SoundType::WOOD) @@ -3075,7 +3077,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock(195, L"jungle_door", - (new DoorBlock(Material::WOOD)) + (new (BlockBootstrapAllocation<0xc8>{}) DoorBlock(Material::WOOD)) ->setIconName(L"door_jungle") ->setDestroyTime(3.0) ->setSoundType(SoundType::WOOD) @@ -3086,7 +3088,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock(196, L"acacia_door", - (new DoorBlock(Material::WOOD)) + (new (BlockBootstrapAllocation<0xc8>{}) DoorBlock(Material::WOOD)) ->setIconName(L"door_acacia") ->setDestroyTime(3.0) ->setSoundType(SoundType::WOOD) @@ -3097,7 +3099,7 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock(197, L"dark_oak_door", - (new DoorBlock(Material::WOOD)) + (new (BlockBootstrapAllocation<0xc8>{}) DoorBlock(Material::WOOD)) ->setIconName(L"door_dark_oak") ->setDestroyTime(3.0) ->setSoundType(SoundType::WOOD) @@ -3129,7 +3131,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock( 200, L"chorus_flower", - (new ChorusFlowerBlock()) + (new (BlockBootstrapAllocation<0xc0>{}) ChorusFlowerBlock()) ->setIconName(L"chorus_flower") ->setDestroyTime(0.4) ->setSoundType(SoundType::WOOD) @@ -3149,7 +3151,8 @@ void Block::staticCtor() { // Size: 0xC8u Block::registerBlock( 202, L"purpur_pillar", - (new RotatedPillarBlockImpl(Material::STONE, MaterialColor::COLOR_MAGENTA)) + (new (BlockBootstrapAllocation<0xc8>{}) + RotatedPillarBlockImpl(Material::STONE, MaterialColor::COLOR_MAGENTA)) ->setIconTopName(L"purpur_pillar_top") // TODO ->setIconName(L"purpur_pillar") ->setDestroyTime(1.5) @@ -3160,7 +3163,7 @@ void Block::staticCtor() { // Size: 0xC0u Block::registerBlock(203, L"purpur_stairs", - (new StairBlock(purpurBlock->defaultBlockState())) + (new (BlockBootstrapAllocation<0xc0>{}) StairBlock(purpurBlock->defaultBlockState())) ->setNameAndDescriptionId(StringIDs::PurpurStairs, 0xdda0c93) ->setBaseItemTypeAndMaterial(16, 62)); @@ -3199,7 +3202,7 @@ void Block::staticCtor() { // Size: 0x110u Block::registerBlock( 207, L"beetroots", - (new BeetrootBlock()) + (new (BlockBootstrapAllocation<0x110>{}) BeetrootBlock()) ->setIconName(L"beetroots") ->disableMipmap() ->setNameAndDescriptionId(StringIDs::Beetroots, @@ -3207,7 +3210,7 @@ void Block::staticCtor() { // Size: 0xB0u Block* grassPathBlock - = (new GrassPathBlock()) + = (new (BlockBootstrapAllocation<0xb0>{}) GrassPathBlock()) ->setDestroyTime(0.65) ->setSoundType(SoundType::GRASS) ->setIconName(L"grass_path") @@ -3218,9 +3221,9 @@ void Block::staticCtor() { // Size: 0xB0u Block::registerBlock( 209, L"end_gateway", - (new EndGatewayBlock(Material::PORTAL)) + (new (BlockBootstrapAllocation<0xb0>{}) EndGatewayBlock(Material::PORTAL)) ->setIconName(L"stone") - ->setDestroyTime(3.4028e38) + ->setDestroyTime(3.4028234663852886e38f) ->setExplodeable(6000000.0) ->setNameAndDescriptionId(StringIDs::EndGateway, StringIDs::GeneratedWhenEnderDragonIsKilledThrowingAn)); @@ -3228,7 +3231,7 @@ void Block::staticCtor() { // Size: 0xD8u Block::registerBlock( 212, L"frosted_ice", - (new FrostedIceBlock()) + (new (BlockBootstrapAllocation<0xd8>{}) FrostedIceBlock()) ->setDestroyTime(0.5) ->setLightBlock(3) ->setSoundType(SoundType::GLASS) @@ -3281,14 +3284,14 @@ void Block::staticCtor() { // Size: 0xD0u Block::registerBlock(218, L"observer", - (new ObserverBlock()) + (new (BlockBootstrapAllocation<0xd0>{}) ObserverBlock()) ->setDestroyTime(3.0) ->setNameAndDescriptionId(StringIDs::Observer, StringIDs::EmitsARedstoneSignalWhenAdjacentBlocksAre)); // Size: 0xB8u Block::registerBlock(219, L"white_shulker_box", - (new ShulkerBoxBlock(DyeColor::WHITE)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::WHITE)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3298,7 +3301,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(220, L"orange_shulker_box", - (new ShulkerBoxBlock(DyeColor::ORANGE)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::ORANGE)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3308,7 +3311,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(221, L"magenta_shulker_box", - (new ShulkerBoxBlock(DyeColor::MAGENTA)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::MAGENTA)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3318,7 +3321,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(222, L"light_blue_shulker_box", - (new ShulkerBoxBlock(DyeColor::LIGHT_BLUE)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::LIGHT_BLUE)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3328,7 +3331,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(223, L"yellow_shulker_box", - (new ShulkerBoxBlock(DyeColor::YELLOW)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::YELLOW)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3339,7 +3342,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 224, L"lime_shulker_box", - (new ShulkerBoxBlock(DyeColor::LIME)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::LIME)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3349,7 +3352,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 225, L"pink_shulker_box", - (new ShulkerBoxBlock(DyeColor::PINK)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::PINK)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3359,7 +3362,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 226, L"gray_shulker_box", - (new ShulkerBoxBlock(DyeColor::GRAY)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::GRAY)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3368,7 +3371,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(227, L"silver_shulker_box", - (new ShulkerBoxBlock(DyeColor::SILVER)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::SILVER)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3379,7 +3382,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 228, L"cyan_shulker_box", - (new ShulkerBoxBlock(DyeColor::CYAN)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::CYAN)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3388,7 +3391,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(229, L"purple_shulker_box", - (new ShulkerBoxBlock(DyeColor::PURPLE)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::PURPLE)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3399,7 +3402,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 230, L"blue_shulker_box", - (new ShulkerBoxBlock(DyeColor::BLUE)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::BLUE)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3408,7 +3411,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(231, L"brown_shulker_box", - (new ShulkerBoxBlock(DyeColor::BROWN)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::BROWN)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3418,7 +3421,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock(232, L"green_shulker_box", - (new ShulkerBoxBlock(DyeColor::GREEN)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::GREEN)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3429,7 +3432,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 233, L"red_shulker_box", - (new ShulkerBoxBlock(DyeColor::RED)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::RED)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3439,7 +3442,7 @@ void Block::staticCtor() { // Size: 0xB8u Block::registerBlock( 234, L"black_shulker_box", - (new ShulkerBoxBlock(DyeColor::BLACK)) + (new (BlockBootstrapAllocation<0xb8>{}) ShulkerBoxBlock(DyeColor::BLACK)) ->setIconName(L"shulker_top") ->setDestroyTime(2.0) ->setSoundType(SoundType::STONE) @@ -3570,7 +3573,7 @@ void Block::staticCtor() { // Size: 0x128u Block::registerBlock( 251, L"concrete", - (new ColoredBlock(Material::STONE)) + (new (BlockBootstrapAllocation<0x128>{}) ColoredBlock(Material::STONE)) ->setDestroyTime(1.8) ->setSoundType(SoundType::STONE) ->setIconName(L"concrete") @@ -3578,7 +3581,7 @@ void Block::staticCtor() { // Size: 0x128u Block::registerBlock(252, L"concrete_powder", - (new ConcretePowderBlock()) + (new (BlockBootstrapAllocation<0x128>{}) ConcretePowderBlock()) ->setDestroyTime(0.5) ->setSoundType(SoundType::SAND) ->setIconName(L"concrete_powder") @@ -3602,8 +3605,9 @@ void Block::staticCtor() { } else { StairBlock* s = dynamic_cast(block); HalfSlabBlock* b = dynamic_cast(block); - if (block == farmBlock || block == grassPathBlock || !s || b) - block->m_field3C = block->m_lightEmission == 0 || block->m_isBlocksLight; + // The original uses opacity here; emission is a separate field. + if (block != farmBlock && block != grassPathBlock && !s && !b) + block->m_field3C = block->m_lightBlock == 0 || block->m_isBlocksLight; else block->m_field3C = 1; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/Block.h b/src/Minecraft.World/net/minecraft/world/level/block/Block.h index a023fa19..f87d0eb1 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/Block.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/Block.h @@ -217,6 +217,7 @@ class Block { Material* getMaterial(); int getId(); + static int getId(Block*); bool neighbourVisibleThroughShapes(const arrayWithLength*, LevelSource*, const BlockPos&, const Direction*); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/BlockBootstrapAllocation.h b/src/Minecraft.World/net/minecraft/world/level/block/BlockBootstrapAllocation.h new file mode 100644 index 00000000..54f76312 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/block/BlockBootstrapAllocation.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +// Several block declarations still expose only their reconstructed prefix. +// Keep the original initializer's allocation size without inventing fields or +// changing those partial class layouts. Placement-new retains allocation before +// constructor argument evaluation, as in the original new expression. +template +struct BlockBootstrapAllocation {}; + +template +inline __attribute__((always_inline)) void* operator new(std::size_t declaredSize, + BlockBootstrapAllocation) { + return ::operator new(OriginalSize); +} + +template +inline void operator delete(void* pointer, BlockBootstrapAllocation) noexcept { + ::operator delete(pointer); +} diff --git a/src/Minecraft.World/net/minecraft/world/level/block/Blocks.h b/src/Minecraft.World/net/minecraft/world/level/block/Blocks.h index b48fce2e..f8a415ed 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/Blocks.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/Blocks.h @@ -20,6 +20,7 @@ class Blocks { static void staticInit(); static Block* get(const std::wstring&); + static Block* byString(const std::wstring&); static inline Block* AIR; static inline Block* STONE; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/CactusBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/CactusBlock.h index 8b28cf17..b3a21a1c 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/CactusBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/CactusBlock.h @@ -1,8 +1,9 @@ -#pragma once - -#include "net/minecraft/world/level/block/Block.h" - -class CactusBlock : public Block { -public: - CactusBlock(); -}; +#pragma once + +#include "net/minecraft/world/level/block/Block.h" + +class CactusBlock : public Block { +public: + CactusBlock(); + virtual bool canSurvive(Level*, const BlockPos&); +}; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/ChestBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/ChestBlock.h index 550daf3b..1903c70f 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/ChestBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/ChestBlock.h @@ -5,6 +5,7 @@ class ChestBlock : public Block { public: ChestBlock(bool trapped); + const BlockState* reorient(Level*, const BlockPos&, const BlockState*); static void blockStaticCtor(); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/ChorusFlowerBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/ChorusFlowerBlock.h index 26e258ac..ed7b58fd 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/ChorusFlowerBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/ChorusFlowerBlock.h @@ -1,8 +1,9 @@ -#pragma once - -#include "net/minecraft/world/level/block/Block.h" - -class ChorusFlowerBlock : public Block { -public: - ChorusFlowerBlock(); -}; +#pragma once + +#include "net/minecraft/world/level/block/Block.h" + +class ChorusFlowerBlock : public Block { +public: + static void generatePlant(Level*, BlockPos, Random*, int); + ChorusFlowerBlock(); +}; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/CocoaBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/CocoaBlock.h index a432208c..12e5472e 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/CocoaBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/CocoaBlock.h @@ -1,13 +1,14 @@ -#pragma once - -#include "net/minecraft/world/level/block/BonemealableBlock.h" -#include "net/minecraft/world/level/block/HorizontalDirectionalBlock.h" - -class CocoaBlock : public HorizontalDirectionalBlock, public BonemealableBlock { -public: - CocoaBlock(); - - bool isValidBonemealTarget(Level*, const BlockPos&, const BlockState*, bool) override; - bool isBonemealSuccess(Level*, Random*, const BlockPos&, const BlockState*) override; - void performBonemeal(Level*, Random*, const BlockPos&, const BlockState*) override; -}; +#pragma once + +#include "net/minecraft/world/level/block/BonemealableBlock.h" +#include "net/minecraft/world/level/block/HorizontalDirectionalBlock.h" + +class CocoaBlock : public HorizontalDirectionalBlock, public BonemealableBlock { +public: + static Property* AGE; + CocoaBlock(); + + bool isValidBonemealTarget(Level*, const BlockPos&, const BlockState*, bool) override; + bool isBonemealSuccess(Level*, Random*, const BlockPos&, const BlockState*) override; + void performBonemeal(Level*, Random*, const BlockPos&, const BlockState*) override; +}; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/ColoredBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/ColoredBlock.h index 50e5b4a1..6850ba05 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/ColoredBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/ColoredBlock.h @@ -4,6 +4,7 @@ class ColoredBlock : public Block { public: + static Property* COLOR; ColoredBlock(Material*); static void blockStaticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/DoublePlantBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/DoublePlantBlock.h index e1632fc5..64c89707 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/DoublePlantBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/DoublePlantBlock.h @@ -1,10 +1,31 @@ #pragma once +#include "net/minecraft/core/StringRepresentable.h" #include "net/minecraft/world/level/block/Block.h" class DoublePlantBlock : public Block { public: + class Variant : public StringRepresentable { + public: + static Variant* FERN; + static Variant* GRASS; + static Variant* SUNFLOWER; + static Variant* SYRINGA; + static Variant* ROSE; + static Variant* PAEONIA; + static inline Variant* VARIANTS[6]; + static Variant* byData(int data) { return VARIANTS[static_cast(data) > 5 ? 0 : data]; } + int getNameId() { return m_nameId; } + int getDescriptionId() { return m_descriptionId; } + + int m_data; + std::wstring m_name; + int m_nameId; + int m_descriptionId; + }; + DoublePlantBlock(); + void placeAt(Level*, const BlockPos&, Variant*, int); static void blockStaticCtor(); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/EndGatewayBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/EndGatewayBlock.h index 975f10f5..6017af17 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/EndGatewayBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/EndGatewayBlock.h @@ -1,8 +1,10 @@ -#pragma once - -#include "net/minecraft/world/level/block/Block.h" - -class EndGatewayBlock : public BaseEntityBlock { -public: - EndGatewayBlock(Material*); -}; +#pragma once + +#include "net/minecraft/world/level/block/BaseEntityBlock.h" +#include "net/minecraft/world/level/block/state/IntegerProperty.h" + +class EndGatewayBlock : public BaseEntityBlock { +public: + static IntegerProperty* FJ_PORTAL_NUMBER; + EndGatewayBlock(Material*); +}; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/FlowerBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/FlowerBlock.h index 429402f1..81ce2f48 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/FlowerBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/FlowerBlock.h @@ -6,7 +6,10 @@ class FlowerBlock : public Bush, public BonemealableBlock { public: - class FlowerCategory; + class FlowerCategory { + public: + FlowerBlock* getBlock(); + }; class FlowerCategoryPredicate; class Flower { public: @@ -14,6 +17,14 @@ class FlowerBlock : public Bush, public BonemealableBlock { static Flower* RED_FLOWER; static Flower* RED_MUSHROOM; static Flower* BROWN_MUSHROOM; + static Flower* OXEYE_DAISY; + static Flower* BLUE_ORCHID; + static Flower* HOUSTONIA; + static Flower* RED_TULIP; + static Flower* ORANGE_TULIP; + static Flower* WHITE_TULIP; + static Flower* PINK_TULIP; + static Flower* FLOWERS[10]; enum EFlower {}; @@ -21,9 +32,18 @@ class FlowerBlock : public Bush, public BonemealableBlock { FlowerBlock::Flower::EFlower); void* m_field0; + FlowerCategory* getCategory() const; + int getData(); + int getNameId(); + int getDescriptionId(); + int m_field8; + int m_field12; + int m_data; }; virtual FlowerBlock::FlowerCategory* getFlowerCategory() = 0; - virtual void getFlowerProperty(); + virtual Property* getFlowerProperty(); + + Property* m_flowerProperty; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/HalfSlabBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/HalfSlabBlock.h index 413356f6..94666f1f 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/HalfSlabBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/HalfSlabBlock.h @@ -53,7 +53,7 @@ class HalfSlabBlock : public Block { bool isSolidRender(const BlockState*) const override; int getResourceCount(Random*) override; const BlockState* getStateForPlacement(Level*, const BlockPos&, const Direction*, float, float, float, - int, std::__1::shared_ptr) override; + int, std::shared_ptr) override; bool isSilkTouchable() override; virtual std::wstring getAuxName(int aux) = 0; virtual bool isFullSize() const = 0; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/HorizontalDirectionalBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/HorizontalDirectionalBlock.h index 77a4a29e..843c570c 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/HorizontalDirectionalBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/HorizontalDirectionalBlock.h @@ -9,4 +9,5 @@ class HorizontalDirectionalBlock : public Block { static void blockStaticCtor(); static EnumProperty* AXIS; + static Property* FACING; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/HugeMushroomBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/HugeMushroomBlock.h index 220150ff..bf3abb94 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/HugeMushroomBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/HugeMushroomBlock.h @@ -4,6 +4,20 @@ class HugeMushroomBlock : public Block { public: + class Variant { + public: + static Variant* byData(int); + static Variant* NORTH_WEST; + static Variant* NORTH_EAST; + static Variant* SOUTH_WEST; + static Variant* SOUTH_EAST; + static Variant* CENTER; + static Variant* ALL_INSIDE; + static Variant* STEM; + }; + + static Property* VARIANT; + HugeMushroomBlock(Material*, const MaterialColor*, Block*); static void blockStaticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/Mirror.h b/src/Minecraft.World/net/minecraft/world/level/block/Mirror.h new file mode 100644 index 00000000..92640c3a --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/block/Mirror.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +class Mirror { +public: + enum eTYPE { MIRROR_0, MIRROR_LEFT_RIGHT, MIRROR_FRONT_BACK }; + + static Mirror* NONE; + static Mirror* LEFT_RIGHT; + + Mirror(const std::wstring& name, eTYPE type); + + std::wstring m_name; + eTYPE m_type; +}; + +static_assert(sizeof(Mirror) == 0x20, "Switch mirror layout"); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/NewLeafBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/NewLeafBlock.h index 9eacf59c..da97518e 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/NewLeafBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/NewLeafBlock.h @@ -1,9 +1,12 @@ #pragma once #include "net/minecraft/world/level/block/LeafBlock.h" +#include "net/minecraft/world/level/block/PlanksBlock.h" +#include "net/minecraft/world/level/block/state/EnumProperty.h" class NewLeafBlock : public LeafBlock { public: + static EnumProperty* VARIANT; NewLeafBlock(); static void blockStaticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/OldLeafBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/OldLeafBlock.h index aabba62d..ccbbcbbd 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/OldLeafBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/OldLeafBlock.h @@ -1,9 +1,11 @@ #pragma once #include "net/minecraft/world/level/block/LeafBlock.h" +#include "net/minecraft/world/level/block/PlanksBlock.h" class OldLeafBlock : public LeafBlock { public: + static EnumProperty* VARIANT; OldLeafBlock(); static void blockStaticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/OreBlock.cpp b/src/Minecraft.World/net/minecraft/world/level/block/OreBlock.cpp index ded354b1..92a3c2b6 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/OreBlock.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/block/OreBlock.cpp @@ -59,7 +59,7 @@ void OreBlock::spawnResources(Level* level, const BlockPos& pos, const BlockStat int OreBlock::getResourceCountForLootBonus(int fortuneLevel, Random* random) { if (fortuneLevel > 0 && Item::byBlock(this) - != this->getResource(this->getBlockStateDefinition()->getPossibleBlockStates()->get(0), random, + != this->getResource((*this->getBlockStateDefinition()->getPossibleBlockStates())[0], random, fortuneLevel)) { int i = random->nextInt(fortuneLevel + 2) - 1; if (i < 0) { diff --git a/src/Minecraft.World/net/minecraft/world/level/block/PlanksBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/PlanksBlock.h index 987fa049..9df23468 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/PlanksBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/PlanksBlock.h @@ -33,6 +33,7 @@ class PlanksBlock : public Block { } int getData() { return this->m_data; } + int getNameId() { return this->m_nameId; } const MaterialColor* getMaterialColor() { return this->m_materialColor; } std::wstring toString() const override { return this->m_name; } diff --git a/src/Minecraft.World/net/minecraft/world/level/block/RedSandStoneBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/RedSandStoneBlock.h index f663f30a..83472045 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/RedSandStoneBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/RedSandStoneBlock.h @@ -28,6 +28,7 @@ class RedSandStoneBlock : public Block { } int getData() { return this->m_data; } + int getNameId() { return this->m_nameId; } std::wstring toString() const override { return this->m_name; } std::wstring getSerializedName() const override { return this->m_name; } diff --git a/src/Minecraft.World/net/minecraft/world/level/block/Rotation.h b/src/Minecraft.World/net/minecraft/world/level/block/Rotation.h index 5370e3c4..0e406644 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/Rotation.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/Rotation.h @@ -9,6 +9,9 @@ class Rotation { public: enum eTYPE { ROTATE_0, ROTATE_90, ROTATE_180, ROTATE_270 }; + static Rotation* NONE; + static Rotation* CLOCKWISE_90; + Rotation(const std::wstring& name, eTYPE type); Rotation* getRotated(Rotation* rot); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/SandBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/SandBlock.h index 0ff2ded5..11f8194d 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/SandBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/SandBlock.h @@ -32,6 +32,8 @@ class SandBlock : public FallingBlock { } int getData() { return this->m_data; } + int getNameId() { return this->m_nameId; } + int getDescriptionId() { return this->m_descId; } std::wstring getName() { return this->m_name; } const MaterialColor* getMaterialColor() { return this->m_materialColor; } int getDustColor() { return this->m_dustColor; } diff --git a/src/Minecraft.World/net/minecraft/world/level/block/SandStoneBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/SandStoneBlock.h index 1152ab95..bab82443 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/SandStoneBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/SandStoneBlock.h @@ -27,6 +27,7 @@ class SandStoneBlock : public Block { } int getData() { return this->m_data; } + int getNameId() { return this->m_nameId; } std::wstring toString() const override { return this->m_name; } std::wstring getSerializedName() const override { return this->m_name; } diff --git a/src/Minecraft.World/net/minecraft/world/level/block/SoundType.h b/src/Minecraft.World/net/minecraft/world/level/block/SoundType.h index 65ce03c0..cb41a51d 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/SoundType.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/SoundType.h @@ -22,11 +22,16 @@ class SoundType { SoundType(float volume, float pitch, const SoundEvent* dig, const SoundEvent* step, const SoundEvent* place, const SoundEvent* hit, const SoundEvent* fall); + const SoundEvent* getBreakSound(); + const SoundEvent* getStepSound(); + const SoundEvent* getHitSound(); + const SoundEvent* getFallSound(); + float m_volume; float m_pitch; - SoundEvent* m_digSound; - SoundEvent* m_stepSound; - SoundEvent* m_placeSound; - SoundEvent* m_hitSound; - SoundEvent* m_fallSound; + const SoundEvent* m_digSound; + const SoundEvent* m_stepSound; + const SoundEvent* m_placeSound; + const SoundEvent* m_hitSound; + const SoundEvent* m_fallSound; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/SpongeBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/SpongeBlock.h index 3b8e272a..4330169f 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/SpongeBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/SpongeBlock.h @@ -1,8 +1,11 @@ -#pragma once - -#include "net/minecraft/world/level/block/Block.h" - -class SpongeBlock : public Block { -public: - SpongeBlock(); -}; +#pragma once + +#include "net/minecraft/world/level/block/Block.h" + +class BooleanProperty; + +class SpongeBlock : public Block { +public: + SpongeBlock(); + static BooleanProperty* WET; +}; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/StoneSlabBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/StoneSlabBlock.h index 079b9960..8c800073 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/StoneSlabBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/StoneSlabBlock.h @@ -1,8 +1,17 @@ #pragma once +#include "net/minecraft/core/StringRepresentable.h" #include "net/minecraft/world/level/block/Block.h" +#include "net/minecraft/world/level/block/state/EnumProperty.h" class StoneSlabBlock : public Block { public: + // Variant interface only; catalogue layout and construction remain unreconstructed. + class Variant : public StringRepresentable { + public: + static Variant* SANDSTONE; + }; + + static EnumProperty* VARIANT; static void blockStaticCtor(); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/TallGrassBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/TallGrassBlock.h index 207120ed..f627212d 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/TallGrassBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/TallGrassBlock.h @@ -1,10 +1,18 @@ #pragma once -#include "net/minecraft/world/level/block/Block.h" +#include "net/minecraft/world/level/block/Bush.h" -class TallGrassBlock : public Block { +class TallGrassBlock : public Bush { public: + class Variant { + public: + static Variant* GRASS; + static Variant* FERN; + }; + TallGrassBlock(); static void blockStaticCtor(); + + static Property* TYPE; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/TorchBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/TorchBlock.h index e69cbbcf..1c99fc7f 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/TorchBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/TorchBlock.h @@ -4,6 +4,7 @@ class TorchBlock : public Block { public: + static Property* FACING; TorchBlock(); static void blockStaticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/VineBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/VineBlock.h index 4274adad..18681488 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/VineBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/VineBlock.h @@ -1,8 +1,14 @@ -#pragma once - -#include "net/minecraft/world/level/block/Block.h" - -class VineBlock : public Block { -public: - VineBlock(); -}; +#pragma once + +#include "net/minecraft/world/level/block/Block.h" + +class BooleanProperty; + +class VineBlock : public Block { +public: + static BooleanProperty* EAST; + static BooleanProperty* WEST; + static BooleanProperty* SOUTH; + static BooleanProperty* NORTH; + VineBlock(); +}; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/WallBlock.h b/src/Minecraft.World/net/minecraft/world/level/block/WallBlock.h index bcf900df..93706caa 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/WallBlock.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/WallBlock.h @@ -1,9 +1,21 @@ #pragma once +#include "net/minecraft/core/StringRepresentable.h" #include "net/minecraft/world/level/block/Block.h" class WallBlock : public Block { public: + class Variant : public StringRepresentable { + public: + static inline Variant* VARIANTS[2]; + static Variant* byData(int data) { return VARIANTS[static_cast(data) > 1 ? 0 : data]; } + int getNameId() { return m_nameId; } + + int m_data; + std::wstring m_name; + int m_nameId; + }; + WallBlock(Block*); static void blockStaticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/block/entity/BlockEntity.h b/src/Minecraft.World/net/minecraft/world/level/block/entity/BlockEntity.h index 83ceb7e6..1e8da66c 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/entity/BlockEntity.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/entity/BlockEntity.h @@ -57,6 +57,7 @@ class BlockEntity : public std::enable_shared_from_this { virtual void mirror(Mirror*); CompoundTag* saveMetadata(CompoundTag*); + bool isType(eINSTANCEOF); void setRenderRemoveStage(unsigned char); bool shouldRemoveForRender() const { return m_renderFlag == 2; } diff --git a/src/Minecraft.World/net/minecraft/world/level/block/state/BlockStateDefinition.h b/src/Minecraft.World/net/minecraft/world/level/block/state/BlockStateDefinition.h index 7faacad3..1b910af0 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/state/BlockStateDefinition.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/state/BlockStateDefinition.h @@ -3,6 +3,7 @@ #include "net/minecraft/world/ArrayWithLength.h" #include "net/minecraft/world/level/block/state/BlockState.h" #include "net/minecraft/world/level/block/state/properties/AbstractProperty.h" +#include #include class Block; @@ -72,14 +73,19 @@ class BlockStateDefinition { void _init(Block* block, const Property** properties, unsigned int propertiesCount); - Block* getBlock(); + Block* getBlock() const; + const std::vector& getProperties() const; + bool hasProperty(const Property*) const; + Boxed* getPropertyValue(const Property*, unsigned short state) const; + // Property must belong to this definition's encoded state table. + const BlockState* getNeighbour(const Property*, Boxed*, unsigned short state) const; const BlockState* any(); - arrayWithLength* getPossibleBlockStates() { return &this->m_states; } + const arrayWithLength* getPossibleBlockStates() const; private: Block* m_block; std::vector m_properties; arrayWithLength m_states; - void** m_propertiesArr; // this is array - void** m_anotherProperties; // this is also array + std::uint8_t* m_propertyBitOffsets; + std::uint16_t* m_propertyBitMasks; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/block/state/properties/AbstractProperty.h b/src/Minecraft.World/net/minecraft/world/level/block/state/properties/AbstractProperty.h index 29adffb1..2eef33a3 100644 --- a/src/Minecraft.World/net/minecraft/world/level/block/state/properties/AbstractProperty.h +++ b/src/Minecraft.World/net/minecraft/world/level/block/state/properties/AbstractProperty.h @@ -20,6 +20,7 @@ class Predicate { template class Predicates { public: + static Predicate* equalTo(T value) { return new EqualToValuePredicate(value); } // TODO: impl those, and check if those below are correctly declared class ConnectivePredicate : public Predicate { bool apply(T) const override; @@ -46,7 +47,13 @@ class Predicates { bool m_constValue; // I guess it's bool, could be union; if you find possiblity of it, do it }; class EqualToValuePredicate : public Predicate { - bool apply(T) const override; + public: + EqualToValuePredicate(T value) : m_value(value) {} + + bool apply(T value) const override { return m_value == value; } + + private: + T m_value; }; }; @@ -110,7 +117,10 @@ class AbstractProperty : public Property { return this->m_name == otherCasted->m_name; } // TODO: this is wrong as hell btw !!!!! - int hashCode() const override { return 31 * (size_t)this->m_typeInfo + javaStringHashCode(this->m_name); } + int hashCode() const override { + return 31 * static_cast(reinterpret_cast(this->m_typeInfo)) + + static_cast(javaStringHashCode(this->m_name)); + } virtual T getUnboxedValue(const std::wstring&) const = 0; virtual std::wstring getName(const T&) const = 0; diff --git a/src/Minecraft.World/net/minecraft/world/level/chunk/Chunk.cpp b/src/Minecraft.World/net/minecraft/world/level/chunk/Chunk.cpp index 19488c41..327e807e 100644 --- a/src/Minecraft.World/net/minecraft/world/level/chunk/Chunk.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/chunk/Chunk.cpp @@ -1,5 +1,7 @@ #include "net/minecraft/world/level/chunk/Chunk.h" +#include + #include "NX/Platform.h" #include "NX/Render/RendererCore.h" #include "net/minecraft/client/CMinecraftApp.h" diff --git a/src/Minecraft.World/net/minecraft/world/level/chunk/Chunk.h b/src/Minecraft.World/net/minecraft/world/level/chunk/Chunk.h index b40d4fca..5d5b0c65 100644 --- a/src/Minecraft.World/net/minecraft/world/level/chunk/Chunk.h +++ b/src/Minecraft.World/net/minecraft/world/level/chunk/Chunk.h @@ -1,5 +1,9 @@ #pragma once +#include + +#include + #include #include "nn/os/os_MutexTypes.h" diff --git a/src/Minecraft.World/net/minecraft/world/level/chunk/ChunkGenerator.h b/src/Minecraft.World/net/minecraft/world/level/chunk/ChunkGenerator.h index f259aed9..3d27b537 100644 --- a/src/Minecraft.World/net/minecraft/world/level/chunk/ChunkGenerator.h +++ b/src/Minecraft.World/net/minecraft/world/level/chunk/ChunkGenerator.h @@ -17,13 +17,14 @@ class ChunkGenerator { static const std::wstring VILLAGE_NAME; static const std::wstring MINESHAFT_NAME; static const std::wstring TEMPLE_NAME; + static const std::wstring END_CITY_NAME; ChunkGenerator() {} virtual ~ChunkGenerator(); virtual LevelChunk* createChunk(int, int) = 0; virtual void postProcess(int, int) = 0; virtual bool postProcessLoadedChunk(LevelChunk*, int, int) = 0; - virtual std::vector* getMobsAt(MobCategory*, const BlockPos&) = 0; + virtual std::vector* getMobsAt(MobCategory*, const BlockPos&) = 0; virtual BlockPos* findNearestMapFeature(Level*, const std::wstring&, const BlockPos&, bool) = 0; virtual void recreateLogicStructuresForChunk(LevelChunk*, int, int) = 0; virtual bool isPosInFeature(Level*, const std::wstring&, const BlockPos&) = 0; diff --git a/src/Minecraft.World/net/minecraft/world/level/chunk/ChunkSource.h b/src/Minecraft.World/net/minecraft/world/level/chunk/ChunkSource.h index f6f520af..9c71b77a 100644 --- a/src/Minecraft.World/net/minecraft/world/level/chunk/ChunkSource.h +++ b/src/Minecraft.World/net/minecraft/world/level/chunk/ChunkSource.h @@ -32,7 +32,7 @@ class ChunkSource { virtual bool shouldSave() = 0; virtual ChunkSource* getCache(); virtual void dataReceived(int, int); - virtual std::vector* getMobsAt(MobCategory*, const BlockPos&) = 0; + virtual std::vector* getMobsAt(MobCategory*, const BlockPos&) = 0; virtual void findNearestMapFeature(Level*, const std::wstring&, const BlockPos&, bool) = 0; virtual int getLoadedChunks() = 0; virtual void recreateLogicStructuresForChunk(LevelChunk*, int, int) = 0; diff --git a/src/Minecraft.World/net/minecraft/world/level/chunk/LevelChunk.h b/src/Minecraft.World/net/minecraft/world/level/chunk/LevelChunk.h index af6b2f10..cfcdab2b 100644 --- a/src/Minecraft.World/net/minecraft/world/level/chunk/LevelChunk.h +++ b/src/Minecraft.World/net/minecraft/world/level/chunk/LevelChunk.h @@ -33,6 +33,7 @@ class LevelChunk { static bool touchedSky; // Name from b1.2_02 LevelChunk(Level*, ChunkPrimer*, int, int); + void setCheckAllLight(); enum EntityCreationType {}; diff --git a/src/Minecraft.World/net/minecraft/world/level/gamemode/minigames/glide/GlideRingGenerator.h b/src/Minecraft.World/net/minecraft/world/level/gamemode/minigames/glide/GlideRingGenerator.h index b7b23557..5adba7c7 100644 --- a/src/Minecraft.World/net/minecraft/world/level/gamemode/minigames/glide/GlideRingGenerator.h +++ b/src/Minecraft.World/net/minecraft/world/level/gamemode/minigames/glide/GlideRingGenerator.h @@ -8,8 +8,24 @@ class TextureAtlasSprite; class GlideRingGenerator { public: - enum eGlideRingSize {}; + // Ordinal names are inferred; the three entries are present in the executable tables. + enum eGlideRingSize { Size0 = 0, Size1 = 1, Size2 = 2 }; static void BuildRing(std::vector&, const AABB*, eGlideRingSize); static TextureAtlasSprite* getIcon(eGlideRingSize); + + // Names for these data tables and internal helpers are inferred from their use. + static TextureAtlasSprite* sIcons[3]; + static const int sCornerCounts[3]; + static const int sRadii[3]; + static const int sStraightOffsets[3]; + static const int sCornerRadii[3]; + static const int sCornerOffsets[3]; + +private: + static void appendSegment(std::vector&, const BlockPos&, eGlideRingSize, unsigned int segment, + int plane); + static BlockPos orientOffset(const BlockPos&, int plane, int horizontal, int vertical); + static int horizontalOffset(eGlideRingSize, unsigned int segment, int index); + static int verticalOffset(eGlideRingSize, unsigned int segment, int index); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/GenericOverworldLevelSource.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/GenericOverworldLevelSource.h index a6380507..dc371f2f 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/GenericOverworldLevelSource.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/GenericOverworldLevelSource.h @@ -7,5 +7,5 @@ class GenericOverworldLevelSource { GenericOverworldLevelSource() {} virtual void prepareHeights(int, int, ChunkPrimer*); - // missing a second unknown virtual function + virtual bool isFlat(); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/LevelGenerationOptions.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/LevelGenerationOptions.h index da54064e..1760daf3 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/LevelGenerationOptions.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/LevelGenerationOptions.h @@ -1,9 +1,15 @@ #pragma once #include "net/minecraft/world/level/LevelRuleset.h" +#include "net/minecraft/world/level/biome/Biome.h" + +class BlockPos; class LevelGenerationOptions { public: LevelRuleset* getRequiredGameRules(); void loadBaseSaveData(); + bool intersects(const BlockPos& lower, const BlockPos& upper); + // LegacyBlockData is the reconstruction's existing name for original BlockPair. + void getBiomeOverride(int biomeId, Biome::LegacyBlockData* filler, Biome::LegacyBlockData* surface); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/NetherFlatLevelSource.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/NetherFlatLevelSource.cpp index a9162366..28715550 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/NetherFlatLevelSource.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/NetherFlatLevelSource.cpp @@ -172,8 +172,8 @@ bool NetherFlatLevelSource::postProcessLoadedChunk(LevelChunk* chunk, int x, int return false; } -std::vector* NetherFlatLevelSource::getMobsAt(MobCategory* category, - const BlockPos& pos) { +std::vector* NetherFlatLevelSource::getMobsAt(MobCategory* category, + const BlockPos& pos) { Biome* biome = m_level->getBiome(pos); if (biome) return biome->getMobs(category); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/NetherFlatLevelSource.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/NetherFlatLevelSource.h index a3ee492a..4d89392b 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/NetherFlatLevelSource.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/NetherFlatLevelSource.h @@ -12,7 +12,7 @@ class NetherFlatLevelSource : public ChunkGenerator { LevelChunk* createChunk(int, int) override; void postProcess(int, int) override; bool postProcessLoadedChunk(LevelChunk*, int, int) override; - std::vector* getMobsAt(MobCategory*, const BlockPos&) override; + std::vector* getMobsAt(MobCategory*, const BlockPos&) override; BlockPos* findNearestMapFeature(Level*, const std::wstring&, const BlockPos&, bool) override; void recreateLogicStructuresForChunk(LevelChunk*, int, int) override; bool isPosInFeature(Level*, const std::wstring&, const BlockPos&) override; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/OverworldLevelSource.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/OverworldLevelSource.cpp index f2e63c38..169a3542 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/OverworldLevelSource.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/OverworldLevelSource.cpp @@ -1,5 +1,7 @@ #include "net/minecraft/world/level/levelgen/OverworldLevelSource.h" +#include + #include "NX/Platform.h" #include "net/minecraft/util/Mth.h" #include "net/minecraft/world/entity/MobCategory.h" @@ -128,7 +130,6 @@ float OverworldLevelSource::getHeightFalloff(int chunkX, int chunkZ, int* distan return result; } -// NON_MATCHING | Score: 1630 (lower is better) int OverworldLevelSource::distanceToEdge(float a, int, int x, int z, int size) { int halfSize = size / 2; @@ -150,18 +151,19 @@ int OverworldLevelSource::distanceToEdge(float a, int, int x, int z, int size) { if (inLeftBand || inRightBand) { Vec3* p = Vec3::newTemp(x, 0.0f, z); - Vec3* edgeStart = (x < 1) ? topLeft : topRight; - Vec3* edgeEnd = (x < 1) ? bottomLeft : bottomRight; - - distance = p->distanceToSegment(edgeStart, edgeEnd); + if (x >= 1) + distance = p->distanceToSegment(topRight, bottomRight); + else + distance = p->distanceToSegment(topLeft, bottomLeft); } if (((z > leftBound) && (z < rightBound)) || ((z > (maxCoord - a)) && (z < (maxCoord + a)))) { Vec3* p = Vec3::newTemp(x, 0.0f, z); - Vec3* edgeStart = (z < 1) ? topLeft : topRight; - Vec3* edgeEnd = (z < 1) ? bottomLeft : bottomRight; - - float verticalDistance = p->distanceToSegment(edgeStart, edgeEnd); + float verticalDistance; + if (z >= 1) + verticalDistance = p->distanceToSegment(bottomLeft, bottomRight); + else + verticalDistance = p->distanceToSegment(topLeft, topRight); if (verticalDistance < distance) { distance = verticalDistance; @@ -184,7 +186,7 @@ void OverworldLevelSource::buildSurfaces(int chunkX, int chunkZ, ChunkPrimer* pr for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { - Biome* biome = biomes[z + x * 16]; + Biome* biome = biomes.get(z + x * 16); { std::wstring biomeName = biome->getName(false); PIXBeginNamedEvent(0.0, "Building surface for biome %ls", biomeName.c_str()); @@ -322,11 +324,11 @@ void OverworldLevelSource::getHeights(int posX, int posY, int posZ, arrayWithLen float weightedScale = 0.0f; float weightedDepth = 0.0f; float totalWeight = 0.0f; - Biome* b = biomes[x + 2 + (z + 2) * 10]; + Biome* b = biomes.get(x + 2 + (z + 2) * 10); for (int xo = -2; xo <= 2; ++xo) { for (int zo = -2; zo <= 2; ++zo) { - Biome* b2 = biomes[x + xo + 2 + (z + zo + 2) * 10]; + Biome* b2 = biomes.get(x + xo + 2 + (z + zo + 2) * 10); float depth = m_sourceSettings->m_biomeDepthOffset + (b2->getDepth() * m_sourceSettings->m_biomeDepthWeight); @@ -563,19 +565,25 @@ void OverworldLevelSource::prepareHeights(int chunkX, int chunkZ, ChunkPrimer* p PIXBeginNamedEvent(0.0, "Generating"); for (int subX = 0; subX < width; subX++) { + int leftColumn = subX * xSize; + int rightColumn = (subX + 1) * xSize; for (int subZ = 0; subZ < width; subZ++) { + int n00 = (subZ + leftColumn) * ySize; + int n10 = n00 + ySize; + int n01 = (subZ + rightColumn) * ySize; + int n11 = n01 + ySize; for (int subY = 0; subY < 16; subY++) { // + 0 is for padding so these look nicer - double h00 = heights[((subX + 0) * xSize + (subZ + 0)) * ySize + subY]; - double h10 = heights[((subX + 0) * xSize + (subZ + 1)) * ySize + subY]; - double h01 = heights[((subX + 1) * xSize + (subZ + 0)) * ySize + subY]; - double h11 = heights[((subX + 1) * xSize + (subZ + 1)) * ySize + subY]; + double h00 = heights[n00 + subY]; + double h10 = heights[n10 + subY]; + double h01 = heights[n01 + subY]; + double h11 = heights[n11 + subY]; // interpolation steps - double iy00 = (heights[((subX + 0) * xSize + (subZ + 0)) * ySize + subY + 1] - h00) * 0.125; - double iy10 = (heights[((subX + 0) * xSize + (subZ + 1)) * ySize + subY + 1] - h10) * 0.125; - double iy01 = (heights[((subX + 1) * xSize + (subZ + 0)) * ySize + subY + 1] - h01) * 0.125; - double iy11 = (heights[((subX + 1) * xSize + (subZ + 1)) * ySize + subY + 1] - h11) * 0.125; + double iy00 = (heights[n00 + subY + 1] - h00) * 0.125; + double iy10 = (heights[n10 + subY + 1] - h10) * 0.125; + double iy01 = (heights[n01 + subY + 1] - h01) * 0.125; + double iy11 = (heights[n11 + subY + 1] - h11) * 0.125; for (int ym = 0; ym < 8; ym++) { double heightAtXZ0 = h00; @@ -591,19 +599,20 @@ void OverworldLevelSource::prepareHeights(int chunkX, int chunkZ, ChunkPrimer* p int defaultId = (subY * height + ym < seaLevel) ? 9 : 0; - double _h = h00; + double _h = heightAtXZ0; double _hStep = (heightAtXZ1 - heightAtXZ0) * 0.25; _h -= _hStep; for (int zm = 0; zm < 4; zm++) { - int x = subX * width + xm; + int x = chunkX * 16 + subX * width + xm; int y = subY * height + ym; - int z = subZ * width + zm; + int z = chunkZ * 16 + subZ * width + zm; int blockId; int distance; // Falloff at the edge of the world, does not exist in Java Edition - if (getHeightFalloff(x, z, &distance) > (_h += _hStep)) { + float falloff = getHeightFalloff(x, z, &distance); + if ((_h += _hStep) > falloff) { blockId = 1; } else { blockId = defaultId; @@ -642,8 +651,8 @@ void OverworldLevelSource::prepareHeights(int chunkX, int chunkZ, ChunkPrimer* p delete[] biomes.m_data; } -std::vector* OverworldLevelSource::getMobsAt(MobCategory* category, - const BlockPos& pos) { +std::vector* OverworldLevelSource::getMobsAt(MobCategory* category, + const BlockPos& pos) { Biome* biome = m_level->getBiome(pos); if (m_shouldGenerateStructures) { @@ -687,30 +696,29 @@ void OverworldLevelSource::recreateLogicStructuresForChunk(LevelChunk* chunk, in } } -// NON_MATCHING | Score: 860- (lower is better) bool OverworldLevelSource::isPosInFeature(Level* level, const std::wstring& featureName, const BlockPos& pos) { if (!m_shouldGenerateStructures) { return false; } - if (ChunkGenerator::STRONGHOLD_NAME.compare(featureName) == 0) { - return m_strongholdFeature && m_strongholdFeature->isInsideFeature(pos); + if (ChunkGenerator::STRONGHOLD_NAME.compare(featureName) == 0 && m_strongholdFeature) { + return m_strongholdFeature->isInsideFeature(pos); } - if (ChunkGenerator::MANSION_NAME.compare(featureName) == 0) { - return m_woodlandMansionFeature && m_woodlandMansionFeature->isInsideFeature(pos); + if (ChunkGenerator::MANSION_NAME.compare(featureName) == 0 && m_woodlandMansionFeature) { + return m_woodlandMansionFeature->isInsideFeature(pos); } - if (ChunkGenerator::MONUMENT_NAME.compare(featureName) == 0) { - return m_oceanMonumentFeature && m_oceanMonumentFeature->isInsideFeature(pos); + if (ChunkGenerator::MONUMENT_NAME.compare(featureName) == 0 && m_oceanMonumentFeature) { + return m_oceanMonumentFeature->isInsideFeature(pos); } - if (ChunkGenerator::VILLAGE_NAME.compare(featureName) == 0) { - return m_villageFeature && m_villageFeature->isInsideFeature(pos); + if (ChunkGenerator::VILLAGE_NAME.compare(featureName) == 0 && m_villageFeature) { + return m_villageFeature->isInsideFeature(pos); } - if (ChunkGenerator::MINESHAFT_NAME.compare(featureName) == 0) { - return m_mineshaftFeature && m_mineshaftFeature->isInsideFeature(pos); + if (ChunkGenerator::MINESHAFT_NAME.compare(featureName) == 0 && m_mineshaftFeature) { + return m_mineshaftFeature->isInsideFeature(pos); } - if (ChunkGenerator::TEMPLE_NAME.compare(featureName) == 0) { - return m_randomScatteredLargeFeature && m_randomScatteredLargeFeature->isInsideFeature(pos); + if (ChunkGenerator::TEMPLE_NAME.compare(featureName) == 0 && m_randomScatteredLargeFeature) { + return m_randomScatteredLargeFeature->isInsideFeature(pos); } return false; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/OverworldLevelSource.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/OverworldLevelSource.h index 200aa253..0f46b7f5 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/OverworldLevelSource.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/OverworldLevelSource.h @@ -38,7 +38,7 @@ class OverworldLevelSource : public ChunkGenerator, public GenericOverworldLevel LevelChunk* createChunk(int, int) override; void postProcess(int, int) override; bool postProcessLoadedChunk(LevelChunk*, int, int) override; - std::vector* getMobsAt(MobCategory*, const BlockPos&) override; + std::vector* getMobsAt(MobCategory*, const BlockPos&) override; BlockPos* findNearestMapFeature(Level*, const std::wstring&, const BlockPos&, bool) override; void recreateLogicStructuresForChunk(LevelChunk*, int, int) override; bool isPosInFeature(Level*, const std::wstring&, const BlockPos&) override; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/EndCityFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/EndCityFeature.h new file mode 100644 index 00000000..2ccbe984 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/EndCityFeature.h @@ -0,0 +1,18 @@ +#pragma once + +#include "net/minecraft/world/level/levelgen/feature/StructureFeature.h" + +class TheEndLevelSource; + +// Constructor and specialized virtual methods remain unreconstructed. +class EndCityFeature : public StructureFeature { +public: + std::wstring getFeatureName() override; + BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) override; + bool isFeatureChunk(int, int, bool) override; + StructureStart* createStructureStart(int, int) override; + + explicit EndCityFeature(TheEndLevelSource*); + TheEndLevelSource* m_source; +}; +ASSERT_SIZEOF(EndCityFeature, 0x70) diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/Feature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/Feature.h index 8cdbf359..832283bb 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/Feature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/Feature.h @@ -7,7 +7,7 @@ class BlockState; class Feature { public: - Feature(bool isUpdate); + Feature(bool isUpdate = false); virtual ~Feature(); virtual bool place(Level* level, Random& random, const BlockPos& pos) = 0; virtual void init(); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/FlowerFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/FlowerFeature.h index dc75dada..13a8daa3 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/FlowerFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/FlowerFeature.h @@ -7,9 +7,9 @@ class FlowerFeature : public Feature { public: FlowerFeature(FlowerBlock*, FlowerBlock::Flower*); - ~FlowerFeature() override; bool place(Level* level, Random& random, const BlockPos& pos) override; + void setFlower(FlowerBlock*, FlowerBlock::Flower*); - void* m_field10; - void* m_field18; + FlowerBlock* m_flower; + const BlockState* m_state; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/FossilFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/FossilFeature.h new file mode 100644 index 00000000..e5e9f87c --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/FossilFeature.h @@ -0,0 +1,13 @@ +#pragma once + +#include "net/minecraft/world/level/levelgen/feature/Feature.h" +#include "types.h" + +class FossilFeature : public Feature { +public: + FossilFeature() = default; + ~FossilFeature() override = default; + bool place(Level*, Random&, const BlockPos&) override; +}; + +ASSERT_SIZEOF(FossilFeature, 0x10) diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/LargeFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/LargeFeature.h index 1cef066b..2c0c185b 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/LargeFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/LargeFeature.h @@ -7,11 +7,12 @@ class Level; class LargeFeature { public: + LargeFeature(); virtual ~LargeFeature(); virtual void apply(Level*, int, int, ChunkPrimer*); virtual void addFeature(Level*, int, int, int, int, ChunkPrimer*); int m_radius; Random m_random; - void* m_unused; + Level* m_level; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/MineShaftFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/MineShaftFeature.h index 9bffdc34..b02cd3c0 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/MineShaftFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/MineShaftFeature.h @@ -4,6 +4,11 @@ class MineShaftFeature : public StructureFeature { public: + std::wstring getFeatureName() override; + BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) override; + bool isFeatureChunk(int, int, bool) override; + StructureStart* createStructureStart(int, int) override; + MineShaftFeature(); char m_filler[0x8]; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/MonsterRoomFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/MonsterRoomFeature.h index 371cd466..0b8e69e3 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/MonsterRoomFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/MonsterRoomFeature.h @@ -1,10 +1,14 @@ #pragma once #include "net/minecraft/world/level/levelgen/feature/Feature.h" +#include class MonsterRoomFeature : public Feature { public: MonsterRoomFeature(); bool place(Level* level, Random& random, const BlockPos& pos) override; + +private: + std::wstring randomEntityId(Random&); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/NetherBridgeFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/NetherBridgeFeature.h new file mode 100644 index 00000000..5260ab58 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/NetherBridgeFeature.h @@ -0,0 +1,22 @@ +#pragma once + +#include "net/minecraft/world/level/biome/Biome.h" +#include "net/minecraft/world/level/levelgen/feature/StructureFeature.h" + +class NetherBridgeFeature : public StructureFeature { +public: + std::wstring getFeatureName() override; + BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) override; + bool isFeatureChunk(int, int, bool) override; + StructureStart* createStructureStart(int, int) override; + + NetherBridgeFeature(); + ~NetherBridgeFeature() override; + std::vector* getSpawnList(); + +private: + // Structure-owned spawn data and trailing state are still external reconstruction work. + char m_unknown68[0x28]; +}; + +ASSERT_SIZEOF(NetherBridgeFeature, 0x90) diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/OceanMonumentFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/OceanMonumentFeature.h index bfa3f3f9..f7161500 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/OceanMonumentFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/OceanMonumentFeature.h @@ -7,11 +7,16 @@ class OceanMonumentFeature : public StructureFeature { public: - static std::vector MOB_SPAWNERS; + std::wstring getFeatureName() override; + BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) override; + bool isFeatureChunk(int, int, bool) override; + StructureStart* createStructureStart(int, int) override; + + static std::vector MOB_SPAWNERS; OceanMonumentFeature(); - std::vector* getEnemies(); + std::vector* getEnemies(); static void staticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/RandomScatteredLargeFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/RandomScatteredLargeFeature.h index 72851eb6..12eb4dcb 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/RandomScatteredLargeFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/RandomScatteredLargeFeature.h @@ -7,10 +7,15 @@ class BlockPos; class RandomScatteredLargeFeature : public StructureFeature { public: + std::wstring getFeatureName() override; + BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) override; + bool isFeatureChunk(int, int, bool) override; + StructureStart* createStructureStart(int, int) override; + RandomScatteredLargeFeature(); bool isSwamphut(const BlockPos&); - std::vector* getSwamphutEnemies(); + std::vector* getSwamphutEnemies(); static void staticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StrongholdFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StrongholdFeature.h index ac3cb0ea..c3dd9b6f 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StrongholdFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StrongholdFeature.h @@ -4,6 +4,12 @@ class StrongholdFeature : public StructureFeature { public: + std::wstring getFeatureName() override; + BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) override; + bool isFeatureChunk(int, int, bool) override; + StructureStart* createStructureStart(int, int) override; + std::vector* getGuesstimatedFeaturePositions() override; + StrongholdFeature(); char m_filler[0x48]; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StructureFeature.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StructureFeature.cpp new file mode 100644 index 00000000..0a5540ff --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StructureFeature.cpp @@ -0,0 +1,162 @@ +#include "net/minecraft/world/level/levelgen/feature/StructureFeature.h" + +#include "com/mojang/nbt/ByteArrayTag.h" +#include "com/mojang/nbt/CompoundTag.h" +#include "net/minecraft/core/BlockPos.h" +#include "net/minecraft/world/level/Level.h" +#include "net/minecraft/world/level/LevelType.h" +#include "net/minecraft/world/level/chunk/ChunkPos.h" +#include "net/minecraft/world/level/levelgen/structure/BoundingBox.h" +#include "net/minecraft/world/level/levelgen/structure/StructureFeatureIO.h" +#include "net/minecraft/world/level/levelgen/structure/StructurePiece.h" +#include "net/minecraft/world/level/levelgen/structure/StructureStart.h" +#include "net/minecraft/world/level/saveddata/StructureFeatureSavedData.h" +#include "net/minecraft/world/level/storage/LevelData.h" + +StructureFeature::StructureFeature() { + m_savedData = nullptr; +} + +StructureFeature::~StructureFeature() { + for (auto it = m_starts.begin(); it != m_starts.end(); ++it) + delete it->second; +} + +void StructureFeature::addFeature(Level* level, int sourceX, int sourceZ, int, int, ChunkPrimer*) { + restoreSavedData(level); + if (m_starts.find(ChunkPos::asLong(sourceX, sourceZ)) == m_starts.end()) { + m_random.nextInt(); + if (isFeatureChunk(sourceX, sourceZ, level->getLevelData()->getGeneratorType() == LevelType::FLAT)) { + StructureStart* start = createStructureStart(sourceX, sourceZ); + m_starts[ChunkPos::asLong(sourceX, sourceZ)] = start; + if (start->isValid()) + saveFeature(sourceX, sourceZ, start); + } + } +} + +bool StructureFeature::postProcess(Level* level, Random& random, ChunkPos* chunk) { + restoreSavedData(level); + int x = chunk->m_x << 4; + int z = chunk->m_z << 4; + bool generated = false; + for (auto it = m_starts.begin(); it != m_starts.end(); ++it) { + StructureStart* start = it->second; + if (start->isValid() && start->isValidForPostProcess(chunk) + && start->getBoundingBox()->intersects(x, z, x + 15, z + 15)) { + BoundingBox bounds(x, z, x + 15, z + 15); + start->postProcess(level, random, &bounds); + start->notifyPostProcessAt(chunk); + if (start->isDirty()) + saveFeature(start->getChunkX(), start->getChunkZ(), start); + generated = true; + } + } + return generated; +} + +bool StructureFeature::isIntersection(int x, int z) { + restoreSavedData(m_level); + for (auto it = m_starts.begin(); it != m_starts.end(); ++it) { + StructureStart* start = it->second; + if (start->isValid() && start->getBoundingBox()->intersects(x, z, x, z)) { + auto* pieces = start->getPieces(); + for (auto piece = pieces->begin(); piece != pieces->end(); ++piece) + if ((*piece)->getBoundingBox()->intersects(x, z, x, z)) + return true; + } + } + return false; +} + +bool StructureFeature::isInsideFeature(const BlockPos& pos) { + if (!m_level) + return false; + restoreSavedData(m_level); + return getStructureAt(pos) != nullptr; +} + +StructureStart* StructureFeature::getStructureAt(const BlockPos& pos) { + for (auto it = m_starts.begin(); it != m_starts.end(); ++it) { + StructureStart* start = it->second; + if (start->isValid() && start->getBoundingBox()->isInside(pos)) { + auto* pieces = start->getPieces(); + auto piece = pieces->begin(); + while (piece != pieces->end()) { + if ((*piece)->getBoundingBox()->isInside(pos)) + return start; + ++piece; + } + } + } + return nullptr; +} + +bool StructureFeature::isInsideBoundingFeature(Level* level, const BlockPos& pos) { + restoreSavedData(level); + for (auto it = m_starts.begin(); it != m_starts.end(); ++it) { + StructureStart* start = it->second; + if (start->isValid() && start->getBoundingBox()->isInside(pos)) + return true; + } + return false; +} + +std::vector* StructureFeature::getGuesstimatedFeaturePositions() { + return nullptr; +} + +void StructureFeature::restoreSavedData(Level* level) { + if (level && !m_savedData) { + m_savedData = std::dynamic_pointer_cast( + level->getSavedData(typeid(StructureFeatureSavedData), getFeatureName())); + if (!m_savedData) { + m_savedData + = std::shared_ptr(new StructureFeatureSavedData(getFeatureName())); + level->setSavedData(getFeatureName(), m_savedData); + } else { + auto* tags = m_savedData->getFullTag()->getAllTags(); + for (auto it = tags->begin(); it != tags->end(); ++it) { + Tag* tag = it->second; + if (tag->getId() == Tag::TAG_Byte_Array) { + StructureStart* start + = StructureFeatureIO::loadStaticStart(static_cast(tag), level); + if (start) + m_starts[ChunkPos::asLong(start->getChunkX(), start->getChunkZ())] = start; + } + } + } + } +} + +void StructureFeature::saveFeature(int chunkX, int chunkZ, StructureStart* start) { + m_savedData->putFeatureTag(start->createTag(chunkX, chunkZ), chunkX, chunkZ); + m_savedData->setDirty(); + start->clearDirty(); +} + +BlockPos* StructureFeature::findNearestFeaturePositionBySpacing(Level* level, StructureFeature* feature, + const BlockPos& origin, int, int, int, bool, + int maxRadius, bool skipKnown) { + int centerX = origin.getX() >> 4; + int centerZ = origin.getZ() >> 4; + int halfSize = level->getLevelData()->getXZSize() / 2; + // The Switch's finite-world search visits successive chunk-square perimeters. + for (int radius = 0; radius <= maxRadius; ++radius) { + for (int dx = -radius; dx <= radius; ++dx) { + bool edgeX = dx == -radius || dx == radius; + for (int dz = -radius; dz <= radius; ++dz) { + if (edgeX || dz == -radius || dz == radius) { + int x = centerX + dx; + int z = centerZ + dz; + if (feature->isFeatureChunk(x, z, + level->getLevelData()->getGeneratorType() == LevelType::FLAT) + && x >= -halfSize && x <= halfSize && z >= -halfSize && z <= halfSize + && (!skipKnown || !level->isChunkGeneratedAt(x, z))) + return new BlockPos((x << 4) + 8, 64, (z << 4) + 8); + } + } + } + } + return nullptr; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StructureFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StructureFeature.h index 9ae37554..d2edc95d 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StructureFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/StructureFeature.h @@ -2,27 +2,40 @@ #include "net/minecraft/world/level/levelgen/feature/LargeFeature.h" #include "types.h" +#include +#include +#include +#include class BlockPos; class ChunkPos; +class StructureFeatureSavedData; class StructureStart; class StructureFeature : public LargeFeature { public: - virtual std::wstring getFeatureName(); + StructureFeature(); + ~StructureFeature() override; + void addFeature(Level*, int, int, int, int, ChunkPrimer*) override; + virtual std::wstring getFeatureName() = 0; virtual bool postProcess(Level*, Random&, ChunkPos*); virtual bool isIntersection(int, int); virtual bool isInsideFeature(const BlockPos&); - virtual BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool); - virtual void getGuesstimatedFeaturePositions(); + virtual BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) = 0; + virtual std::vector* getGuesstimatedFeaturePositions(); virtual void restoreSavedData(Level*); virtual void saveFeature(int, int, StructureStart*); - virtual bool isFeatureChunk(int, int, bool); - virtual void createStructureStart(int, int); - - char m_filler[0x38]; + virtual bool isFeatureChunk(int, int, bool) = 0; + virtual StructureStart* createStructureStart(int, int) = 0; + StructureStart* getStructureAt(const BlockPos&); bool isInsideBoundingFeature(Level*, const BlockPos&); + static BlockPos* findNearestFeaturePositionBySpacing(Level*, StructureFeature*, const BlockPos&, + int spacing, int separation, int salt, bool linear, + int maxRadius, bool skipKnown); + + std::shared_ptr m_savedData; + std::unordered_map m_starts; }; ASSERT_SIZEOF(StructureFeature, 0x68) diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/VillageFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/VillageFeature.h index df581bf5..569e8fa6 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/VillageFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/VillageFeature.h @@ -1,12 +1,21 @@ #pragma once #include "net/minecraft/world/level/levelgen/feature/StructureFeature.h" +#include + +class Biome; class VillageFeature : public StructureFeature { public: + std::wstring getFeatureName() override; + BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) override; + bool isFeatureChunk(int, int, bool) override; + StructureStart* createStructureStart(int, int) override; + VillageFeature(int); static void staticCtor(); + static std::vector ALLOWED_BIOMES; char m_filler[0x10]; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/WoodlandMansionFeature.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/WoodlandMansionFeature.h index fb911195..0c2d3c7a 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/WoodlandMansionFeature.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/feature/WoodlandMansionFeature.h @@ -3,10 +3,17 @@ #include "net/minecraft/world/level/levelgen/feature/StructureFeature.h" class GenericOverworldLevelSource; +class SuperflatConfig; class WoodlandMansionFeature : public StructureFeature { public: + std::wstring getFeatureName() override; + BlockPos* getNearestGeneratedFeature(Level*, const BlockPos&, bool) override; + bool isFeatureChunk(int, int, bool) override; + StructureStart* createStructureStart(int, int) override; + WoodlandMansionFeature(GenericOverworldLevelSource*); + WoodlandMansionFeature(GenericOverworldLevelSource*, SuperflatConfig*); static void staticCtor(); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/BoundingBox.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/BoundingBox.cpp index ebfcc641..6e7f4e33 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/BoundingBox.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/BoundingBox.cpp @@ -1,5 +1,12 @@ #include "net/minecraft/world/level/levelgen/structure/BoundingBox.h" +#include "java/io/DataInputStream.h" +#include "java/io/DataOutputStream.h" +#include "net/minecraft/core/BlockPos.h" +#include "net/minecraft/core/Direction.h" +#include +#include + BoundingBox::BoundingBox(int x0, int y0, int z0, int x1, int y1, int z1) { this->m_x0 = x0; this->m_y0 = y0; @@ -8,3 +15,127 @@ BoundingBox::BoundingBox(int x0, int y0, int z0, int x1, int y1, int z1) { this->m_y1 = y1; this->m_z1 = z1; } + +// Names of the shared integer helpers are inferred from their use in box expansion. +int boundingBoxMin(int a, int b) { + return a < b ? a : b; +} +int boundingBoxMax(int a, int b) { + return a > b ? a : b; +} + +BoundingBox::BoundingBox() : m_x0(0), m_y0(0), m_z0(0), m_x1(0), m_y1(0), m_z1(0) {} + +BoundingBox::BoundingBox(BoundingBox* other) { + m_x0 = other->m_x0; + m_y0 = other->m_y0; + m_z0 = other->m_z0; + m_x1 = other->m_x1; + m_y1 = other->m_y1; + m_z1 = other->m_z1; +} + +BoundingBox::BoundingBox(int x0, int z0, int x1, int z1) { + m_y1 = 512; + m_z1 = z1; + m_z0 = z0; + m_x1 = x1; + m_x0 = x0; + m_y0 = 1; +} + +BoundingBox* BoundingBox::getUnknownBox() { + return new BoundingBox(INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MIN, INT_MIN); +} + +BoundingBox* BoundingBox::createProper(int x0, int y0, int z0, int x1, int y1, int z1) { + return new BoundingBox(std::min(x0, x1), std::min(y0, y1), std::min(z0, z1), std::max(x0, x1), + std::max(y0, y1), std::max(z0, z1)); +} + +BoundingBox* BoundingBox::orientBox(int x, int y, int z, int offsetX, int offsetY, int offsetZ, int width, + int height, int depth, const Direction* direction) { + switch (direction->get3DDataValue()) { + case 2: + return new BoundingBox(x + offsetX, y + offsetY, z + offsetZ + 1 - depth, x + offsetX + width - 1, + y + offsetY + height - 1, z + offsetZ); + case 4: + return new BoundingBox(x + offsetZ + 1 - depth, y + offsetY, z + offsetX, x + offsetZ, + y + offsetY + height - 1, z + offsetX + width - 1); + case 5: + return new BoundingBox(x + offsetZ, y + offsetY, z + offsetX, x + offsetZ + depth - 1, + y + offsetY + height - 1, z + offsetX + width - 1); + default: + return new BoundingBox(x + offsetX, y + offsetY, z + offsetZ, x + offsetX + width - 1, + y + offsetY + height - 1, z + offsetZ + depth - 1); + } +} + +bool BoundingBox::intersects(BoundingBox* other) { + return m_x1 >= other->m_x0 && m_x0 <= other->m_x1 && m_z1 >= other->m_z0 && m_z0 <= other->m_z1 + && m_y1 >= other->m_y0 && m_y0 <= other->m_y1; +} + +bool BoundingBox::intersects(Vec3i lower, Vec3i upper) { + return m_x1 >= lower.getX() && m_x0 <= upper.getX() && m_z1 >= lower.getZ() && m_z0 <= upper.getZ() + && m_y1 >= lower.getY() && m_y0 <= upper.getY(); +} + +bool BoundingBox::intersects(int x0, int z0, int x1, int z1) { + return m_x1 >= x0 && m_x0 <= x1 && m_z1 >= z0 && m_z0 <= z1; +} + +void BoundingBox::expand(BoundingBox* other) { + m_x0 = boundingBoxMin(m_x0, other->m_x0); + m_y0 = boundingBoxMin(m_y0, other->m_y0); + m_z0 = boundingBoxMin(m_z0, other->m_z0); + m_x1 = boundingBoxMax(m_x1, other->m_x1); + m_y1 = boundingBoxMax(m_y1, other->m_y1); + m_z1 = boundingBoxMax(m_z1, other->m_z1); +} + +void BoundingBox::move(int x, int y, int z) { + m_x0 += x; + m_y0 += y; + m_z0 += z; + m_x1 += x; + m_y1 += y; + m_z1 += z; +} + +bool BoundingBox::isInside(Vec3i pos) { + return pos.getX() >= m_x0 && pos.getX() <= m_x1 && pos.getZ() >= m_z0 && pos.getZ() <= m_z1 + && pos.getY() >= m_y0 && pos.getY() <= m_y1; +} + +int BoundingBox::getXSpan() { + return m_x1 - m_x0 + 1; +} +int BoundingBox::getYSpan() { + return m_y1 - m_y0 + 1; +} +int BoundingBox::getZSpan() { + return m_z1 - m_z0 + 1; +} + +BlockPos BoundingBox::getCenter() { + return BlockPos(m_x0 + (m_x1 - m_x0 + 1) / 2, m_y0 + (m_y1 - m_y0 + 1) / 2, m_z0 + (m_z1 - m_z0 + 1) / 2); +} + +void BoundingBox::write(DataOutputStream* stream) { + stream->writeInt(m_x0); + stream->writeInt(m_y0); + stream->writeInt(m_z0); + stream->writeInt(m_x1); + stream->writeInt(m_y1); + stream->writeInt(m_z1); +} + +void BoundingBox::read(DataInputStream* stream) { + m_x0 = stream->readInt(); + m_y0 = stream->readInt(); + m_z0 = stream->readInt(); + m_x1 = stream->readInt(); + m_y1 = stream->readInt(); + m_z1 = stream->readInt(); +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/BoundingBox.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/BoundingBox.h index bb2ab077..86c38fae 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/BoundingBox.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/BoundingBox.h @@ -1,5 +1,11 @@ #pragma once +class BlockPos; +class Direction; +class Vec3i; +class DataInputStream; +class DataOutputStream; + class BoundingBox { public: int m_x0; @@ -9,5 +15,26 @@ class BoundingBox { int m_y1; int m_z1; + BoundingBox(); + explicit BoundingBox(BoundingBox*); + BoundingBox(int x0, int z0, int x1, int z1); BoundingBox(int x0, int y0, int z0, int x1, int y1, int z1); + static BoundingBox* getUnknownBox(); + static BoundingBox* createProper(int, int, int, int, int, int); + static BoundingBox* orientBox(int x, int y, int z, int offsetX, int offsetY, int offsetZ, int width, + int height, int depth, const Direction*); + bool intersects(BoundingBox*); + bool intersects(Vec3i lower, Vec3i upper); + bool intersects(int x0, int z0, int x1, int z1); + void expand(BoundingBox*); + void move(int x, int y, int z); + bool isInside(Vec3i); + int getXSpan(); + int getYSpan(); + int getZSpan(); + BlockPos getCenter(); + void write(DataOutputStream*); + void read(DataInputStream*); }; + +static_assert(sizeof(BoundingBox) == 0x18, "Switch bounding box layout"); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureFeatureIO.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureFeatureIO.h index 908f873f..75547c4c 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureFeatureIO.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureFeatureIO.h @@ -1,6 +1,18 @@ #pragma once +#include + +class DataInputStream; +class ByteArrayTag; +class Level; +class StructurePiece; +class StructureStart; + class StructureFeatureIO { public: static void staticCtor(); + static std::wstring getEncodeId(StructureStart*); + static std::wstring getEncodeId(StructurePiece*); + static StructurePiece* loadStaticPiece(DataInputStream*, Level*); + static StructureStart* loadStaticStart(ByteArrayTag*, Level*); }; diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePiece.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePiece.h new file mode 100644 index 00000000..c54c2919 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePiece.h @@ -0,0 +1,102 @@ +#pragma once + +#include + +class BlockPos; +class BlockState; +class BoundingBox; +class CompoundTag; +class DataInputStream; +class DataOutputStream; +class Direction; +class Level; +class Mirror; +class Random; +class ResourceLocation; +class Rotation; +class StructureManager; + +class StructurePiece { +public: + class BlockSelector { + public: + BlockSelector(); + virtual ~BlockSelector(); + virtual void next(Random&, int x, int y, int z, bool boundary) = 0; + virtual const BlockState* getNext(); + + const BlockState* m_next; + }; + + StructurePiece(); + explicit StructurePiece(int genDepth); + + virtual int GetType() = 0; + virtual ~StructurePiece(); + virtual CompoundTag* createTag(); + virtual void addAdditionalSaveData(DataOutputStream*) = 0; + virtual void load(Level*, DataInputStream*); + virtual void readAdditionalSaveData(DataInputStream*, StructureManager*) = 0; + virtual void addChildren(StructurePiece*, std::vector*, Random&); + virtual bool postProcess(Level*, Random&, BoundingBox*) = 0; + virtual BoundingBox* getBoundingBox(); + virtual BlockPos* getLocatorPosition(); + virtual void placeBlock(Level*, const BlockState*, int, int, int, BoundingBox*); + virtual const BlockState* getBlock(Level*, int, int, int, BoundingBox*); + virtual int getSkyBrightness(Level*, int, int, int, BoundingBox*); + virtual void generateAirBox(Level*, BoundingBox*, int, int, int, int, int, int); + virtual void generateBox(Level*, BoundingBox*, int, int, int, int, int, int, const BlockState*, + const BlockState*, bool); + virtual void generateBox(Level*, BoundingBox*, BoundingBox*, const BlockState*, const BlockState*, bool); + virtual void generateBox(Level*, BoundingBox*, int, int, int, int, int, int, bool, Random&, + BlockSelector*); + virtual void generateBox(Level*, BoundingBox*, BoundingBox*, bool, Random&, BlockSelector*); + virtual void generateMaybeBox(Level*, BoundingBox*, Random&, float, int, int, int, int, int, int, + const BlockState*, const BlockState*, bool, int maxSkyBrightness); + virtual void maybeGenerateBlock(Level*, BoundingBox*, Random&, float, int, int, int, const BlockState*); + virtual void generateUpperHalfSphere(Level*, BoundingBox*, int, int, int, int, int, int, + const BlockState*, bool); + virtual void generateFullSphere(Level*, BoundingBox*, int, int, int, int, const BlockState*, + const BlockState*, bool); + virtual void generateAirColumnUp(Level*, int, int, int, BoundingBox*); + virtual void generateAirBoxUp(Level*, int, int, int, int, int, BoundingBox*); + virtual void fillColumnDown(Level*, const BlockState*, int, int, int, BoundingBox*); + virtual void fillBoxDown(Level*, const BlockState*, int, int, int, int, int, BoundingBox*); + virtual bool createChest(Level*, BoundingBox*, Random&, int, int, int, ResourceLocation*); + virtual bool createChest(Level*, BoundingBox*, Random&, const BlockPos&, ResourceLocation*, + const BlockState*); + virtual bool createDispenser(Level*, BoundingBox*, Random&, int, int, int, const Direction*, + ResourceLocation*); + virtual void addStructurePieceSaveData(DataOutputStream*, std::vector, std::vector, + std::vector, std::vector); + virtual void readStructurePieceSaveData(DataInputStream*, std::vector&, std::vector&, + std::vector&, std::vector&); + virtual void addBoolSaveData(DataOutputStream*, std::vector); + virtual std::vector readBoolSaveData(DataInputStream*); + virtual void addIntSaveData(DataOutputStream*, std::vector); + virtual std::vector readIntSaveData(DataInputStream*); + virtual void move(int, int, int); + virtual Rotation* getRotation(); + virtual Mirror* getMirror(); + + void write(DataOutputStream*); + void setBoundingBox(BoundingBox*); + const Direction* getOrientation(); + void setOrientation(const Direction*); + int getWorldX(int x, int z); + int getWorldY(int y); + int getWorldZ(int x, int z); + void setGenDepth(int); + void setDirty(); + void clearDirty(); + bool isDirty(); + + BoundingBox* m_boundingBox; + const Direction* m_orientation; + Mirror* m_mirror; + Rotation* m_rotation; + int m_genDepth; + bool m_dirty; +}; + +static_assert(sizeof(StructurePiece) == 0x30, "Switch structure piece layout"); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceCore.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceCore.cpp new file mode 100644 index 00000000..dfb774f2 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceCore.cpp @@ -0,0 +1,145 @@ +#include "net/minecraft/world/level/levelgen/structure/StructurePiece.h" + +#include "com/mojang/nbt/CompoundTag.h" +#include "java/io/DataInputStream.h" +#include "java/io/DataOutputStream.h" +#include "net/minecraft/core/BlockPos.h" +#include "net/minecraft/core/Direction.h" +#include "net/minecraft/world/level/Level.h" +#include "net/minecraft/world/level/block/Mirror.h" +#include "net/minecraft/world/level/block/Rotation.h" +#include "net/minecraft/world/level/levelgen/structure/BoundingBox.h" +#include "net/minecraft/world/level/levelgen/structure/StructureFeatureIO.h" +#include "net/minecraft/world/level/storage/LevelStorage.h" + +StructurePiece::StructurePiece() + : m_boundingBox(nullptr), m_orientation(nullptr), m_mirror(Mirror::NONE), m_rotation(Rotation::NONE), + m_genDepth(0), m_dirty(true) {} + +StructurePiece::StructurePiece(int genDepth) { + m_boundingBox = nullptr; + m_genDepth = genDepth; + m_orientation = nullptr; + m_mirror = Mirror::NONE; + m_rotation = Rotation::NONE; + m_dirty = true; +} + +StructurePiece::~StructurePiece() { + delete m_boundingBox; +} + +void StructurePiece::setBoundingBox(BoundingBox* bounds) { + delete m_boundingBox; + m_boundingBox = bounds; +} + +CompoundTag* StructurePiece::createTag() { + return new CompoundTag(); +} + +void StructurePiece::write(DataOutputStream* output) { + output->writeUTF(StructureFeatureIO::getEncodeId(this)); + m_boundingBox->write(output); + output->writeInt(m_orientation ? m_orientation->get2DDataValue() : -1); + output->writeInt(m_genDepth); + addAdditionalSaveData(output); +} + +void StructurePiece::load(Level* level, DataInputStream* input) { + delete m_boundingBox; + m_boundingBox = new BoundingBox(); + m_boundingBox->read(input); + int orientation = input->readInt(); + setOrientation(orientation == -1 ? nullptr : Direction::from2DDataValue(orientation)); + m_genDepth = input->readInt(); + readAdditionalSaveData(input, level->getLevelStorage()->getStructureManager()); +} + +void StructurePiece::addChildren(StructurePiece*, std::vector*, Random&) {} + +BlockPos* StructurePiece::getLocatorPosition() { + return new BlockPos(static_cast(m_boundingBox->getCenter())); +} + +const Direction* StructurePiece::getOrientation() { + return m_orientation; +} + +void StructurePiece::setOrientation(const Direction* orientation) { + m_orientation = orientation; + if (orientation != nullptr) { + if (orientation == Direction::SOUTH) { + m_mirror = Mirror::LEFT_RIGHT; + m_rotation = Rotation::NONE; + } else if (orientation == Direction::WEST) { + m_mirror = Mirror::LEFT_RIGHT; + m_rotation = Rotation::CLOCKWISE_90; + } else if (orientation == Direction::EAST) { + m_mirror = Mirror::NONE; + m_rotation = Rotation::CLOCKWISE_90; + } else { + m_mirror = Mirror::NONE; + m_rotation = Rotation::NONE; + } + } else { + m_rotation = Rotation::NONE; + m_mirror = Mirror::NONE; + } +} + +int StructurePiece::getWorldX(int x, int z) { + const Direction* orientation = getOrientation(); + if (orientation) { + switch (orientation->get3DDataValue()) { + case 2: + case 3: + return m_boundingBox->m_x0 + x; + case 4: + return m_boundingBox->m_x1 - z; + case 5: + return m_boundingBox->m_x0 + z; + } + } + return x; +} + +int StructurePiece::getWorldY(int y) { + return getOrientation() ? m_boundingBox->m_y0 + y : y; +} + +int StructurePiece::getWorldZ(int x, int z) { + const Direction* orientation = getOrientation(); + if (orientation) { + switch (orientation->get3DDataValue()) { + case 2: + return m_boundingBox->m_z1 - z; + case 3: + return m_boundingBox->m_z0 + z; + case 4: + case 5: + return m_boundingBox->m_z0 + x; + } + } + return z; +} + +void StructurePiece::setGenDepth(int depth) { + m_genDepth = depth; +} + +void StructurePiece::setDirty() { + m_dirty = true; +} + +void StructurePiece::move(int x, int y, int z) { + m_boundingBox->move(x, y, z); +} + +Rotation* StructurePiece::getRotation() { + return m_rotation; +} + +Mirror* StructurePiece::getMirror() { + return m_mirror; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceData.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceData.cpp new file mode 100644 index 00000000..dde5eade --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceData.cpp @@ -0,0 +1,67 @@ +#include "net/minecraft/world/level/levelgen/structure/StructurePiece.h" + +#include "java/io/DataInputStream.h" +#include "java/io/DataOutputStream.h" +#include "net/minecraft/util/StringUtils.h" + +void StructurePiece::addStructurePieceSaveData(DataOutputStream* output, std::vector flags0, + std::vector flags1, std::vector values0, + std::vector values1) { + addBoolSaveData(output, flags0); + addBoolSaveData(output, flags1); + addIntSaveData(output, values0); + addIntSaveData(output, values1); +} + +void StructurePiece::readStructurePieceSaveData(DataInputStream* input, std::vector& flags0, + std::vector& flags1, std::vector& values0, + std::vector& values1) { + flags0 = readBoolSaveData(input); + flags1 = readBoolSaveData(input); + values0 = readIntSaveData(input); + values1 = readIntSaveData(input); +} + +void StructurePiece::addBoolSaveData(DataOutputStream* output, std::vector values) { + std::wstring text = L""; + for (std::size_t i = 0; i < values.size(); ++i) { + text += std::to_wstring(values[i]); + if (i < values.size() - 1) + text += L","; + } + output->writeUTF(text); +} + +std::vector StructurePiece::readBoolSaveData(DataInputStream* input) { + std::vector values; + std::wstring text = input->readUTF(); + if (!text.empty()) { + std::vector tokens; + tokens = split(text, L','); + for (std::size_t i = 0; i < tokens.size(); ++i) + values.push_back(_fromString(tokens[i])); + } + return values; +} + +void StructurePiece::addIntSaveData(DataOutputStream* output, std::vector values) { + std::wstring text = L""; + for (std::size_t i = 0; i < values.size(); ++i) { + text += std::to_wstring(values[i]); + if (i < values.size() - 1) + text += L","; + } + output->writeUTF(text); +} + +std::vector StructurePiece::readIntSaveData(DataInputStream* input) { + std::vector values; + std::wstring text = input->readUTF(); + if (!text.empty()) { + std::vector tokens; + tokens = split(text, L','); + for (std::size_t i = 0; i < tokens.size(); ++i) + values.push_back(_fromString(tokens[i])); + } + return values; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePiecePlacement.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePiecePlacement.cpp new file mode 100644 index 00000000..87ecfe0f --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePiecePlacement.cpp @@ -0,0 +1,32 @@ +#include "net/minecraft/world/level/levelgen/structure/StructurePiece.h" + +#include "net/minecraft/core/BlockPos.h" +#include "net/minecraft/world/level/Level.h" +#include "net/minecraft/world/level/block/Block.h" +#include "net/minecraft/world/level/block/Blocks.h" +#include "net/minecraft/world/level/block/Mirror.h" +#include "net/minecraft/world/level/block/Rotation.h" +#include "net/minecraft/world/level/block/state/BlockState.h" +#include "net/minecraft/world/level/levelgen/structure/BoundingBox.h" + +void StructurePiece::placeBlock(Level* level, const BlockState* state, int x, int y, int z, + BoundingBox* bounds) { + BlockPos pos(getWorldX(x, z), getWorldY(y), getWorldZ(x, z)); + if (bounds->isInside(pos) && pos.getY() != 0) { + if (m_mirror != Mirror::NONE) + state = state->getBlock()->mirror(state, m_mirror); + if (m_rotation != Rotation::NONE) + state = state->getBlock()->rotate(state, m_rotation); + level->setBlock(pos, state, 18, false); + } +} + +const BlockState* StructurePiece::getBlock(Level* level, int x, int y, int z, BoundingBox* bounds) { + BlockPos pos(getWorldX(x, z), getWorldY(y), getWorldZ(x, z)); + return bounds->isInside(pos) ? level->getBlockState(pos) : Blocks::AIR->defaultBlockState(); +} + +int StructurePiece::getSkyBrightness(Level* level, int x, int y, int z, BoundingBox* bounds) { + BlockPos pos(getWorldX(x, z), getWorldY(y + 1), getWorldZ(x, z)); + return bounds->isInside(pos) ? level->getBrightness(LightLayer::SKY, pos) : 15; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceState.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceState.cpp new file mode 100644 index 00000000..efa9d822 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceState.cpp @@ -0,0 +1,13 @@ +#include "net/minecraft/world/level/levelgen/structure/StructurePiece.h" + +BoundingBox* StructurePiece::getBoundingBox() { + return m_boundingBox; +} + +void StructurePiece::clearDirty() { + m_dirty = false; +} + +bool StructurePiece::isDirty() { + return m_dirty; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceVolumes.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceVolumes.cpp new file mode 100644 index 00000000..fd286e88 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructurePieceVolumes.cpp @@ -0,0 +1,170 @@ +#include "net/minecraft/world/level/levelgen/structure/StructurePiece.h" + +#include "net/minecraft/core/BlockPos.h" +#include "net/minecraft/world/Random.h" +#include "net/minecraft/world/level/Level.h" +#include "net/minecraft/world/level/block/Block.h" +#include "net/minecraft/world/level/block/Blocks.h" +#include "net/minecraft/world/level/block/state/BlockState.h" +#include "net/minecraft/world/level/levelgen/structure/BoundingBox.h" +#include "net/minecraft/world/level/material/Material.h" +#include +#include + +const BlockState* StructurePiece::BlockSelector::getNext() { + return m_next; +} + +void StructurePiece::generateAirBox(Level* level, BoundingBox* bounds, int x0, int y0, int z0, int x1, int y1, + int z1) { + for (int y = y0; y <= y1; ++y) + for (int x = x0; x <= x1; ++x) + for (int z = z0; z <= z1; ++z) + placeBlock(level, Blocks::AIR->defaultBlockState(), x, y, z, bounds); +} + +void StructurePiece::generateBox(Level* level, BoundingBox* bounds, int x0, int y0, int z0, int x1, int y1, + int z1, const BlockState* boundary, const BlockState* inside, bool skipAir) { + for (int y = y0; y <= y1; ++y) + for (int x = x0; x <= x1; ++x) + for (int z = z0; z <= z1; ++z) { + if (skipAir && getBlock(level, x, y, z, bounds)->getBlock()->getMaterial() == Material::AIR) + continue; + if (y == y0 || y == y1 || x == x0 || x == x1 || z == z0 || z == z1) + placeBlock(level, boundary, x, y, z, bounds); + else + placeBlock(level, inside, x, y, z, bounds); + } +} + +void StructurePiece::generateBox(Level* level, BoundingBox* bounds, BoundingBox* box, + const BlockState* boundary, const BlockState* inside, bool skipAir) { + generateBox(level, bounds, box->m_x0, box->m_y0, box->m_z0, box->m_x1, box->m_y1, box->m_z1, boundary, + inside, skipAir); +} + +void StructurePiece::generateBox(Level* level, BoundingBox* bounds, int x0, int y0, int z0, int x1, int y1, + int z1, bool skipAir, Random& random, BlockSelector* selector) { + for (int y = y0; y <= y1; ++y) + for (int x = x0; x <= x1; ++x) + for (int z = z0; z <= z1; ++z) { + if (skipAir && getBlock(level, x, y, z, bounds)->getBlock()->getMaterial() == Material::AIR) + continue; + selector->next(random, x, y, z, + y == y0 || y == y1 || x == x0 || x == x1 || z == z0 || z == z1); + placeBlock(level, selector->getNext(), x, y, z, bounds); + } +} + +void StructurePiece::generateBox(Level* level, BoundingBox* bounds, BoundingBox* box, bool skipAir, + Random& random, BlockSelector* selector) { + generateBox(level, bounds, box->m_x0, box->m_y0, box->m_z0, box->m_x1, box->m_y1, box->m_z1, skipAir, + random, selector); +} + +void StructurePiece::generateMaybeBox(Level* level, BoundingBox* bounds, Random& random, float chance, int x0, + int y0, int z0, int x1, int y1, int z1, const BlockState* boundary, + const BlockState* inside, bool skipAir, int maxSkyBrightness) { + for (int y = y0; y <= y1; ++y) + for (int x = x0; x <= x1; ++x) + for (int z = z0; z <= z1; ++z) { + if (random.nextFloat() > chance) + continue; + if (skipAir && getBlock(level, x, y, z, bounds)->getBlock()->getMaterial() == Material::AIR) + continue; + if (maxSkyBrightness > 0 && getSkyBrightness(level, x, y, z, bounds) >= maxSkyBrightness) + continue; + if (y == y0 || y == y1 || x == x0 || x == x1 || z == z0 || z == z1) + placeBlock(level, boundary, x, y, z, bounds); + else + placeBlock(level, inside, x, y, z, bounds); + } +} + +void StructurePiece::maybeGenerateBlock(Level* level, BoundingBox* bounds, Random& random, float chance, + int x, int y, int z, const BlockState* state) { + if (random.nextFloat() < chance) + placeBlock(level, state, x, y, z, bounds); +} + +void StructurePiece::generateUpperHalfSphere(Level* level, BoundingBox* bounds, int x0, int y0, int z0, + int x1, int y1, int z1, const BlockState* state, bool skipAir) { + float width = x1 - x0 + 1; + float height = y1 - y0 + 1; + float depth = z1 - z0 + 1; + float centerX = x0 + width / 2.0f; + float centerZ = z0 + depth / 2.0f; + for (int y = y0; y <= y1; ++y) { + float dy = (y - y0) / height; + for (int x = x0; x <= x1; ++x) { + float dx = (x - centerX) / (width / 2.0f); + for (int z = z0; z <= z1; ++z) { + if (skipAir && getBlock(level, x, y, z, bounds)->getBlock()->getMaterial() == Material::AIR) + continue; + float dz = (z - centerZ) / (depth / 2.0f); + if (dx * dx + dy * dy + dz * dz <= 1.05f) + placeBlock(level, state, x, y, z, bounds); + } + } + } +} + +void StructurePiece::generateFullSphere(Level* level, BoundingBox* bounds, int centerX, int centerY, + int centerZ, int radius, const BlockState* boundary, + const BlockState* inside, bool skipNull) { + for (int y = centerY - radius; y <= centerY + radius; ++y) + for (int x = centerX - radius; x <= centerX + radius; ++x) + for (int z = centerZ - radius; z <= centerZ + radius; ++z) { + // This Switch helper tests for a null state, unlike the air-material filters above. + if (skipNull && getBlock(level, x, y, z, bounds) == nullptr) + continue; + float dx = std::abs(x - centerX) + 0.5f; + float dy = std::abs(y - centerY) + 0.5f; + float dz = std::abs(z - centerZ) + 0.5f; + float distance = std::sqrt(dx * dx + dy * dy + dz * dz); + if (std::fabs(distance - radius) <= 0.5f) + placeBlock(level, boundary, x, y, z, bounds); + if (radius - distance > 0.5f) + placeBlock(level, inside, x, y, z, bounds); + } +} + +void StructurePiece::generateAirColumnUp(Level* level, int x, int y, int z, BoundingBox* bounds) { + BlockPos pos(getWorldX(x, z), getWorldY(y), getWorldZ(x, z)); + if (bounds->isInside(pos)) { + while (!level->isEmptyBlock(pos) && pos.getY() < 255) { + level->setBlock(pos, Blocks::AIR->defaultBlockState(), 2, false); + pos = pos.above(); + } + } +} + +void StructurePiece::generateAirBoxUp(Level* level, int x0, int z0, int x1, int z1, int y, + BoundingBox* bounds) { + for (int x = x0; x < x1; ++x) + for (int z = z0; z < z1; ++z) + generateAirColumnUp(level, x, y, z, bounds); +} + +void StructurePiece::fillColumnDown(Level* level, const BlockState* state, int x, int y, int z, + BoundingBox* bounds) { + int worldX = getWorldX(x, z); + int worldY = getWorldY(y); + int worldZ = getWorldZ(x, z); + if (bounds->isInside(BlockPos(worldX, worldY, worldZ))) { + while ( + (level->isEmptyBlock(BlockPos(worldX, worldY, worldZ)) + || level->getBlockState(BlockPos(worldX, worldY, worldZ))->getBlock()->getMaterial()->isLiquid()) + && worldY > 1) { + level->setBlock(BlockPos(worldX, worldY, worldZ), state, 2, false); + --worldY; + } + } +} + +void StructurePiece::fillBoxDown(Level* level, const BlockState* state, int x0, int z0, int x1, int z1, int y, + BoundingBox* bounds) { + for (int x = x0; x < x1; ++x) + for (int z = z0; z < z1; ++z) + fillColumnDown(level, state, x, y, z, bounds); +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureStart.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureStart.cpp new file mode 100644 index 00000000..e2a6e199 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureStart.cpp @@ -0,0 +1,130 @@ +#include "net/minecraft/world/level/levelgen/structure/StructureStart.h" + +#include "java/io/ByteArrayOutputStream.h" +#include "java/io/DataInputStream.h" +#include "java/io/DataOutputStream.h" +#include "net/minecraft/world/Random.h" +#include "net/minecraft/world/level/Level.h" +#include "net/minecraft/world/level/levelgen/structure/BoundingBox.h" +#include "net/minecraft/world/level/levelgen/structure/StructureFeatureIO.h" +#include "net/minecraft/world/level/levelgen/structure/StructurePiece.h" + +StructureStart::StructureStart() : m_boundingBox(nullptr), m_chunkX(0), m_chunkZ(0), m_dirty(true) {} + +StructureStart::StructureStart(int chunkX, int chunkZ) : m_chunkX(chunkX), m_chunkZ(chunkZ) { + m_boundingBox = nullptr; + m_dirty = true; +} + +StructureStart::~StructureStart() { + for (auto it = m_pieces.begin(); it != m_pieces.end(); ++it) + delete *it; + delete m_boundingBox; +} + +void StructureStart::postProcess(Level* level, Random& random, BoundingBox* bounds) { + auto it = m_pieces.begin(); + while (it != m_pieces.end()) { + StructurePiece* piece = *it; + if (piece->getBoundingBox()->intersects(bounds) && !piece->postProcess(level, random, bounds)) { + // The original removes the pointer without deleting the rejected piece. + it = m_pieces.erase(it); + } else { + if (piece->isDirty()) { + setDirty(); + piece->clearDirty(); + } + ++it; + } + } +} + +void StructureStart::calculateBoundingBox() { + m_boundingBox = BoundingBox::getUnknownBox(); + for (auto it = m_pieces.begin(); it != m_pieces.end(); ++it) + m_boundingBox->expand((*it)->getBoundingBox()); +} + +arrayWithLength StructureStart::createTag(int chunkX, int chunkZ) { + ByteArrayOutputStream bytes; + DataOutputStream output(&bytes); + output.writeInt(3); + output.writeUTF(StructureFeatureIO::getEncodeId(this)); + output.writeInt(chunkX); + output.writeInt(chunkZ); + m_boundingBox->write(&output); + output.writeInt(m_pieces.size()); + for (auto it = m_pieces.begin(); it != m_pieces.end(); ++it) + (*it)->write(&output); + addAdditionalSaveData(&output); + return bytes.toByteArray(); +} + +void StructureStart::addAdditionalSaveData(DataOutputStream*) {} + +void StructureStart::load(Level* level, DataInputStream* input) { + m_chunkX = input->readInt(); + m_chunkZ = input->readInt(); + m_boundingBox = new BoundingBox(); + m_boundingBox->read(input); + int count = input->readInt(); + for (int i = 0; i < count; ++i) { + StructurePiece* piece = StructureFeatureIO::loadStaticPiece(input, level); + if (piece) + m_pieces.push_back(piece); + } + readAdditionalSaveData(input); +} + +void StructureStart::readAdditionalSaveData(DataInputStream*) {} + +void StructureStart::moveBelowSeaLevel(Level* level, Random& random, int padding) { + int limit = level->getSeaLevel() - padding; + int target = m_boundingBox->getYSpan() + 1; + if (target < limit) + target += random.nextInt(limit - target); + int delta = target - m_boundingBox->m_y1; + m_boundingBox->move(0, delta, 0); + for (auto it = m_pieces.begin(); it != m_pieces.end(); ++it) + (*it)->move(0, delta, 0); +} + +void StructureStart::moveInsideHeights(Level*, Random& random, int minY, int maxY) { + int range = maxY - minY + 1 - m_boundingBox->getYSpan(); + int target = minY; + if (range > 1) + target += random.nextInt(range); + int delta = target - m_boundingBox->m_y0; + m_boundingBox->move(0, delta, 0); + for (auto it = m_pieces.begin(); it != m_pieces.end(); ++it) + (*it)->move(0, delta, 0); +} + +bool StructureStart::isValid() { + return true; +} +bool StructureStart::isValidForPostProcess(ChunkPos*) { + return true; +} +void StructureStart::notifyPostProcessAt(ChunkPos*) {} +std::vector* StructureStart::getPieces() { + return &m_pieces; +} +BoundingBox* StructureStart::getBoundingBox() { + return m_boundingBox; +} +int StructureStart::getChunkX() { + return m_chunkX; +} +int StructureStart::getChunkZ() { + return m_chunkZ; +} +void StructureStart::setDirty() { + m_dirty = true; +} +void StructureStart::clearDirty() { + m_dirty = false; +} +bool StructureStart::isDirty() { + return m_dirty; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureStart.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureStart.h new file mode 100644 index 00000000..ab68cdd3 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/StructureStart.h @@ -0,0 +1,47 @@ +#pragma once + +#include "net/minecraft/world/ArrayWithLength.h" +#include + +class BoundingBox; +class ChunkPos; +class DataInputStream; +class DataOutputStream; +class Level; +class Random; +class StructurePiece; + +class StructureStart { +public: + StructureStart(); + StructureStart(int chunkX, int chunkZ); + virtual ~StructureStart(); + virtual void postProcess(Level*, Random&, BoundingBox*); + virtual arrayWithLength createTag(int chunkX, int chunkZ); + virtual void addAdditionalSaveData(DataOutputStream*); + virtual void load(Level*, DataInputStream*); + virtual void readAdditionalSaveData(DataInputStream*); + virtual bool isValid(); + virtual bool isValidForPostProcess(ChunkPos*); + virtual void notifyPostProcessAt(ChunkPos*); + virtual int GetType() = 0; + + std::vector* getPieces(); + BoundingBox* getBoundingBox(); + int getChunkX(); + int getChunkZ(); + void setDirty(); + void clearDirty(); + bool isDirty(); + void calculateBoundingBox(); + void moveBelowSeaLevel(Level*, Random&, int padding); + void moveInsideHeights(Level*, Random&, int minY, int maxY); + + std::vector m_pieces; + BoundingBox* m_boundingBox; + int m_chunkX; + int m_chunkZ; + bool m_dirty; +}; + +static_assert(sizeof(StructureStart) == 0x38, "Switch structure start layout"); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.cpp new file mode 100644 index 00000000..74d860a3 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.cpp @@ -0,0 +1,10 @@ +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h" + +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.h" + +void StructureManager::staticCtor() {} +StructureManager::StructureManager(DataFixerUpper* fixer) : m_fixerUpper(fixer) {} +StructureManager::~StructureManager() { + for (const auto& entry : m_templates) + delete entry.second; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h index 9b091180..d6362d70 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h @@ -1,6 +1,28 @@ #pragma once +#include +#include + +class DataFixerUpper; +class InputStream; +class StructureTemplate; + class StructureManager { public: + StructureManager(DataFixerUpper*); + virtual ~StructureManager(); static void staticCtor(); + StructureTemplate* getOrCreate(int); + StructureTemplate* get(int); + bool loadArchive(int); + std::wstring getArchivePath(int); + void loadFromStream(int, InputStream*); + + std::unordered_map m_templates; + DataFixerUpper* m_fixerUpper; + static constexpr int RESOURCE_COUNT = 114; + +private: + static const wchar_t* const s_resourceNames[RESOURCE_COUNT]; }; +static_assert(sizeof(StructureManager) == 0x38, "Original structure manager allocation"); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerArchive.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerArchive.cpp new file mode 100644 index 00000000..93975087 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerArchive.cpp @@ -0,0 +1,18 @@ +#include "java/io/ByteArrayInputStream.h" +#include "net/minecraft/client/CMinecraftApp.h" +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h" + +bool StructureManager::loadArchive(int id) { + const auto path = getArchivePath(id); + if (!CConsoleMinecraftApp::sInstance.hasArchiveFile(path, false)) + return false; + const auto data = CConsoleMinecraftApp::sInstance.getArchiveFile(path, false); + if (!data.m_length || !data.m_data) { + return false; + } + ByteArrayInputStream input(data); + loadFromStream(id, &input); + input.reset(); + delete[] data.m_data; + return true; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerLookup.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerLookup.cpp new file mode 100644 index 00000000..d439d237 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerLookup.cpp @@ -0,0 +1,19 @@ +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h" +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.h" + +StructureTemplate* StructureManager::getOrCreate(int id) { + auto* result = get(id); + if (!result) { + result = new StructureTemplate; + m_templates[id] = result; + } + return result; +} +StructureTemplate* StructureManager::get(int id) { + if (m_templates.find(id) == m_templates.end()) { + loadArchive(id); + if (m_templates.find(id) == m_templates.end()) + return new StructureTemplate; // Original failure fallback is not cached. + } + return m_templates.find(id)->second; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerNbt.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerNbt.cpp new file mode 100644 index 00000000..0536bbb9 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerNbt.cpp @@ -0,0 +1,17 @@ +#include "com/mojang/nbt/CompoundTag.h" +#include "com/mojang/nbt/NbtIo.h" +#include "net/minecraft/util/datafix/DataFixerUpper.h" +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h" +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.h" + +void StructureManager::loadFromStream(int id, InputStream* input) { + CompoundTag* tag = NbtIo::readCompressed(input); + if (!tag->contains(DataFixerUpper::DATA_VERSION_KEY, 99)) + tag->putInt(DataFixerUpper::DATA_VERSION_KEY, 500); + StructureTemplate* structure = new StructureTemplate(); + CompoundTag* updated = m_fixerUpper->updateData(DataFixTypes::STRUCTURE, tag); + structure->loadTag(updated); + delete tag; + int key = id; + m_templates[key] = structure; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerPaths.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerPaths.cpp new file mode 100644 index 00000000..8e245ac1 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureManagerPaths.cpp @@ -0,0 +1,11 @@ +#include "net/minecraft/util/StringUtils.h" +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureManager.h" +#include +const wchar_t* const StructureManager::s_resourceNames[RESOURCE_COUNT] = { +#include "StructureNames.inc" + +}; +std::wstring StructureManager::getArchivePath(int id) { + const std::wstring name(s_resourceNames[id]); + return std::move(replaceAll(name, L"/", L"\\").insert(0, L"Structures\\")); +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureNames.inc b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureNames.inc new file mode 100644 index 00000000..1f8c28a0 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureNames.inc @@ -0,0 +1,115 @@ +// Original resource identifiers in index order. + L"igloo/igloo_top", + L"igloo/igloo_middle", + L"igloo/igloo_bottom", + L"fossils/fossil_spine_01", + L"fossils/fossil_spine_02", + L"fossils/fossil_spine_03", + L"fossils/fossil_spine_04", + L"fossils/fossil_spine_01_coal", + L"fossils/fossil_spine_02_coal", + L"fossils/fossil_spine_03_coal", + L"fossils/fossil_spine_04_coal", + L"fossils/fossil_skull_01", + L"fossils/fossil_skull_02", + L"fossils/fossil_skull_03", + L"fossils/fossil_skull_04", + L"fossils/fossil_skull_01_coal", + L"fossils/fossil_skull_02_coal", + L"fossils/fossil_skull_03_coal", + L"fossils/fossil_skull_04_coal", + L"endcity/base_floor", + L"endcity/base_roof", + L"endcity/bridge_end", + L"endcity/bridge_gentle_stairs", + L"endcity/bridge_piece", + L"endcity/bridge_steep_stairs", + L"endcity/fat_tower_base", + L"endcity/fat_tower_middle", + L"endcity/fat_tower_top", + L"endcity/second_floor", + L"endcity/second_floor_2", + L"endcity/second_roof", + L"endcity/ship", + L"endcity/third_floor", + L"endcity/third_floor_b", + L"endcity/third_floor_c", + L"endcity/third_roof", + L"endcity/tower_base", + L"endcity/tower_floor", + L"endcity/tower_piece", + L"endcity/tower_top", + L"mansion/carpet_south", + L"mansion/carpet_south_2", + L"mansion/carpet_west", + L"mansion/carpet_west_2", + L"mansion/carpet_north", + L"mansion/carpet_east", + L"mansion/corridor_floor", + L"mansion/corridor_floor_2", + L"mansion/indoors_wall", + L"mansion/indoors_wall_2", + L"mansion/indoors_door", + L"mansion/indoors_door_2", + L"mansion/roof", + L"mansion/roof_front", + L"mansion/small_wall", + L"mansion/small_wall_corner", + L"mansion/roof_corner", + L"mansion/roof_inner_corner", + L"mansion/entrance", + L"mansion/wall_corner", + L"mansion/wall_flat", + L"mansion/wall_window", + L"mansion/1x1_a1", + L"mansion/1x1_a2", + L"mansion/1x1_a3", + L"mansion/1x1_a4", + L"mansion/1x1_a5", + L"mansion/1x1_as1", + L"mansion/1x1_as2", + L"mansion/1x1_as3", + L"mansion/1x1_as4", + L"mansion/1x1_b1", + L"mansion/1x1_b2", + L"mansion/1x1_b3", + L"mansion/1x1_b4", + L"mansion/1x1_b5", + L"mansion/1x2_a1", + L"mansion/1x2_a2", + L"mansion/1x2_a3", + L"mansion/1x2_a4", + L"mansion/1x2_a5", + L"mansion/1x2_a6", + L"mansion/1x2_a7", + L"mansion/1x2_a8", + L"mansion/1x2_a9", + L"mansion/1x2_b1", + L"mansion/1x2_b2", + L"mansion/1x2_b3", + L"mansion/1x2_b4", + L"mansion/1x2_b5", + L"mansion/1x2_c_stairs", + L"mansion/1x2_c1", + L"mansion/1x2_c2", + L"mansion/1x2_c3", + L"mansion/1x2_c4", + L"mansion/1x2_d_stairs", + L"mansion/1x2_d1", + L"mansion/1x2_d2", + L"mansion/1x2_d3", + L"mansion/1x2_d4", + L"mansion/1x2_d5", + L"mansion/1x2_s1", + L"mansion/1x2_s2", + L"mansion/1x2_se1", + L"mansion/2x2_a1", + L"mansion/2x2_a2", + L"mansion/2x2_a3", + L"mansion/2x2_a4", + L"mansion/2x2_b1", + L"mansion/2x2_b2", + L"mansion/2x2_b3", + L"mansion/2x2_b4", + L"mansion/2x2_b5", + L"mansion/2x2_s1", diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.cpp new file mode 100644 index 00000000..e20fcb1f --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.cpp @@ -0,0 +1,46 @@ +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.h" + +#include "com/mojang/nbt/CompoundTag.h" +#include "net/minecraft/world/level/block/Rotation.h" +#include "net/minecraft/world/phys/Vec3.h" + +StructureTemplate::StructureTemplate() { + m_size = BlockPos::zero; + m_author.assign(L"?"); +} + +StructureTemplate::~StructureTemplate() { + for (auto* block : m_blocks) + delete block; + for (auto* entity : m_entities) + delete entity; +} + +StructureTemplate::BlockInfo::BlockInfo(const BlockPos& pos, const BlockState* state, CompoundTag* tag) { + m_pos = pos; + m_state = state; + m_tag = tag; +} +StructureTemplate::BlockInfo::~BlockInfo() { + delete m_tag; +} + +StructureTemplate::EntityInfo::EntityInfo(Vec3* pos, const BlockPos& blockPos, CompoundTag* tag) { + m_pos = pos; + m_blockPos = blockPos; + m_tag = tag; +} +StructureTemplate::EntityInfo::~EntityInfo() { + delete m_pos; + delete m_tag; +} + +BlockPos StructureTemplate::getSize() { + return m_size; +} +BlockPos StructureTemplate::getSize(Rotation* rotation) { + const auto type = rotation->getType(); + if ((type | 2) == 3) + return BlockPos(m_size.getZ(), m_size.getY(), m_size.getX()); + return m_size; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.h new file mode 100644 index 00000000..656051ec --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.h @@ -0,0 +1,44 @@ +#pragma once + +#include "net/minecraft/core/BlockPos.h" +#include +#include + +class BlockState; +class CompoundTag; +class Rotation; +class Vec3; + +class StructureTemplate { +public: + struct BlockInfo { + BlockInfo(const BlockPos&, const BlockState*, CompoundTag*); + ~BlockInfo(); + BlockPos m_pos; + const BlockState* m_state; // Borrowed from the block-state registry. + CompoundTag* m_tag; + }; + struct EntityInfo { + EntityInfo(Vec3*, const BlockPos&, CompoundTag*); + ~EntityInfo(); + Vec3* m_pos; + BlockPos m_blockPos; + CompoundTag* m_tag; + }; + + StructureTemplate(); + virtual ~StructureTemplate(); + BlockPos getSize(); + BlockPos getSize(Rotation*); + void loadTag(CompoundTag*); + + std::vector m_palette; + std::vector m_blocks; + std::vector m_entities; + BlockPos m_size; + std::wstring m_author; +}; + +static_assert(sizeof(StructureTemplate) == 0x78, "Original template allocation"); +static_assert(sizeof(StructureTemplate::BlockInfo) == 0x20, "Original block record"); +static_assert(sizeof(StructureTemplate::EntityInfo) == 0x20, "Original entity record"); diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateNbt.cpp b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateNbt.cpp new file mode 100644 index 00000000..3665fa84 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateNbt.cpp @@ -0,0 +1,66 @@ +#include "com/mojang/nbt/CompoundTag.h" +#include "com/mojang/nbt/ListTag.h" +#include "com/mojang/nbt/NbtUtils.h" +#include "net/minecraft/world/level/block/Blocks.h" +#include "net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.h" +#include "net/minecraft/world/phys/Vec3.h" + +void StructureTemplate::loadTag(CompoundTag* tag) { + for (auto* block : m_blocks) + delete block; + for (auto* entity : m_entities) + delete entity; + m_blocks.clear(); + m_entities.clear(); + m_palette.clear(); + + ListTag* size = tag->getList(L"size", Tag::TAG_Int); + int x = size->getInt(0); + int y = size->getInt(1); + int z = size->getInt(2); + m_size = BlockPos(x, y, z); + m_author = tag->getString(L"author"); + + ListTag* palette = tag->getList(L"palette", Tag::TAG_Compound); + for (int i = 0; i < static_cast(palette->size()); ++i) { + const BlockState* state = NbtUtils::readBlockState(palette->getCompound(i)); + m_palette.push_back(state); + } + + ListTag* blocks = tag->getList(L"blocks", Tag::TAG_Compound); + for (int i = 0; i < static_cast(blocks->size()); ++i) { + CompoundTag* block = blocks->getCompound(i); + ListTag* pos = block->getList(L"pos", Tag::TAG_Int); + x = pos->getInt(0); + y = pos->getInt(1); + z = pos->getInt(2); + BlockPos blockPos(x, y, z); + int index = block->getInt(L"state"); + const BlockState* state = static_cast(index) < m_palette.size() ? + m_palette[index] : + Blocks::AIR->defaultBlockState(); + CompoundTag* nbt = block->contains(L"nbt") ? block->getCompound(L"nbt")->copy() : nullptr; + BlockInfo* info = new BlockInfo(blockPos, state, nbt); + m_blocks.push_back(info); + } + + ListTag* entities = tag->getList(L"entities", Tag::TAG_Compound); + for (int i = 0; i < static_cast(entities->size()); ++i) { + CompoundTag* entity = entities->getCompound(i); + ListTag* pos = entity->getList(L"pos", Tag::TAG_Double); + double px = pos->getDouble(0); + double py = pos->getDouble(1); + double pz = pos->getDouble(2); + Vec3* entityPos = Vec3::newPermanent(px, py, pz); + ListTag* blockPosTag = entity->getList(L"blockPos", Tag::TAG_Int); + x = blockPosTag->getInt(0); + y = blockPosTag->getInt(1); + z = blockPosTag->getInt(2); + BlockPos blockPos(x, y, z); + if (entity->contains(L"nbt")) { + CompoundTag* nbt = entity->getCompound(L"nbt")->copy(); + EntityInfo* info = new EntityInfo(entityPos, blockPos, nbt); + m_entities.push_back(info); + } + } +} diff --git a/src/Minecraft.World/net/minecraft/world/level/levelgen/synth/PerlinSimplexNoise.h b/src/Minecraft.World/net/minecraft/world/level/levelgen/synth/PerlinSimplexNoise.h index 4813debe..62d04637 100644 --- a/src/Minecraft.World/net/minecraft/world/level/levelgen/synth/PerlinSimplexNoise.h +++ b/src/Minecraft.World/net/minecraft/world/level/levelgen/synth/PerlinSimplexNoise.h @@ -3,7 +3,7 @@ #include "net/minecraft/world/ArrayWithLength.h" #include "net/minecraft/world/level/levelgen/synth/Synth.h" -class ImprovedNoise; +class SimplexNoise; class Random; class PerlinSimplexNoise : public Synth { @@ -14,7 +14,9 @@ class PerlinSimplexNoise : public Synth { void init(Random*, int); arrayWithLength getRegion(arrayWithLength, double, double, int, int, double, double, double); + arrayWithLength getRegion(arrayWithLength, double, double, int, int, double, double, + double, double); - ImprovedNoise** m_noiseLevels; + SimplexNoise** m_noiseLevels; int m_maxOctaves; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/newbiome/layer/BiomeInitLayer.cpp b/src/Minecraft.World/net/minecraft/world/level/newbiome/layer/BiomeInitLayer.cpp index 6ac19ccd..415211b1 100644 --- a/src/Minecraft.World/net/minecraft/world/level/newbiome/layer/BiomeInitLayer.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/newbiome/layer/BiomeInitLayer.cpp @@ -12,41 +12,41 @@ BiomeInitLayer::BiomeInitLayer(long long seed, std::shared_ptr parent, Le m_parent = parent; if (levelType == LevelType::NORMAL_1_1) { m_warmBiomes = {6, true}; - m_warmBiomes[0] = Biome::DESERT; - m_warmBiomes[1] = Biome::FOREST; - m_warmBiomes[2] = Biome::EXTREME_HILLS; - m_warmBiomes[3] = Biome::SWAMP; - m_warmBiomes[4] = Biome::PLAINS; - m_warmBiomes[5] = Biome::TAIGA; + m_warmBiomes.get(0) = Biome::DESERT; + m_warmBiomes.get(1) = Biome::FOREST; + m_warmBiomes.get(2) = Biome::EXTREME_HILLS; + m_warmBiomes.get(3) = Biome::SWAMP; + m_warmBiomes.get(4) = Biome::PLAINS; + m_warmBiomes.get(5) = Biome::TAIGA; } else { m_warmBiomes = {6, true}; - m_warmBiomes[0] = Biome::DESERT; - m_warmBiomes[1] = Biome::DESERT; - m_warmBiomes[2] = Biome::DESERT; - m_warmBiomes[3] = Biome::SAVANNA; - m_warmBiomes[4] = Biome::SAVANNA; - m_warmBiomes[5] = Biome::PLAINS; + m_warmBiomes.get(0) = Biome::DESERT; + m_warmBiomes.get(1) = Biome::DESERT; + m_warmBiomes.get(2) = Biome::DESERT; + m_warmBiomes.get(3) = Biome::SAVANNA; + m_warmBiomes.get(4) = Biome::SAVANNA; + m_warmBiomes.get(5) = Biome::PLAINS; } m_mediumBiomes = {6, true}; - m_mediumBiomes[0] = Biome::FOREST; - m_mediumBiomes[1] = Biome::ROOFED_FOREST; - m_mediumBiomes[2] = Biome::EXTREME_HILLS; - m_mediumBiomes[3] = Biome::PLAINS; - m_mediumBiomes[4] = Biome::BIRCH_FOREST; - m_mediumBiomes[5] = Biome::SWAMP; + m_mediumBiomes.get(0) = Biome::FOREST; + m_mediumBiomes.get(1) = Biome::ROOFED_FOREST; + m_mediumBiomes.get(2) = Biome::EXTREME_HILLS; + m_mediumBiomes.get(3) = Biome::PLAINS; + m_mediumBiomes.get(4) = Biome::BIRCH_FOREST; + m_mediumBiomes.get(5) = Biome::SWAMP; m_coldBiomes = {4, true}; - m_coldBiomes[0] = Biome::FOREST; - m_coldBiomes[1] = Biome::EXTREME_HILLS; - m_coldBiomes[2] = Biome::TAIGA; - m_coldBiomes[3] = Biome::PLAINS; + m_coldBiomes.get(0) = Biome::FOREST; + m_coldBiomes.get(1) = Biome::EXTREME_HILLS; + m_coldBiomes.get(2) = Biome::TAIGA; + m_coldBiomes.get(3) = Biome::PLAINS; m_iceBiomes = {4, true}; - m_iceBiomes[0] = Biome::ICE_PLAINS; - m_iceBiomes[1] = Biome::ICE_PLAINS; - m_iceBiomes[2] = Biome::ICE_PLAINS; - m_iceBiomes[3] = Biome::COLD_TAIGA; + m_iceBiomes.get(0) = Biome::ICE_PLAINS; + m_iceBiomes.get(1) = Biome::ICE_PLAINS; + m_iceBiomes.get(2) = Biome::ICE_PLAINS; + m_iceBiomes.get(3) = Biome::COLD_TAIGA; CustomizableSourceSettings* settings = nullptr; if (levelType != LevelType::NORMAL_1_1 && levelType == LevelType::CUSTOMIZED) { @@ -83,22 +83,22 @@ arrayWithLength BiomeInitLayer::getArea(int x, int y, int width, int height area[n + m * width] = Biome::MESA_PLATEAU->m_biomeId; } } else { - area[n + m * width] = m_warmBiomes[nextRandom(m_warmBiomes.m_length)]->m_biomeId; + area[n + m * width] = m_warmBiomes.get(nextRandom(m_warmBiomes.m_length))->m_biomeId; } } else if (o == 2) { if (p > 0) { area[n + m * width] = Biome::JUNGLE->m_biomeId; } else { - area[n + m * width] = m_mediumBiomes[nextRandom(m_mediumBiomes.m_length)]->m_biomeId; + area[n + m * width] = m_mediumBiomes.get(nextRandom(m_mediumBiomes.m_length))->m_biomeId; } } else if (o == 3) { if (p > 0) { area[n + m * width] = Biome::MEGA_TAIGA->m_biomeId; } else { - area[n + m * width] = m_coldBiomes[nextRandom(m_coldBiomes.m_length)]->m_biomeId; + area[n + m * width] = m_coldBiomes.get(nextRandom(m_coldBiomes.m_length))->m_biomeId; } } else if (o == 4) { - area[n + m * width] = m_iceBiomes[nextRandom(m_iceBiomes.m_length)]->m_biomeId; + area[n + m * width] = m_iceBiomes.get(nextRandom(m_iceBiomes.m_length))->m_biomeId; } else { area[n + m * width] = Biome::MUSHROOM_ISLAND->m_biomeId; } diff --git a/src/Minecraft.World/net/minecraft/world/level/newbiome/layer/IntCache.h b/src/Minecraft.World/net/minecraft/world/level/newbiome/layer/IntCache.h index deee731a..b50a8e0e 100644 --- a/src/Minecraft.World/net/minecraft/world/level/newbiome/layer/IntCache.h +++ b/src/Minecraft.World/net/minecraft/world/level/newbiome/layer/IntCache.h @@ -1,6 +1,7 @@ #pragma once #include "net/minecraft/world/ArrayWithLength.h" +#include class IntCache { public: @@ -14,5 +15,19 @@ class IntCache { static void Reset(); - class ThreadStorage {}; + class ThreadStorage { + public: + ThreadStorage(); + ~ThreadStorage(); + + // Arrays remain owned here; returned arrayWithLength values are views. + int m_maxSize; + std::vector> m_freeSmall; + std::vector> m_activeSmall; + std::vector> m_freeLarge; + std::vector> m_activeLarge; + std::vector> m_retiredLarge; + }; + + static unsigned int sThreadStorageIndex; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/saveddata/MapItemSavedData.h b/src/Minecraft.World/net/minecraft/world/level/saveddata/MapItemSavedData.h index ef5deedf..3d19ae92 100644 --- a/src/Minecraft.World/net/minecraft/world/level/saveddata/MapItemSavedData.h +++ b/src/Minecraft.World/net/minecraft/world/level/saveddata/MapItemSavedData.h @@ -37,7 +37,7 @@ class MapItemSavedData : public SavedData { ~MapItemSavedData() override; void load(CompoundTag*) override; - void save(CompoundTag*) override; + CompoundTag* save(CompoundTag*) override; void tickCarriedBy(std::shared_ptr player, not_null_ptr item); void mergeInMapData(std::shared_ptr mapData); diff --git a/src/Minecraft.World/net/minecraft/world/level/saveddata/SavedData.h b/src/Minecraft.World/net/minecraft/world/level/saveddata/SavedData.h index 9315bdc7..981316a2 100644 --- a/src/Minecraft.World/net/minecraft/world/level/saveddata/SavedData.h +++ b/src/Minecraft.World/net/minecraft/world/level/saveddata/SavedData.h @@ -10,7 +10,7 @@ class SavedData : public std::enable_shared_from_this { SavedData(const std::wstring&); virtual ~SavedData(); virtual void load(CompoundTag*) = 0; - virtual void save(CompoundTag*) = 0; + virtual CompoundTag* save(CompoundTag*) = 0; void setDirty(bool); void setDirty(); diff --git a/src/Minecraft.World/net/minecraft/world/level/saveddata/StructureFeatureSavedData.cpp b/src/Minecraft.World/net/minecraft/world/level/saveddata/StructureFeatureSavedData.cpp new file mode 100644 index 00000000..85958bee --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/saveddata/StructureFeatureSavedData.cpp @@ -0,0 +1,38 @@ +#include "net/minecraft/world/level/saveddata/StructureFeatureSavedData.h" + +#include "com/mojang/nbt/CompoundTag.h" + +std::wstring StructureFeatureSavedData::FEATURES_KEY = L"Features"; + +StructureFeatureSavedData::StructureFeatureSavedData(const std::wstring& path) : SavedData(path) { + mTag = new CompoundTag(); +} + +StructureFeatureSavedData::~StructureFeatureSavedData() { + delete mTag; +} + +void StructureFeatureSavedData::load(CompoundTag* root) { + delete mTag; + bool present = root->contains(FEATURES_KEY); + CompoundTag* features = root->getCompound(FEATURES_KEY); + // getCompound creates an owned empty tag when the key is absent. + mTag = present ? features->copy() : features; +} + +CompoundTag* StructureFeatureSavedData::save(CompoundTag* root) { + root->put(FEATURES_KEY, mTag->copy()); + return root; +} + +std::wstring StructureFeatureSavedData::createFeatureTagId(int chunkX, int chunkZ) { + return L"[" + std::to_wstring(chunkX) + L"," + std::to_wstring(chunkZ) + L"]"; +} + +void StructureFeatureSavedData::putFeatureTag(arrayWithLength data, int chunkX, int chunkZ) { + mTag->putByteArray(createFeatureTagId(chunkX, chunkZ), data); +} + +CompoundTag* StructureFeatureSavedData::getFullTag() { + return mTag; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/saveddata/StructureFeatureSavedData.h b/src/Minecraft.World/net/minecraft/world/level/saveddata/StructureFeatureSavedData.h index 97a54822..2c5be39d 100644 --- a/src/Minecraft.World/net/minecraft/world/level/saveddata/StructureFeatureSavedData.h +++ b/src/Minecraft.World/net/minecraft/world/level/saveddata/StructureFeatureSavedData.h @@ -1,5 +1,6 @@ #pragma once +#include "net/minecraft/world/ArrayWithLength.h" #include "net/minecraft/world/level/saveddata/SavedData.h" class CompoundTag; @@ -7,9 +8,18 @@ class CompoundTag; class StructureFeatureSavedData : public SavedData { public: StructureFeatureSavedData(const std::wstring&); + ~StructureFeatureSavedData() override; void load(CompoundTag*) override; - void save(CompoundTag*) override; + CompoundTag* save(CompoundTag*) override; + + static std::wstring createFeatureTagId(int chunkX, int chunkZ); + void putFeatureTag(arrayWithLength, int chunkX, int chunkZ); + CompoundTag* getFullTag(); + + static std::wstring FEATURES_KEY; CompoundTag* mTag; }; + +static_assert(sizeof(StructureFeatureSavedData) == 0x40, "Structure saved-data layout"); diff --git a/src/Minecraft.World/net/minecraft/world/level/storage/LevelData.cpp b/src/Minecraft.World/net/minecraft/world/level/storage/LevelData.cpp index 4ce690d3..a919fd94 100644 --- a/src/Minecraft.World/net/minecraft/world/level/storage/LevelData.cpp +++ b/src/Minecraft.World/net/minecraft/world/level/storage/LevelData.cpp @@ -4,6 +4,7 @@ #include "net/minecraft/core/BlockPos.h" #include "net/minecraft/core/System.h" +#include "net/minecraft/util/datafix/DataFixerUpper.h" #include "net/minecraft/world/Difficulty.h" #include "net/minecraft/world/level/LevelType.h" @@ -68,7 +69,7 @@ CompoundTag* LevelData::createTag(std::vector>*) { } void LevelData::setTagData(CompoundTag* out) { - out->putInt(sLevelDataVersionString, 922); // why is DataVersion it's own static shit wtf + out->putInt(DataFixerUpper::DATA_VERSION_KEY, 922); out->putLong(L"RandomSeed", this->m_seed); out->putString(L"generatorName", this->m_levelType->getGeneratorName()); out->putInt(L"generatorVersion", this->m_levelType->getVersion()); diff --git a/src/Minecraft.World/net/minecraft/world/level/storage/LevelStorage.h b/src/Minecraft.World/net/minecraft/world/level/storage/LevelStorage.h index 043030dd..86ea1e03 100644 --- a/src/Minecraft.World/net/minecraft/world/level/storage/LevelStorage.h +++ b/src/Minecraft.World/net/minecraft/world/level/storage/LevelStorage.h @@ -1,5 +1,7 @@ #pragma once +#include + #include class Dimension; @@ -10,6 +12,7 @@ class ChunkStorage; class PlayerIO; class ConsoleSavePath; class ConsoleSaveFile; +class StructureManager; class LevelStorage { public: @@ -26,7 +29,7 @@ class LevelStorage { virtual void getFolder() = 0; virtual ConsoleSavePath getDataFile(const std::wstring&) = 0; virtual void getLevelId() = 0; - virtual void getStructureManager() = 0; + virtual StructureManager* getStructureManager() = 0; virtual ConsoleSaveFile* getSaveFile(); virtual void flushSaveFile(bool); virtual int getAuxValueForMap(PlayerUID, int, int, int, int); diff --git a/src/Minecraft.World/net/minecraft/world/level/storage/MockedLevelStorage.h b/src/Minecraft.World/net/minecraft/world/level/storage/MockedLevelStorage.h index e37c4d08..4adad1e2 100644 --- a/src/Minecraft.World/net/minecraft/world/level/storage/MockedLevelStorage.h +++ b/src/Minecraft.World/net/minecraft/world/level/storage/MockedLevelStorage.h @@ -15,6 +15,6 @@ class MockedLevelStorage : public LevelStorage { void getFolder() override; ConsoleSavePath getDataFile(const std::wstring&) override; void getLevelId() override; - void getStructureManager() override; + StructureManager* getStructureManager() override; ConsoleSaveFile* getSaveFile() override; }; diff --git a/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightRetirement.cpp b/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightRetirement.cpp new file mode 100644 index 00000000..d991504a --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightRetirement.cpp @@ -0,0 +1,71 @@ +#include "XLockFreeStack.h" +#include "net/minecraft/world/level/storage/light/SparseLightStorage.h" + +// Inferred names for the globals at 0x71017a4410 and 0x71017a4418. +int SparseLightStorage::sRetirementSlot; +XLockFreeStack SparseLightStorage::sRetired[3]; + +void SparseLightStorage::staticCtor() { + sRetired[0].doSomething(); + sRetired[1].doSomething(); + sRetired[2].doSomething(); +} + +void SparseLightStorage::retire(unsigned char* buffer) { + sRetired[sRetirementSlot].Push(buffer); +} + +void SparseLightStorage::tick() { + XLockFreeStack* stack = &sRetired[(sRetirementSlot + 1) % 3]; + unsigned char* buffer; + do { + buffer = stack->Pop(); + freeBuffer(buffer, 0); + } while (buffer); + sRetirementSlot = (sRetirementSlot + 1) % 3; +} + +#include "NX/Platform.h" +#include +#include + +void sparseLightMemSet(void*, int, std::size_t); + +void SparseLightStorage::expandLayers(std::vector& layers) { + for (;;) { + unsigned long long packed = __atomic_load_n(&m_packed, __ATOMIC_SEQ_CST); + unsigned char* old = reinterpret_cast(packed & 0x0000ffffffffffffULL); + unsigned int oldCount = packed >> 48; + unsigned long long newCount = oldCount; + for (auto layer = layers.begin(); layer != layers.end();) { + if (static_cast(old[*layer]) >= 0) { + layers.erase(layer); + } else { + ++layer; + newCount = static_cast(newCount) + 1; + } + } + unsigned char* buffer = allocate(newCount * 128 + 128); + XMemCpy(buffer, old, oldCount * 128 + 128); + int slab = oldCount; + for (auto layer = layers.begin(); layer != layers.end(); ++layer) { + if (static_cast(old[*layer]) < 0) { + sparseLightMemSet( + reinterpret_cast(buffer)[static_cast(slab)] + 128, + old[*layer] == 0x81 ? 255 : 0, 128); + buffer[*layer] = slab; + ++slab; + } + } + unsigned long long replacement + = (reinterpret_cast(buffer) & 0x0000ffffffffffffULL) + | (static_cast(newCount) << 48); + if (__atomic_compare_exchange_n(&m_packed, &packed, replacement, true, __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST)) { + retire(old); + return; + } + // The original frees losing allocations directly, without subtracting accounting. + std::free(buffer); + } +} diff --git a/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightStorage.cpp b/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightStorage.cpp new file mode 100644 index 00000000..55c2e2a1 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightStorage.cpp @@ -0,0 +1,236 @@ +#include "net/minecraft/world/level/storage/light/SparseLightStorage.h" + +#include "NX/Platform.h" +#include "java/io/DataInputStream.h" +#include +#include + +// Inferred name for the original allocation accounting word at 0x71017a44c0. +int gSparseLightAllocatedBytes; + +// Separate original memset trampoline at 0x71006910fc (inferred name). +void sparseLightMemSet(void* buffer, int value, std::size_t bytes) { + std::memset(buffer, value, bytes); +} + +namespace { +const unsigned long long PointerMask = 0x0000ffffffffffffULL; +} + +unsigned char* SparseLightStorage::allocate(unsigned int bytes) { + unsigned char* buffer = static_cast(std::malloc(bytes)); + gSparseLightAllocatedBytes += bytes; + return buffer; +} + +void SparseLightStorage::freeBuffer(unsigned char* buffer, int bytes) { + std::free(buffer); + gSparseLightAllocatedBytes -= bytes; +} + +SparseLightStorage::SparseLightStorage(bool bright) { + unsigned char* buffer = allocate(0x4000); + buffer[127] = bright ? 0x81 : 0x80; + for (int i = 0; i < 127; ++i) + buffer[i] = i; + // Even the bright variant starts its explicit slabs with zero light. + // Original 0x71006910fc is a separate memset trampoline with this ABI. + sparseLightMemSet(buffer + 128, 0, 0x3f80); + __atomic_store_n(&m_packed, (reinterpret_cast(buffer) & PointerMask) | (127ULL << 48), + __ATOMIC_SEQ_CST); +} + +SparseLightStorage::SparseLightStorage(bool bright, bool) { + unsigned char* buffer = allocate(128); + for (int i = 0; i != 128; i += 4) { + unsigned char value = bright ? 0x81 : 0x80; + buffer[i] = value; + buffer[i + 1] = value; + buffer[i + 2] = value; + buffer[i + 3] = value; + } + __atomic_store_n(&m_packed, reinterpret_cast(buffer) & PointerMask, __ATOMIC_SEQ_CST); +} + +int SparseLightStorage::bufferSize(unsigned long long packed) { + return ((packed >> 41) & 0x7fff80) + 128; +} + +SparseLightStorage::SparseLightStorage(const SparseLightStorage& other) { + unsigned long long packed = __atomic_load_n(&other.m_packed, __ATOMIC_SEQ_CST); + unsigned char* source = reinterpret_cast(packed & PointerMask); + unsigned int bytes = bufferSize(packed); + unsigned char* buffer = allocate(bytes); + __atomic_store_n(&m_packed, + (packed & ~PointerMask) | (reinterpret_cast(buffer) & PointerMask), + __ATOMIC_SEQ_CST); + XMemCpy(buffer, source, static_cast(bytes)); +} + +SparseLightStorage::~SparseLightStorage() { + unsigned char* buffer + = reinterpret_cast(__atomic_load_n(&m_packed, __ATOMIC_SEQ_CST) & PointerMask); + int bytes = bufferSize(__atomic_load_n(&m_packed, __ATOMIC_SEQ_CST)); + __atomic_store_n(&m_packed, 0ULL, __ATOMIC_SEQ_CST); + freeBuffer(buffer, bytes); +} + +void SparseLightStorage::getBuffers(unsigned char** indices, unsigned char** data) { + unsigned long long packed = __atomic_load_n(&m_packed, __ATOMIC_SEQ_CST); + *indices = reinterpret_cast(packed & PointerMask); + *data = *indices + 128; +} + +void SparseLightStorage::replace(unsigned long long packed) { + unsigned long long old; + do { + old = __atomic_load_n(&m_packed, __ATOMIC_SEQ_CST); + } while (!__atomic_compare_exchange_n(&m_packed, &old, packed, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); + retire(reinterpret_cast(old & PointerMask)); +} + +void SparseLightStorage::fromNibbles(arrayWithLength source, int offset) { + unsigned char indices[128]; + unsigned int slabs = 0; + for (int y = 0; y != 128; ++y) { + unsigned int zero = 1; + unsigned int full = 1; + for (unsigned int xz = 0; xz != 0x8000; xz += 128) { + unsigned char value = (source[offset + ((xz | y) >> 1)] >> ((y & 1) << 2)) & 15; + zero &= value == 0; + full &= value == 15; + } + unsigned int uniform = zero | full; + indices[y] = uniform ? (zero ? 0x80 : 0x81) : slabs; + slabs += uniform ^ 1; + } + unsigned char* buffer = allocate(slabs * 128 + 128); + unsigned char* slab = buffer + 128; + XMemCpy(buffer, indices, 128); + for (int y = 0; y != 128; ++y) { + if (static_cast(buffer[y]) >= 0) { + unsigned char* input = &source[offset + (y >> 1)]; + int shift = (y & 1) << 2; + for (int i = 0; i != 128; i += 2) { + slab[i] = (input[0] >> shift) & 15; + slab[i] |= (input[0x40] >> shift) << 4; + slab[i + 1] = (input[0x80] >> shift) & 15; + slab[i + 1] |= (input[0xc0] >> shift) << 4; + input += 0x100; + } + slab += 128; + } + } + replace((reinterpret_cast(buffer) & PointerMask) + | (static_cast(slabs) << 48)); +} + +void SparseLightStorage::toNibbles(arrayWithLength output, unsigned int offset) { + sparseLightMemSet(output.m_data + offset, 0, 0x4000); + unsigned char* indices; + unsigned char* data; + getBuffers(&indices, &data); + for (int y = 0; y != 128; ++y) { + unsigned char index = indices[y]; + if (index == 0x80) + continue; + unsigned char* target = output.m_data + (offset + (y >> 1)); + int shift = (y & 1) << 2; + if (index == 0x81) { + unsigned char value = 15 << shift; + for (int i = 0; i != 0x4000; i += 0x100) { + target[i] |= value; + target[i + 0x40] |= value; + target[i + 0x80] |= value; + target[i + 0xc0] |= value; + } + } else { + const unsigned char* slab = data + index * 128; + for (int i = 0; i != 128; ++i) { + target[0] |= (slab[i] & 15) << shift; + target[0x40] |= (slab[i] >> 4) << shift; + target += 0x80; + } + } + } +} + +unsigned char SparseLightStorage::getLight(int x, int y, int z) { + unsigned char* indices; + unsigned char* data; + getBuffers(&indices, &data); + unsigned char index = indices[y]; + if (index == 0x80) + return 0; + if (index == 0x81) + return 15; + int xz = x * 16 + z; + int offset = xz / 2; + return (data[(static_cast(index) << 7) + offset] >> ((xz & 1) << 2)) & 15; +} + +unsigned int SparseLightStorage::compress() { + unsigned long long packed = __atomic_load_n(&m_packed, __ATOMIC_SEQ_CST); + unsigned char* old = reinterpret_cast(packed & PointerMask); + unsigned char indices[128]; + unsigned int changed = 0; + unsigned int slabs = 0; + for (int y = 0; y != 128; ++y) { + unsigned char index = old[y]; + if (static_cast(index) >= -126) { + unsigned int zero = 1; + unsigned int full = 1; + unsigned char* slab = old + 128 + index * 128; + for (int i = 0; i != 128; i += 4) { + zero &= (slab[i] == 0) & (slab[i + 1] == 0) & (slab[i + 2] == 0) & (slab[i + 3] == 0); + full &= ((slab[i] & slab[i + 1]) == 255) & ((slab[i + 2] & slab[i + 3]) == 255); + } + unsigned int uniform = zero | full; + index = uniform ? (zero ? 0x80 : 0x81) : slabs; + slabs += uniform ^ 1; + changed |= uniform; + } + indices[y] = index; + } + if (!changed) + return packed >> 48; + unsigned char* buffer = allocate(slabs * 128 + 128); + unsigned char* target = buffer + 128; + XMemCpy(buffer, indices, 128); + for (int y = 0; y != 128; ++y) { + if (static_cast(buffer[y]) >= 0) { + XMemCpy(target, old + 128 + old[y] * 128, 128); + target += 128; + } + } + unsigned long long replacement = (reinterpret_cast(buffer) & PointerMask) + | (static_cast(slabs) << 48); + bool success = __atomic_compare_exchange_n(&m_packed, &packed, replacement, true, __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + retire(success ? old : buffer); + // The computed count is returned even when another writer wins the exchange. + return slabs; +} + +bool SparseLightStorage::isCompressed() { + return static_cast(__atomic_load_n(&m_packed, __ATOMIC_SEQ_CST) >> 48) < 127; +} + +void SparseLightStorage::write(DataOutputStream* out) { + unsigned long long packed = __atomic_load_n(&m_packed, __ATOMIC_SEQ_CST); + unsigned int slabs = packed >> 48; + out->writeInt(slabs); + unsigned long long current = __atomic_load_n(&m_packed, __ATOMIC_SEQ_CST); + arrayWithLength bytes(reinterpret_cast(current & PointerMask), + static_cast(slabs) * 128 + 128); + out->write(bytes); +} + +void SparseLightStorage::read(DataInputStream* in) { + unsigned long long slabs = static_cast(in->readInt()); + unsigned int bytes = static_cast(slabs) * 128 + 128; + unsigned char* buffer = allocate(bytes); + arrayWithLength data(buffer, bytes); + in->readBytes(data); + replace((reinterpret_cast(buffer) & PointerMask) | (slabs << 48)); +} diff --git a/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightStorage.h b/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightStorage.h index 19c5b031..741e8d3f 100644 --- a/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightStorage.h +++ b/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightStorage.h @@ -1,10 +1,49 @@ #pragma once #include "java/io/DataOutputStream.h" +#include + +class DataInputStream; +template +class XLockFreeStack; class SparseLightStorage { public: + SparseLightStorage(bool bright); + SparseLightStorage(bool bright, bool compact); + SparseLightStorage(const SparseLightStorage&); + ~SparseLightStorage(); + + void fromNibbles(arrayWithLength, int offset); + void toNibbles(arrayWithLength, unsigned int offset); + unsigned char getLight(int x, int y, int z); + void setLight(int x, int y, int z, int value); + void setFullBright(); + int setDataRegion(arrayWithLength, int x0, int y0, int z0, int x1, int y1, int z1, + int offset); + int getDataRegion(arrayWithLength, int x0, int y0, int z0, int x1, int y1, int z1, + int offset); + unsigned int compress(); + bool isCompressed(); void write(DataOutputStream* out); + void read(DataInputStream* in); static void staticCtor(); + static void tick(); + +private: + static unsigned char* allocate(unsigned int); + static void freeBuffer(unsigned char*, int); + int bufferSize(unsigned long long); + void getBuffers(unsigned char** indices, unsigned char** data); + void replace(unsigned long long); + void expandLayers(std::vector&); + void retire(unsigned char*); + static int sRetirementSlot; + static XLockFreeStack sRetired[3]; + + // Low 48 bits: buffer pointer; high 16 bits: number of explicit 128-byte slabs. + unsigned long long m_packed; }; + +static_assert(sizeof(SparseLightStorage) == 8, "SparseLightStorage Switch layout"); diff --git a/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightUpdates.cpp b/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightUpdates.cpp new file mode 100644 index 00000000..db4f0a34 --- /dev/null +++ b/src/Minecraft.World/net/minecraft/world/level/storage/light/SparseLightUpdates.cpp @@ -0,0 +1,99 @@ +#include "net/minecraft/world/level/storage/light/SparseLightStorage.h" + +#include "NX/Platform.h" +#include +#include + +void sparseLightMemSet(void*, int, std::size_t); + +namespace { +const unsigned long long PointerMask = 0x0000ffffffffffffULL; +} + +void SparseLightStorage::setLight(int x, int y, int z, int value) { + unsigned char* indices; + unsigned char* data; + getBuffers(&indices, &data); + signed char index = indices[y]; + if (index < 0) { + if (value == 0 && index == -128) + return; + if (value == 15 && index == -127) + return; + { + std::vector layers; + layers.push_back(y); + expandLayers(layers); + } + getBuffers(&indices, &data); + index = indices[y]; + } + int xz = x * 16 + z; + int half = xz / 2; + int shift = (xz & 1) << 2; + int mask = 0xf0 >> shift; + int offset = static_cast(index) * 128 + half; + data[offset] = (mask & data[offset]) | (value << shift); +} + +void SparseLightStorage::setFullBright() { + unsigned char* buffer = allocate(128); +#pragma clang loop unroll(disable) + for (long long i = 0; i != 128; i += 4) + *reinterpret_cast(buffer + i) = 0x81818181; + replace(reinterpret_cast(buffer) & PointerMask); +} + +int SparseLightStorage::setDataRegion(arrayWithLength source, int x0, int y0, int z0, int x1, + int y1, int z1, int offset) { + int height = y1 - y0; + int first = y0 & ~1; + int pairs = height / 2; + { + std::vector layers; + layers.reserve(pairs * 2); + for (int i = 0, y = first; i < pairs; ++i, y += 2) { + int layer = y; + layers.push_back(layer); + layers.push_back(layer + 1); + } + expandLayers(layers); + } + unsigned char* begin = source.m_data + offset; + unsigned char* cursor = begin; + for (; x0 < x1; ++x0) { + for (int z = z0; z < z1; ++z) { + long long i; + int y = first; + for (i = 0; static_cast(i) < pairs; ++i, y += 2) { + setLight(x0, y, z, cursor[i] & 15); + setLight(x0, y + 1, z, cursor[i] >> 4); + } + cursor += i; + } + } + return cursor - begin; +} + +int SparseLightStorage::getDataRegion(arrayWithLength output, int x0, int y0, int z0, int x1, + int y1, int z1, int offset) { + unsigned char* begin = output.m_data + offset; + unsigned char* cursor = begin; + if (x0 < x1) { + int height = y1 - y0; + int first = y0 & ~1; + int pairs = height / 2; + for (; x0 < x1; ++x0) { + for (int z = z0; z < z1; ++z) { + long long i; + int y = first; + for (i = 0; static_cast(i) < pairs; ++i, y += 2) { + cursor[i] = getLight(x0, y, z); + cursor[i] |= getLight(x0, y + 1, z) << 4; + } + cursor += i; + } + } + } + return cursor - begin; +} diff --git a/src/Minecraft.World/net/minecraft/world/level/storage/loot/BuiltInLootTables.h b/src/Minecraft.World/net/minecraft/world/level/storage/loot/BuiltInLootTables.h index 83b085bb..940a1bf2 100644 --- a/src/Minecraft.World/net/minecraft/world/level/storage/loot/BuiltInLootTables.h +++ b/src/Minecraft.World/net/minecraft/world/level/storage/loot/BuiltInLootTables.h @@ -4,7 +4,7 @@ class ResourceLocation; class BuiltInLootTables { public: - static ResourceLocation* SPAWN_BONUS_CHEST; + static ResourceLocation SPAWN_BONUS_CHEST; static ResourceLocation* ABANDONED_MINESHAFT; static ResourceLocation* DESERT_PYRAMID; static ResourceLocation* DISPENSER_TRAP; @@ -14,7 +14,7 @@ class BuiltInLootTables { static ResourceLocation* JUNGLE_TEMPLE_DISPENSER; static ResourceLocation* MONSTER_ROOM; static ResourceLocation* NETHER_BRIDGE; - static ResourceLocation* SIMPLE_DUNGEON; + static ResourceLocation SIMPLE_DUNGEON; static ResourceLocation* STRONGHOLD_CORRIDOR; static ResourceLocation* STRONGHOLD_CROSSING; static ResourceLocation* STRONGHOLD_LIBRARY; diff --git a/src/Minecraft.World/net/minecraft/world/phys/AABB.h b/src/Minecraft.World/net/minecraft/world/phys/AABB.h index 8f6d8460..1351b2ac 100644 --- a/src/Minecraft.World/net/minecraft/world/phys/AABB.h +++ b/src/Minecraft.World/net/minecraft/world/phys/AABB.h @@ -32,8 +32,13 @@ class AABB { AABB(double, double, double, double, double, double); static AABB* newPermanent(double, double, double, double, double, double); + static AABB* newPermanent(const BlockPos&); + static AABB* newPermanent(const BlockPos&, const BlockPos&); static AABB* newPermanent(const AABB*); static AABB* newTemp(double, double, double, double, double, double); + static AABB* newTemp(const BlockPos&); + static AABB* newTemp(const BlockPos&, const BlockPos&); + static AABB* newTemp(const AABB*); bool containsIncludingLowerBound(Vec3*) const; AABB* set(const AABB*); @@ -43,14 +48,26 @@ class AABB { double getSize() const; AABB* grow(double multiplier) const; AABB* grow(double x, double y, double z) const; + AABB* shrink(double multiplier) const; + AABB* shrink(double x, double y, double z) const; AABB* expand(double x, double y, double z) const; + AABB* contract(double x, double y, double z); + bool equals(const AABB* other) const; bool contains(Vec3* vec); + bool contains(const BlockPos& pos) const; bool intersects(const AABB* rhs) const; bool intersects(double, double, double, double, double, double) const; void resetPool(); AABB* move(const BlockPos&) const; AABB* move(double, double, double) const; HitResult* clip(Vec3*, Vec3*) const; + Vec3* collideWithXPlane(double, Vec3*, Vec3*) const; + Vec3* collideWithYPlane(double, Vec3*, Vec3*) const; + Vec3* collideWithZPlane(double, Vec3*, Vec3*) const; + bool isClosest(Vec3* start, Vec3* closest, Vec3* candidate) const; + bool containsYZ(Vec3*) const; + bool containsXZ(Vec3*) const; + bool containsXY(Vec3*) const; void correctMinMax(); double clipXCollide(const AABB*, double); double clipYCollide(const AABB*, double); diff --git a/src/Minecraft.World/net/minecraft/world/phys/HitResult.h b/src/Minecraft.World/net/minecraft/world/phys/HitResult.h index 92504665..73d8e1cb 100644 --- a/src/Minecraft.World/net/minecraft/world/phys/HitResult.h +++ b/src/Minecraft.World/net/minecraft/world/phys/HitResult.h @@ -10,12 +10,17 @@ class Entity; class HitResult { public: ~HitResult(); + HitResult(Vec3*, const Direction*); HitResult(Vec3*, const Direction*, const BlockPos&); + HitResult(std::shared_ptr entity); const BlockPos& getBlockPos() const; BlockPos m_blockPos; + int m_type; const Direction* m_direction; Vec3* m_hitVector; std::shared_ptr m_entity; }; + +ASSERT_SIZEOF(HitResult, 0x30) diff --git a/src/Minecraft.World/net/minecraft/world/phys/Vec3.cpp b/src/Minecraft.World/net/minecraft/world/phys/Vec3.cpp index dbf75105..da8ea896 100644 --- a/src/Minecraft.World/net/minecraft/world/phys/Vec3.cpp +++ b/src/Minecraft.World/net/minecraft/world/phys/Vec3.cpp @@ -1,10 +1,163 @@ #include "net/minecraft/world/phys/Vec3.h" #include "cmath" +#include "net/minecraft/core/Vec3i.h" #include "net/minecraft/world/phys/AABB.h" DEFINE_THREAD_STORAGE(Vec3, 1024) +Vec3* Vec3::ZERO; + +void Vec3::staticCtor() { + ZERO = new Vec3(0.0, 0.0, 0.0); +} + +Vec3* Vec3::newPermanent(double x, double y, double z) { + return new Vec3(x, y, z); +} + +Vec3* Vec3::newPermanent(const Vec3* other) { + return new Vec3(other->m_x, other->m_y, other->m_z); +} + +Vec3* Vec3::newTemp(double x, double y, double z) { + ThreadStorage* ts = static_cast(TlsGetValue(sThreadStorageIndex)); + Vec3* temp = ts->m_storage[ts->m_unk].set(x, y, z); + ts->m_unk++; + ts->m_unk &= 0x3ff; + return temp; +} + +Vec3* Vec3::newTemp(const Vec3* other) { + return newTemp(other->m_x, other->m_y, other->m_z); +} + +Vec3* Vec3::newTemp(const Vec3i& other) { + return newTemp(other.getX(), other.getY(), other.getZ()); +} + +Vec3* Vec3::normalize() { + double magnitude = sqrt(m_x * m_x + m_y * m_y + m_z * m_z); + if (magnitude < 0.0001) + return newTemp(ZERO); + return newTemp(m_x / magnitude, m_y / magnitude, m_z / magnitude); +} + +Vec3* Vec3::lerp(Vec3* other, double weight) { + return newTemp(m_x + (other->m_x - m_x) * weight, m_y + (other->m_y - m_y) * weight, + m_z + (other->m_z - m_z) * weight); +} + +Vec3* Vec3::vectorTo(Vec3* other) { + return newTemp(other->m_x - m_x, other->m_y - m_y, other->m_z - m_z); +} + +Vec3* Vec3::cross(Vec3* other) { + return newTemp(m_y * other->m_z - m_z * other->m_y, m_z * other->m_x - other->m_z * m_x, + other->m_y * m_x - m_y * other->m_x); +} + +Vec3* Vec3::add(Vec3* other) { + return add(other->m_x, other->m_y, other->m_z); +} + +double Vec3::distanceTo(Vec3* other) { + double dx = other->m_x - m_x; + double dy = other->m_y - m_y; + double dz = other->m_z - m_z; + return sqrt(dx * dx + dy * dy + dz * dz); +} + +Vec3* Vec3::scale(double multiplier) { + return newTemp(m_x * multiplier, m_y * multiplier, m_z * multiplier); +} + +double Vec3::lengthSqr() { + return m_x * m_x + m_y * m_y + m_z * m_z; +} + +Vec3* Vec3::getIntermediateWithXValue(Vec3* other, double x) { + double dx = other->m_x - m_x; + double dy = other->m_y - m_y; + double dz = other->m_z - m_z; + if (dx * dx < double(1.0e-7f)) + return nullptr; + double weight = (x - m_x) / dx; + // Reject out-of-range weights; unordered comparisons fall through in the binary. + if (weight < 0.0 || weight > 1.0) + return nullptr; + return newTemp(m_x + dx * weight, m_y + weight * dy, m_z + weight * dz); +} + +Vec3* Vec3::getIntermediateWithYValue(Vec3* other, double y) { + double dx = other->m_x - m_x; + double dy = other->m_y - m_y; + double dz = other->m_z - m_z; + if (dy * dy < double(1.0e-7f)) + return nullptr; + double weight = (y - m_y) / dy; + if (weight < 0.0 || weight > 1.0) + return nullptr; + return newTemp(m_x + dx * weight, m_y + dy * weight, m_z + weight * dz); +} + +Vec3* Vec3::getIntermediateWithZValue(Vec3* other, double z) { + double dx = other->m_x - m_x; + double dy = other->m_y - m_y; + double dz = other->m_z - m_z; + if (dz * dz < double(1.0e-7f)) + return nullptr; + double weight = (z - m_z) / dz; + if (weight < 0.0 || weight > 1.0) + return nullptr; + return newTemp(m_x + dx * weight, m_y + dy * weight, m_z + dz * weight); +} + +bool Vec3::equals(Vec3* other) { + if (other->m_x != m_x) + return false; + if (other->m_y != m_y) + return false; + return other->m_z == m_z; +} + +Vec3* Vec3::xRot(float angle) { + double cosine = cosf(angle); + double sine = sinf(angle); + return newTemp(m_x, cosine * m_y + sine * m_z, cosine * m_z - sine * m_y); +} + +Vec3* Vec3::yRot(float angle) { + double cosine = cosf(angle); + double sine = sinf(angle); + return newTemp(cosine * m_x + sine * m_z, m_y, cosine * m_z - m_x * sine); +} + +Vec3* Vec3::zRot(float angle) { + double cosine = cosf(angle); + double sine = sinf(angle); + return newTemp(cosine * m_x + sine * m_y, cosine * m_y - m_x * sine, m_z); +} + +Vec3* Vec3::add(double x, double y, double z) { + return newTemp(this->m_x + x, this->m_y + y, this->m_z + z); +} + +Vec3* Vec3::subtract(double x, double y, double z) { + return add(-x, -y, -z); +} + +Vec3* Vec3::subtract(Vec3* other) { + return subtract(other->m_x, other->m_y, other->m_z); +} + +double Vec3::distanceToSqr(Vec3* other) { + double dx = other->m_x - this->m_x; + double dy = other->m_y - this->m_y; + double dz = other->m_z - this->m_z; + return dx * dx + dy * dy + dz * dz; +} + double Vec3::dot(Vec3* rhs) { return this->m_x * rhs->m_x + this->m_y * rhs->m_y + this->m_z * rhs->m_z; } @@ -13,10 +166,11 @@ double Vec3::length() { return sqrt(this->m_x * this->m_x + this->m_y * this->m_y + this->m_z * this->m_z); } -void Vec3::set(double x, double y, double z) { +Vec3* Vec3::set(double x, double y, double z) { this->m_x = x; this->m_y = y; this->m_z = z; + return this; } void Vec3::resetPool() {} diff --git a/src/Minecraft.World/net/minecraft/world/phys/Vec3.h b/src/Minecraft.World/net/minecraft/world/phys/Vec3.h index 6a37420c..6962bf60 100644 --- a/src/Minecraft.World/net/minecraft/world/phys/Vec3.h +++ b/src/Minecraft.World/net/minecraft/world/phys/Vec3.h @@ -3,12 +3,19 @@ #include "net/minecraft/util/ThreadStorage.h" class AABB; +class Vec3i; class Vec3 { public: DECLARE_THREAD_STORAGE(Vec3) Vec3(double x, double y, double z) { + if (x == -0.0) + x = 0.0; + if (y == -0.0) + y = 0.0; + if (z == -0.0) + z = 0.0; this->m_x = x; this->m_y = y; this->m_z = z; @@ -17,6 +24,9 @@ class Vec3 { static Vec3* newTemp(double x, double y, double z); static Vec3* newTemp(const Vec3* other); + static Vec3* newTemp(const Vec3i& other); + static void staticCtor(); + static Vec3* ZERO; Vec3 operator=(Vec3 o); @@ -29,15 +39,30 @@ class Vec3 { Vec3 operator/(Vec3 o) { return Vec3(m_x / o.m_x, m_y / o.m_y, m_z / o.m_z); } static Vec3* newPermanent(double, double, double); + static Vec3* newPermanent(const Vec3* other); - Vec3 yRot(float); + Vec3* xRot(float); + Vec3* yRot(float); + Vec3* zRot(float); double dot(Vec3* rhs); double length(); - void set(double x, double y, double z); + double lengthSqr(); + Vec3* set(double x, double y, double z); static void resetPool(); double distanceTo(AABB* aabb); + double distanceTo(Vec3* other); + double distanceToSqr(Vec3* other); + Vec3* subtract(Vec3* other); Vec3* subtract(double, double, double); Vec3* add(double, double, double); + Vec3* add(Vec3* other); + Vec3* vectorTo(Vec3* other); + Vec3* cross(Vec3* other); + Vec3* lerp(Vec3* other, double weight); + bool equals(Vec3* other); + Vec3* getIntermediateWithXValue(Vec3* other, double x); + Vec3* getIntermediateWithYValue(Vec3* other, double y); + Vec3* getIntermediateWithZValue(Vec3* other, double z); Vec3* normalize(); Vec3* scale(double); diff --git a/src/Minecraft.World/net/minecraft/world/stats/GenericStats.cpp b/src/Minecraft.World/net/minecraft/world/stats/GenericStats.cpp index a572e8f3..186caadb 100644 --- a/src/Minecraft.World/net/minecraft/world/stats/GenericStats.cpp +++ b/src/Minecraft.World/net/minecraft/world/stats/GenericStats.cpp @@ -1,5 +1,14 @@ #include "net/minecraft/world/stats/GenericStats.h" +#include "net/minecraft/world/item/ItemInstance.h" + +arrayWithLength GenericStats::param_itemsUsed(std::shared_ptr player, + not_null_ptr item) { + if (!player || item->isEmpty()) + return sInstance->getParam_noArgs(); + return sInstance->getParam_itemsUsed(player, item); +} + Stat* GenericStats::get_achievement(eAward) { return nullptr; } @@ -192,7 +201,7 @@ arrayWithLength GenericStats::getParam_climbOneM(int) { return getParam_noArgs(); } -arrayWithLength GenericStats::getParam_inecartOneM(int) { +arrayWithLength GenericStats::getParam_minecartOneM(int) { return getParam_noArgs(); } @@ -237,8 +246,8 @@ arrayWithLength GenericStats::getParam_itemsBought(int, int, int) return getParam_noArgs(); } -arrayWithLength GenericStats::getParam_obKill(std::shared_ptr, std::shared_ptr, - DamageSource*) { +arrayWithLength GenericStats::getParam_mobKill(std::shared_ptr, std::shared_ptr, + DamageSource*) { return getParam_noArgs(); } @@ -294,7 +303,7 @@ arrayWithLength GenericStats::getParam_chestfulOfCobblestone(int) return getParam_achievement(eAward_CHESTFUL_OF_COBBLESTONE); } -arrayWithLength GenericStats::getParam_usicToMyEars(int) { +arrayWithLength GenericStats::getParam_musicToMyEars(int) { return getParam_achievement(eAward_MUSIC_TO_MY_EARS); } @@ -366,7 +375,7 @@ arrayWithLength GenericStats::getParam_youWontLikeMeWhenImHungry( return getParam_achievement(eAward_YOU_WONT_LIKE_ME_WHEN_IM_HUNGRY); } -arrayWithLength GenericStats::getParam_ine() { +arrayWithLength GenericStats::getParam_mine() { return getParam_achievement(eAward_MINE); } @@ -382,7 +391,7 @@ arrayWithLength GenericStats::getParam_beamMeUp(int) { return getParam_achievement(eAward_BEAM_ME_UP); } -arrayWithLength GenericStats::getParam_apRoom(int) { +arrayWithLength GenericStats::getParam_mapRoom(int) { return getParam_achievement(eAward_MAP_ROOM); } @@ -738,7 +747,7 @@ arrayWithLength GenericStats::param_buildHoe() { return sInstance->getParam_achievement(eAward_BUILD_HOE); } -arrayWithLength GenericStats::param_akeBread() { +arrayWithLength GenericStats::param_makeBread() { return sInstance->getParam_achievement(eAward_MAKE_BREAD); } @@ -830,7 +839,7 @@ arrayWithLength GenericStats::param_deadshot() { return sInstance->getParam_achievement(eAward_DEADSHOT); } -arrayWithLength GenericStats::param_ountainTop() { +arrayWithLength GenericStats::param_mountainTop() { return sInstance->getParam_achievement(eAward_MOUNTAIN_TOP); } diff --git a/src/Minecraft.World/net/minecraft/world/stats/GenericStats.h b/src/Minecraft.World/net/minecraft/world/stats/GenericStats.h index 943f40f2..26d8bbb2 100644 --- a/src/Minecraft.World/net/minecraft/world/stats/GenericStats.h +++ b/src/Minecraft.World/net/minecraft/world/stats/GenericStats.h @@ -72,7 +72,7 @@ class GenericStats { virtual arrayWithLength getParam_swimOneM(int); virtual arrayWithLength getParam_fallOneM(int); virtual arrayWithLength getParam_climbOneM(int); - virtual arrayWithLength getParam_inecartOneM(int); + virtual arrayWithLength getParam_minecartOneM(int); virtual arrayWithLength getParam_boatOneM(int); virtual arrayWithLength getParam_pigOneM(int); virtual arrayWithLength getParam_cowsMilked(); @@ -84,8 +84,8 @@ class GenericStats { virtual arrayWithLength getParam_itemsUsed(std::shared_ptr, not_null_ptr); virtual arrayWithLength getParam_itemsBought(int, int, int); - virtual arrayWithLength getParam_obKill(std::shared_ptr, std::shared_ptr, - DamageSource*); + virtual arrayWithLength getParam_mobKill(std::shared_ptr, std::shared_ptr, + DamageSource*); virtual arrayWithLength getParam_breedEntity(eINSTANCEOF); virtual arrayWithLength getParam_tamedEntity(eINSTANCEOF); virtual arrayWithLength getParam_curedEntity(eINSTANCEOF); @@ -99,7 +99,7 @@ class GenericStats { virtual arrayWithLength getParam_overkill(int); virtual arrayWithLength getParam_openInventory(int); virtual arrayWithLength getParam_chestfulOfCobblestone(int); - virtual arrayWithLength getParam_usicToMyEars(int); + virtual arrayWithLength getParam_musicToMyEars(int); virtual arrayWithLength getParam_MG03Score(int); virtual arrayWithLength getParam_MG03RingCount(int); virtual arrayWithLength getParam_MG03BestTime(unsigned int); @@ -117,11 +117,11 @@ class GenericStats { virtual arrayWithLength getParam_tisButAScratch(); virtual arrayWithLength getParam_cupid(); virtual arrayWithLength getParam_youWontLikeMeWhenImHungry(); - virtual arrayWithLength getParam_ine(); + virtual arrayWithLength getParam_mine(); virtual arrayWithLength getParam_superSonic(int); virtual arrayWithLength getParam_freeDiver(int); virtual arrayWithLength getParam_beamMeUp(int); - virtual arrayWithLength getParam_apRoom(int); + virtual arrayWithLength getParam_mapRoom(int); virtual arrayWithLength getParam_tenaciousBall(int); virtual arrayWithLength getParam_suckMySnowballs(int); virtual arrayWithLength getParam_greatViewFromUpHere(int); @@ -217,7 +217,7 @@ class GenericStats { static arrayWithLength param_buildPickaxe(); static arrayWithLength param_buildFurnace(); static arrayWithLength param_buildHoe(); - static arrayWithLength param_akeBread(); + static arrayWithLength param_makeBread(); static arrayWithLength param_bakeCake(); static arrayWithLength param_buildBetterPickaxe(); static arrayWithLength param_onARail(int); @@ -240,7 +240,7 @@ class GenericStats { static arrayWithLength param_backFromTheDead(); static arrayWithLength param_equipYourFists(); static arrayWithLength param_deadshot(); - static arrayWithLength param_ountainTop(); + static arrayWithLength param_mountainTop(); static arrayWithLength param_willLikeNoOther(); static arrayWithLength param_changeOfSheets(); static arrayWithLength param_adventuringTime(); diff --git a/src/types.h b/src/types.h index 8873f9d7..1bcb808b 100644 --- a/src/types.h +++ b/src/types.h @@ -15,7 +15,7 @@ template class not_null_ptr : public std::shared_ptr { public: not_null_ptr() = default; - not_null_ptr(T* ptr); + not_null_ptr(T* ptr) : std::shared_ptr(ptr) {} not_null_ptr(const T& other); };