mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-14 14:02:03 +01:00
Merge branch 'mc1.18/copycat' into mc1.18/0.5.1
This commit is contained in:
commit
da5b752e1f
61 changed files with 1934 additions and 80 deletions
|
@ -63,6 +63,9 @@ a87097f3a092264d9b74966ee9e3bcfc0b743f80 assets/create/blockstates/copper_tile_s
|
|||
1cc9cdcd48ea76fe3407dce0973220ff9f63f51a assets/create/blockstates/copper_tile_stairs.json
|
||||
cbae7653d6a6f2d98370e9a4a3bd91fdb529f89d assets/create/blockstates/copper_tiles.json
|
||||
543af282e2cb44f00509d850814b4501f3491d48 assets/create/blockstates/copper_valve_handle.json
|
||||
22a91cc73d6b492dddd9354693b873701fb82c01 assets/create/blockstates/copycat_base.json
|
||||
f4d185b9eb086e5024a9818bad57d524267d6e13 assets/create/blockstates/copycat_panel.json
|
||||
f4d185b9eb086e5024a9818bad57d524267d6e13 assets/create/blockstates/copycat_step.json
|
||||
b759be6f47fb960a7757b70d194921a38261c90a assets/create/blockstates/creative_crate.json
|
||||
da3f1203dd0b0096ce19e09705060a0ed0478bee assets/create/blockstates/creative_fluid_tank.json
|
||||
f0031f5e970b3d5695472ed384950b8631b015ed assets/create/blockstates/creative_motor.json
|
||||
|
@ -562,24 +565,24 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
|
|||
5616dda664dd106d576848124fc0fc1de18d0fd3 assets/create/blockstates/yellow_valve_handle.json
|
||||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||
29da6f08028cfed0f311c8073d7615d6821aaee6 assets/create/lang/en_ud.json
|
||||
0070b8f388464c998ebdec0dd9ed00f95910922b assets/create/lang/en_us.json
|
||||
819a773dac8b804a497bc798aa5b60011de1f736 assets/create/lang/unfinished/de_de.json
|
||||
ed149274800dbc226bdc3dc0ba5f37fd5aff7e9a assets/create/lang/unfinished/es_cl.json
|
||||
59ba35103b2ec6b30b00c38e6410994eb1050a06 assets/create/lang/unfinished/es_es.json
|
||||
27463977eae36ec876a0a298885f606297c971c1 assets/create/lang/unfinished/fr_fr.json
|
||||
b8f760ee53958b6193350c82a0ad6ec4df0116d9 assets/create/lang/unfinished/it_it.json
|
||||
766d570603a8cb1475002045db8976d7bfae72f1 assets/create/lang/unfinished/ja_jp.json
|
||||
5d585d77810a3bc6b4247eff5a08f0a85fcc0e7c assets/create/lang/unfinished/ko_kr.json
|
||||
1275ee80cc65b49a77c26dbbd3bfba9eac762ead assets/create/lang/unfinished/nl_nl.json
|
||||
9c2210faa1a598567c9b8c6e0529183227afd8de assets/create/lang/unfinished/pl_pl.json
|
||||
4e07b14961b64aa05a60193335663a4ea2cbe4ef assets/create/lang/unfinished/pt_br.json
|
||||
4f27ff82d89d4b25b3cc237118611c385b6bedd9 assets/create/lang/unfinished/pt_pt.json
|
||||
3b76d014cacd40e53e1f8f10545a133e2289ebc7 assets/create/lang/unfinished/ro_ro.json
|
||||
b315407f620e95f376e4b0aab5cc6755c6410227 assets/create/lang/unfinished/ru_ru.json
|
||||
5ec15854ee92e6e463341b226da3682f213ad7a5 assets/create/lang/unfinished/uk_ua.json
|
||||
1be5b9da89c4f22421bda20eae909f69dd8f7554 assets/create/lang/unfinished/zh_cn.json
|
||||
df88975ac97350e6f77355c053f853f14d867ecb assets/create/lang/unfinished/zh_tw.json
|
||||
3054a5519fbf91481b0c9c8160a20679fa9530da assets/create/lang/en_ud.json
|
||||
c57c7f223e483ec45f7b94a33582f2bf66c4cf60 assets/create/lang/en_us.json
|
||||
4080736502d1f2367ae70d9aae33ca0314db5bd9 assets/create/lang/unfinished/de_de.json
|
||||
76227addfbcb0cb33c6851fdcc915b774493b801 assets/create/lang/unfinished/es_cl.json
|
||||
2cce9e6ef650c78c594d62b96cd3f976dc2affec assets/create/lang/unfinished/es_es.json
|
||||
ffd78f1c2269cfc95c9cddb81f98500451f1e249 assets/create/lang/unfinished/fr_fr.json
|
||||
7da0e0a81888382ef09808dc26a0acc00981bfc5 assets/create/lang/unfinished/it_it.json
|
||||
777e9fcbd341e8b7c1a76400f384a7892cebd84f assets/create/lang/unfinished/ja_jp.json
|
||||
3efd5341a65b265b015caff7756c93a9e62e24b2 assets/create/lang/unfinished/ko_kr.json
|
||||
d69eb7e9ada984144b84adcaa66bd58d34392f93 assets/create/lang/unfinished/nl_nl.json
|
||||
ef1d3c48c5b29618c7c03b862cb414450f61b2b4 assets/create/lang/unfinished/pl_pl.json
|
||||
fd304a1b08cb1a26a71bf14e03427f3ea347b851 assets/create/lang/unfinished/pt_br.json
|
||||
02c1b9461cf73901e7c524970fb70bc27cbeb805 assets/create/lang/unfinished/pt_pt.json
|
||||
5e55fe730dadb7c4cb5f8cac65dd2288c3fc8349 assets/create/lang/unfinished/ro_ro.json
|
||||
ab0235e297d83f14990c9c11c9ea494cb725c082 assets/create/lang/unfinished/ru_ru.json
|
||||
2dcd9d1659d59f399b44b2d0e0e7428e248cafca assets/create/lang/unfinished/uk_ua.json
|
||||
1ec8b3397df54e2af39e3e52c1ffb7c0a11a3b8b assets/create/lang/unfinished/zh_cn.json
|
||||
6b2ccb147e70ae407da8686b5b989991a11bd802 assets/create/lang/unfinished/zh_tw.json
|
||||
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
|
||||
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
|
||||
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
|
||||
|
@ -1697,6 +1700,8 @@ ecaea6626101acc4c655a33e2148c336bfde9895 assets/create/models/item/copper_shingl
|
|||
0f6e8e2ff3543fd0b076da64fa2cf8c2bfd017e9 assets/create/models/item/copper_tile_stairs.json
|
||||
532d2c60de6129082b7ff5a713e9a70d89078f58 assets/create/models/item/copper_tiles.json
|
||||
5583368909c319acfcf0f7a419bedf23272fe613 assets/create/models/item/copper_valve_handle.json
|
||||
d17c8d4e1daf2e128254ee6897585c5d84902433 assets/create/models/item/copycat_panel.json
|
||||
aa1b9e74076d71cd096e057dc752023b2bf1d994 assets/create/models/item/copycat_step.json
|
||||
4e253e7c0626dfd76e2d39786ce1a34e0baaa62d assets/create/models/item/crafter_slot_cover.json
|
||||
1f947dafff30da701b7675f5b026ccab3129b079 assets/create/models/item/crafting_blueprint.json
|
||||
db68f1fcc5b91f3ee0cc023538d965d76dd13506 assets/create/models/item/creative_blaze_cake.json
|
||||
|
@ -3450,6 +3455,9 @@ dccfbda7fd3a7a75c323dea619d8d309ae980469 data/create/loot_tables/blocks/copper_s
|
|||
8abac40a29800a0ca18c50ec8ce346cad15ad47a data/create/loot_tables/blocks/copper_tile_stairs.json
|
||||
3eddbc442b37ba3bb309eaf26c2f4ad06de40df7 data/create/loot_tables/blocks/copper_tiles.json
|
||||
6430f776846393ab6d70d23faeccb3e353c66129 data/create/loot_tables/blocks/copper_valve_handle.json
|
||||
5c1df8443043b3fe3b665dba348e2ff188bcbe31 data/create/loot_tables/blocks/copycat_base.json
|
||||
565441b809ded4218e69abd88bf26abee763ca08 data/create/loot_tables/blocks/copycat_panel.json
|
||||
3f3df2ffc1efb1492a2a42c1eff14e5cad06b6f5 data/create/loot_tables/blocks/copycat_step.json
|
||||
24f8cf0606fda07ecc26970f9aeb3f9da75e9a8f data/create/loot_tables/blocks/creative_crate.json
|
||||
02efe9913be9d546c73f89e29016abf486c25f39 data/create/loot_tables/blocks/creative_fluid_tank.json
|
||||
ea6580ed7d1b08ec10838bff7fa46b907e981277 data/create/loot_tables/blocks/creative_motor.json
|
||||
|
@ -5641,11 +5649,13 @@ ac265a674626e0e832330086fd18fe0be37fc327 data/create/recipes/weathered_copper_ti
|
|||
5942a571f79c40524bbf408775cf91de4715f2b6 data/create/recipes/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json
|
||||
2d549ea56fb226c0e31e66c0391996093f8bece9 data/create/tags/blocks/brittle.json
|
||||
d99d5c67bdffff60789a19bd51a5c5267c75e0a4 data/create/tags/blocks/casing.json
|
||||
bc203f09dd7f48965d146d0bd035fb904cb75e7d data/create/tags/blocks/copycat_allow.json
|
||||
d4a3b66f4b763b9a2dcdea74b7273f0ae85cb335 data/create/tags/blocks/copycat_deny.json
|
||||
443f75adbf3d2f6fb0aad4b344372669470065b8 data/create/tags/blocks/fan_transparent.json
|
||||
6e5d3b2123fbb00e7f439c091623619502551bca data/create/tags/blocks/non_movable.json
|
||||
10781e8cfcbb3486327aace3aa00e437fb44b331 data/create/tags/blocks/ore_override_stone.json
|
||||
418c6da531d6206e3cbe4049dce3db23c4270bed data/create/tags/blocks/passive_boiler_heaters.json
|
||||
74f4ba5f6f61c30e27947c6fb4557e888d018285 data/create/tags/blocks/safe_nbt.json
|
||||
3492722cffa53b96d7a91f8c04d792329d902c85 data/create/tags/blocks/safe_nbt.json
|
||||
6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json
|
||||
d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/blocks/toolboxes.json
|
||||
8861f982c335a1f17796df4af53a7d5dc91fc85a data/create/tags/blocks/tree_attachments.json
|
||||
|
@ -5740,8 +5750,8 @@ e16d74571ae10007f06f3b86ddf05d3ca9b73559 data/minecraft/tags/blocks/doors.json
|
|||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/dripstone_replaceable_blocks.json
|
||||
69f596fcb065e26b02ce246760432b5174191b76 data/minecraft/tags/blocks/impermeable.json
|
||||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/lush_ground_replaceable.json
|
||||
f1d3b91aab8ea3c59a06b8ccc1a469b3ef953220 data/minecraft/tags/blocks/mineable/axe.json
|
||||
53541d9dce5cf1462da568b9bde5a11d8fbe24b7 data/minecraft/tags/blocks/mineable/pickaxe.json
|
||||
a8662d145a8b1b5faa263c2aac9d12e7727c8c3f data/minecraft/tags/blocks/mineable/axe.json
|
||||
6f18f0d6fe0e4204079cbf9c7b6dc79c8cebcaa9 data/minecraft/tags/blocks/mineable/pickaxe.json
|
||||
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/moss_replaceable.json
|
||||
e157c1d3af30e409e34bbefbe15a037e6e1c8daa data/minecraft/tags/blocks/needs_iron_tool.json
|
||||
a08f67865337f62601c5e333b4011382d10020e4 data/minecraft/tags/blocks/needs_stone_tool.json
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "create:block/copycat_base/block"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "minecraft:block/air"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "minecraft:block/air"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,6 +64,9 @@
|
|||
"block.create.copper_tile_stairs": "s\u0279\u0131\u0250\u0287S \u01DD\u05DF\u0131\u27D8 \u0279\u01DDddo\u0186",
|
||||
"block.create.copper_tiles": "s\u01DD\u05DF\u0131\u27D8 \u0279\u01DDddo\u0186",
|
||||
"block.create.copper_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u0279\u01DDddo\u0186",
|
||||
"block.create.copycat_base": "\u01DDs\u0250\u15FA \u0287\u0250\u0254\u028Edo\u0186",
|
||||
"block.create.copycat_panel": "\u05DF\u01DDu\u0250\u0500 \u0287\u0250\u0254\u028Edo\u0186",
|
||||
"block.create.copycat_step": "d\u01DD\u0287S \u0287\u0250\u0254\u028Edo\u0186",
|
||||
"block.create.creative_crate": "\u01DD\u0287\u0250\u0279\u0186 \u01DD\u028C\u0131\u0287\u0250\u01DD\u0279\u0186",
|
||||
"block.create.creative_fluid_tank": "\u029Eu\u0250\u27D8 p\u0131n\u05DF\u2132 \u01DD\u028C\u0131\u0287\u0250\u01DD\u0279\u0186",
|
||||
"block.create.creative_motor": "\u0279o\u0287oW \u01DD\u028C\u0131\u0287\u0250\u01DD\u0279\u0186",
|
||||
|
|
|
@ -67,6 +67,9 @@
|
|||
"block.create.copper_tile_stairs": "Copper Tile Stairs",
|
||||
"block.create.copper_tiles": "Copper Tiles",
|
||||
"block.create.copper_valve_handle": "Copper Valve Handle",
|
||||
"block.create.copycat_base": "Copycat Base",
|
||||
"block.create.copycat_panel": "Copycat Panel",
|
||||
"block.create.copycat_step": "Copycat Step",
|
||||
"block.create.creative_crate": "Creative Crate",
|
||||
"block.create.creative_fluid_tank": "Creative Fluid Tank",
|
||||
"block.create.creative_motor": "Creative Motor",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 870",
|
||||
"_": "Missing Localizations: 873",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "Kupferfliesentreppe",
|
||||
"block.create.copper_tiles": "Kupferfliesen",
|
||||
"block.create.copper_valve_handle": "Kupfer Ventilgriff",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Kreative anpassbare Kiste",
|
||||
"block.create.creative_fluid_tank": "Kreativer Flüssigkeitstank",
|
||||
"block.create.creative_motor": "Kreativer Motor",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1016",
|
||||
"_": "Missing Localizations: 1019",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "UNLOCALIZED: Copper Tile Stairs",
|
||||
"block.create.copper_tiles": "Baldosas de Cobre",
|
||||
"block.create.copper_valve_handle": "Válvula de Cobre",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Cajón del Creativo",
|
||||
"block.create.creative_fluid_tank": "Tanque de Fluidos del Creativo",
|
||||
"block.create.creative_motor": "Motor del Creativo",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 36",
|
||||
"_": "Missing Localizations: 39",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "Escaleras de baldosas de cobre",
|
||||
"block.create.copper_tiles": "Bloque de baldosas de cobre",
|
||||
"block.create.copper_valve_handle": "Asa de válvula de cobre",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Caja creativa",
|
||||
"block.create.creative_fluid_tank": "Tanque de fluidos creativo",
|
||||
"block.create.creative_motor": "Motor creativo",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 2165",
|
||||
"_": "Missing Localizations: 2168",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "UNLOCALIZED: Copper Tile Stairs",
|
||||
"block.create.copper_tiles": "Tuiles en cuivre",
|
||||
"block.create.copper_valve_handle": "Vanne en cuivre",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Créateur de schémacanon",
|
||||
"block.create.creative_fluid_tank": "Réservoir créatif",
|
||||
"block.create.creative_motor": "Moteur",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 30",
|
||||
"_": "Missing Localizations: 33",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "Scalini di mattonelle di rame",
|
||||
"block.create.copper_tiles": "Piastrelle di rame",
|
||||
"block.create.copper_valve_handle": "Maniglia per valvola di rame",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Cassa (creativa)",
|
||||
"block.create.creative_fluid_tank": "Serbatoio per fluidi (creativa)",
|
||||
"block.create.creative_motor": "Motore (creativa)",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 32",
|
||||
"_": "Missing Localizations: 35",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "銅タイルの階段",
|
||||
"block.create.copper_tiles": "銅タイル",
|
||||
"block.create.copper_valve_handle": "銅のバルブハンドル",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "クリエティブクレート",
|
||||
"block.create.creative_fluid_tank": "クリエイティブ液体タンク",
|
||||
"block.create.creative_motor": "クリエイティブモーター",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 36",
|
||||
"_": "Missing Localizations: 39",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "구리 타일 계단",
|
||||
"block.create.copper_tiles": "구리 타일",
|
||||
"block.create.copper_valve_handle": "구리 밸브 손잡이",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "크리에이티브 창고",
|
||||
"block.create.creative_fluid_tank": "크리에이티브 탱크",
|
||||
"block.create.creative_motor": "크리에이티브 모터",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 2513",
|
||||
"_": "Missing Localizations: 2516",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "UNLOCALIZED: Copper Tile Stairs",
|
||||
"block.create.copper_tiles": "UNLOCALIZED: Copper Tiles",
|
||||
"block.create.copper_valve_handle": "UNLOCALIZED: Copper Valve Handle",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Bouwtekeningkannon Creatiefeerder",
|
||||
"block.create.creative_fluid_tank": "UNLOCALIZED: Creative Fluid Tank",
|
||||
"block.create.creative_motor": "UNLOCALIZED: Creative Motor",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 40",
|
||||
"_": "Missing Localizations: 43",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "Schody z miedziaych kafelków",
|
||||
"block.create.copper_tiles": "Miedziane kafelki",
|
||||
"block.create.copper_valve_handle": "Miedziane pokrętło",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Kreatywna skrzynka",
|
||||
"block.create.creative_fluid_tank": "Kreatywny zbiornik",
|
||||
"block.create.creative_motor": "Kreatywny silnik",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1359",
|
||||
"_": "Missing Localizations: 1362",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "Escada de ladrilho de cobre",
|
||||
"block.create.copper_tiles": "Ladrilho de cobre",
|
||||
"block.create.copper_valve_handle": "Válvula de Cobre",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Caixa Criativa",
|
||||
"block.create.creative_fluid_tank": "Tanque de Fluidos Criativo",
|
||||
"block.create.creative_motor": "Motor Criativo",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 2224",
|
||||
"_": "Missing Localizations: 2227",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "UNLOCALIZED: Copper Tile Stairs",
|
||||
"block.create.copper_tiles": "UNLOCALIZED: Copper Tiles",
|
||||
"block.create.copper_valve_handle": "Manopla de válvula de Cobre",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Caixa Criativa",
|
||||
"block.create.creative_fluid_tank": "Tanque de Fluidos Criativo",
|
||||
"block.create.creative_motor": "Motor Criativo",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 683",
|
||||
"_": "Missing Localizations: 686",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "Scări De Țiglă De Cupru",
|
||||
"block.create.copper_tiles": "Țigle De Cupru",
|
||||
"block.create.copper_valve_handle": "Mâner De Supapă De Cupru",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Ladă Creativ",
|
||||
"block.create.creative_fluid_tank": "Rezervor De Fluid Creativ",
|
||||
"block.create.creative_motor": "Motor Creativ",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 28",
|
||||
"_": "Missing Localizations: 31",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "Ступеньки из медной плитки",
|
||||
"block.create.copper_tiles": "Медная плитка",
|
||||
"block.create.copper_valve_handle": "Медный ручной вентиль",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Творческий ящик",
|
||||
"block.create.creative_fluid_tank": "Творческий жидкостный бак",
|
||||
"block.create.creative_motor": "Творческий мотор",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 1014",
|
||||
"_": "Missing Localizations: 1017",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "UNLOCALIZED: Copper Tile Stairs",
|
||||
"block.create.copper_tiles": "Мідна плитка",
|
||||
"block.create.copper_valve_handle": "Мідний ручний клапан",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "Творчий ящик",
|
||||
"block.create.creative_fluid_tank": "Творчий бак для рідини",
|
||||
"block.create.creative_motor": "Творчий мотор",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 28",
|
||||
"_": "Missing Localizations: 31",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "铜瓦楼梯",
|
||||
"block.create.copper_tiles": "铜瓦",
|
||||
"block.create.copper_valve_handle": "铜阀门手轮",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "创造板条箱",
|
||||
"block.create.creative_fluid_tank": "创造流体储罐",
|
||||
"block.create.creative_motor": "创造马达",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 36",
|
||||
"_": "Missing Localizations: 39",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -68,6 +68,9 @@
|
|||
"block.create.copper_tile_stairs": "銅磚瓦階梯",
|
||||
"block.create.copper_tiles": "銅磚瓦",
|
||||
"block.create.copper_valve_handle": "銅製閥門開關",
|
||||
"block.create.copycat_base": "UNLOCALIZED: Copycat Base",
|
||||
"block.create.copycat_panel": "UNLOCALIZED: Copycat Panel",
|
||||
"block.create.copycat_step": "UNLOCALIZED: Copycat Step",
|
||||
"block.create.creative_crate": "創造板條箱",
|
||||
"block.create.creative_fluid_tank": "創造流體儲存罐",
|
||||
"block.create.creative_motor": "創造馬達",
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "create:block/copycat_base/panel"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "create:block/copycat_base/step"
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:air"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "create:copycat_panel"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "create:copycat_step"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"minecraft:barrel"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"#minecraft:cauldrons",
|
||||
"#minecraft:saplings",
|
||||
"#minecraft:climbable"
|
||||
]
|
||||
}
|
|
@ -15,6 +15,8 @@
|
|||
"create:radial_chassis",
|
||||
"create:sequenced_gearshift",
|
||||
"create:rotation_speed_controller",
|
||||
"create:copycat_step",
|
||||
"create:copycat_panel",
|
||||
"create:andesite_funnel",
|
||||
"create:andesite_belt_funnel",
|
||||
"create:brass_funnel",
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
"create:deployer",
|
||||
"create:portable_storage_interface",
|
||||
"create:redstone_contact",
|
||||
"create:elevator_contact",
|
||||
"create:mechanical_harvester",
|
||||
"create:mechanical_plough",
|
||||
"create:white_seat",
|
||||
|
@ -99,7 +100,8 @@
|
|||
"create:rotation_speed_controller",
|
||||
"create:mechanical_arm",
|
||||
"create:railway_casing",
|
||||
"create:elevator_contact",
|
||||
"create:copycat_step",
|
||||
"create:copycat_panel",
|
||||
"create:content_observer",
|
||||
"create:stockpile_switch",
|
||||
"create:creative_crate",
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
"create:deployer",
|
||||
"create:portable_storage_interface",
|
||||
"create:redstone_contact",
|
||||
"create:elevator_contact",
|
||||
"create:mechanical_harvester",
|
||||
"create:mechanical_plough",
|
||||
"create:andesite_casing",
|
||||
|
@ -126,7 +127,9 @@
|
|||
"create:train_trapdoor",
|
||||
"create:framed_glass_door",
|
||||
"create:framed_glass_trapdoor",
|
||||
"create:elevator_contact",
|
||||
"create:copycat_base",
|
||||
"create:copycat_step",
|
||||
"create:copycat_panel",
|
||||
"create:item_vault",
|
||||
"create:andesite_funnel",
|
||||
"create:andesite_belt_funnel",
|
||||
|
|
|
@ -144,6 +144,10 @@ import com.simibubi.create.content.curiosities.deco.PlacardBlock;
|
|||
import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock;
|
||||
import com.simibubi.create.content.curiosities.deco.TrainTrapdoorBlock;
|
||||
import com.simibubi.create.content.curiosities.deco.TrapdoorCTBehaviour;
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatPanelBlock;
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatPanelModel;
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatStepBlock;
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatStepModel;
|
||||
import com.simibubi.create.content.curiosities.girder.ConnectedGirderModel;
|
||||
import com.simibubi.create.content.curiosities.girder.GirderBlock;
|
||||
import com.simibubi.create.content.curiosities.girder.GirderBlockStateGenerator;
|
||||
|
@ -1318,6 +1322,24 @@ public class AllBlocks {
|
|||
.item(RedstoneContactItem::new)
|
||||
.transform(customItemModel("_", "block"))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<ElevatorContactBlock> ELEVATOR_CONTACT =
|
||||
REGISTRATE.block("elevator_contact", ElevatorContactBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.properties(p -> p.color(MaterialColor.TERRACOTTA_YELLOW))
|
||||
.properties(p -> p.lightLevel(ElevatorContactBlock::getLight))
|
||||
.transform(axeOrPickaxe())
|
||||
.blockstate((c, p) -> p.directionalBlock(c.get(), state -> {
|
||||
Boolean calling = state.getValue(ElevatorContactBlock.CALLING);
|
||||
Boolean powering = state.getValue(ElevatorContactBlock.POWERING);
|
||||
return powering ? AssetLookup.partialBaseModel(c, p, "powered")
|
||||
: calling ? AssetLookup.partialBaseModel(c, p, "dim") : AssetLookup.partialBaseModel(c, p);
|
||||
}))
|
||||
.loot((p, b) -> p.dropOther(b, REDSTONE_CONTACT.get()))
|
||||
.onRegister(assignDataBehaviour(new CurrentFloorDisplaySource(), "current_floor"))
|
||||
.item()
|
||||
.transform(customItemModel("_", "block"))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<HarvesterBlock> MECHANICAL_HARVESTER =
|
||||
REGISTRATE.block("mechanical_harvester", HarvesterBlock::new)
|
||||
|
@ -1662,22 +1684,28 @@ public class AllBlocks {
|
|||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<ElevatorContactBlock> ELEVATOR_CONTACT =
|
||||
REGISTRATE.block("elevator_contact", ElevatorContactBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.properties(p -> p.color(MaterialColor.TERRACOTTA_YELLOW))
|
||||
.properties(p -> p.lightLevel(ElevatorContactBlock::getLight))
|
||||
.transform(axeOrPickaxe())
|
||||
.blockstate((c, p) -> p.directionalBlock(c.get(), state -> {
|
||||
Boolean calling = state.getValue(ElevatorContactBlock.CALLING);
|
||||
Boolean powering = state.getValue(ElevatorContactBlock.POWERING);
|
||||
return powering ? AssetLookup.partialBaseModel(c, p, "powered")
|
||||
: calling ? AssetLookup.partialBaseModel(c, p, "dim") : AssetLookup.partialBaseModel(c, p);
|
||||
}))
|
||||
.loot((p, b) -> p.dropOther(b, REDSTONE_CONTACT.get()))
|
||||
.onRegister(assignDataBehaviour(new CurrentFloorDisplaySource(), "current_floor"))
|
||||
public static final BlockEntry<Block> COPYCAT_BASE = REGISTRATE.block("copycat_base", Block::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.properties(p -> p.color(MaterialColor.GLOW_LICHEN))
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<CopycatStepBlock> COPYCAT_STEP =
|
||||
REGISTRATE.block("copycat_step", CopycatStepBlock::new)
|
||||
.transform(BuilderTransformers.copycat())
|
||||
.onRegister(CreateRegistrate.blockModel(() -> CopycatStepModel::new))
|
||||
.item()
|
||||
.transform(customItemModel("_", "block"))
|
||||
.transform(customItemModel("copycat_base", "step"))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<CopycatPanelBlock> COPYCAT_PANEL =
|
||||
REGISTRATE.block("copycat_panel", CopycatPanelBlock::new)
|
||||
.transform(BuilderTransformers.copycat())
|
||||
.onRegister(CreateRegistrate.blockModel(() -> CopycatPanelModel::new))
|
||||
.item()
|
||||
.transform(customItemModel("copycat_base", "panel"))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<ItemVaultBlock> ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new)
|
||||
|
|
|
@ -30,6 +30,7 @@ public class AllShapes {
|
|||
CASING_13PX = shape(0, 0, 0, 16, 13, 16).forDirectional(),
|
||||
CASING_12PX = shape(0, 0, 0, 16, 12, 16).forDirectional(),
|
||||
CASING_11PX = shape(0, 0, 0, 16, 11, 16).forDirectional(),
|
||||
CASING_3PX = shape(0, 0, 0, 16, 3, 16).forDirectional(),
|
||||
MOTOR_BLOCK = shape(3, 0, 3, 13, 14, 13).forDirectional(),
|
||||
|
||||
FOUR_VOXEL_POLE = shape(6, 0, 6, 10, 16, 10).forAxis(), SIX_VOXEL_POLE = shape(5, 0, 5, 11, 16, 11).forAxis(),
|
||||
|
@ -124,6 +125,9 @@ public class AllShapes {
|
|||
GIRDER_BEAM_SHAFT = shape(GIRDER_BEAM.get(Axis.X)).add(SIX_VOXEL_POLE.get(Axis.Z))
|
||||
.forHorizontalAxis(),
|
||||
|
||||
STEP_BOTTOM = shape(0, 0, 8, 16, 8, 16).forHorizontal(SOUTH),
|
||||
STEP_TOP = shape(0, 8, 8, 16, 16, 16).forHorizontal(SOUTH),
|
||||
|
||||
CONTROLS = shape(0, 0, 6, 16, 14, 16).forHorizontal(NORTH),
|
||||
CONTRAPTION_CONTROLS = shape(0, 0, 6, 2, 14, 16).add(14, 0, 6, 16, 14, 16)
|
||||
.add(0, 0, 14, 16, 14, 16)
|
||||
|
|
|
@ -125,6 +125,8 @@ public class AllTags {
|
|||
WINDOWABLE,
|
||||
WRENCH_PICKUP,
|
||||
TREE_ATTACHMENTS,
|
||||
COPYCAT_ALLOW,
|
||||
COPYCAT_DENY,
|
||||
|
||||
RELOCATION_NOT_SUPPORTED(FORGE),
|
||||
WG_STONE(FORGE),
|
||||
|
@ -407,6 +409,11 @@ public class AllTags {
|
|||
|
||||
AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS);
|
||||
AllBlockTags.SAFE_NBT.includeAll(BlockTags.BANNERS);
|
||||
|
||||
AllBlockTags.COPYCAT_ALLOW.add(Blocks.BARREL);
|
||||
AllBlockTags.COPYCAT_DENY.includeAll(BlockTags.CAULDRONS);
|
||||
AllBlockTags.COPYCAT_DENY.includeAll(BlockTags.SAPLINGS);
|
||||
AllBlockTags.COPYCAT_DENY.includeAll(BlockTags.CLIMBABLE);
|
||||
|
||||
AllBlockTags.WRENCH_PICKUP.includeAll(BlockTags.RAILS);
|
||||
AllBlockTags.WRENCH_PICKUP.includeAll(BlockTags.BUTTONS);
|
||||
|
|
|
@ -142,6 +142,7 @@ import com.simibubi.create.content.curiosities.deco.PlacardRenderer;
|
|||
import com.simibubi.create.content.curiosities.deco.PlacardTileEntity;
|
||||
import com.simibubi.create.content.curiosities.deco.SlidingDoorRenderer;
|
||||
import com.simibubi.create.content.curiosities.deco.SlidingDoorTileEntity;
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatTileEntity;
|
||||
import com.simibubi.create.content.curiosities.toolbox.ToolBoxInstance;
|
||||
import com.simibubi.create.content.curiosities.toolbox.ToolboxRenderer;
|
||||
import com.simibubi.create.content.curiosities.toolbox.ToolboxTileEntity;
|
||||
|
@ -827,6 +828,11 @@ public class AllTileEntities {
|
|||
.validBlocks(AllBlocks.TRAIN_DOOR, AllBlocks.FRAMED_GLASS_DOOR)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<CopycatTileEntity> UNIVERSAL_FRAME = Create.registrate()
|
||||
.tileEntity("universal_frame", CopycatTileEntity::new)
|
||||
.validBlocks(AllBlocks.COPYCAT_PANEL, AllBlocks.COPYCAT_STEP)
|
||||
.register();
|
||||
|
||||
public static final BlockEntityEntry<FlapDisplayTileEntity> FLAP_DISPLAY = Create.registrate()
|
||||
.tileEntity("flap_display", FlapDisplayTileEntity::new)
|
||||
.instance(() -> MechanicalCrafterInstance::new)
|
||||
|
|
|
@ -2,11 +2,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.be
|
|||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTags.AllBlockTags;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter;
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatTileEntity;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -14,6 +16,7 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
@ -59,11 +62,18 @@ public class BearingContraption extends Contraption {
|
|||
@Override
|
||||
public void addBlock(BlockPos pos, Pair<StructureBlockInfo, BlockEntity> capture) {
|
||||
BlockPos localPos = pos.subtract(anchor);
|
||||
if (!getBlocks().containsKey(localPos) && AllBlockTags.WINDMILL_SAILS.matches(capture.getKey().state))
|
||||
if (!getBlocks().containsKey(localPos) && AllBlockTags.WINDMILL_SAILS.matches(getSailBlock(capture)))
|
||||
sailBlocks++;
|
||||
super.addBlock(pos, capture);
|
||||
}
|
||||
|
||||
private BlockState getSailBlock(Pair<StructureBlockInfo, BlockEntity> capture) {
|
||||
BlockState state = capture.getKey().state;
|
||||
if (AllBlocks.COPYCAT_PANEL.has(state) && capture.getRight()instanceof CopycatTileEntity cte)
|
||||
return cte.getMaterial();
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag writeNBT(boolean spawnPacket) {
|
||||
CompoundTag tag = super.writeNBT(spawnPacket);
|
||||
|
|
|
@ -84,9 +84,13 @@ public class SailBlock extends WrenchableDirectionalBlock {
|
|||
ItemStack heldItem = player.getItemInHand(hand);
|
||||
|
||||
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
|
||||
if (placementHelper.matchesItem(heldItem))
|
||||
return placementHelper.getOffset(player, world, state, pos, ray)
|
||||
.placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
|
||||
if (!player.isShiftKeyDown() && player.mayBuild()) {
|
||||
if (placementHelper.matchesItem(heldItem)) {
|
||||
placementHelper.getOffset(player, world, state, pos, ray)
|
||||
.placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (heldItem.getItem() instanceof ShearsItem) {
|
||||
if (!world.isClientSide)
|
||||
|
@ -119,7 +123,8 @@ public class SailBlock extends WrenchableDirectionalBlock {
|
|||
}
|
||||
|
||||
// Dye all adjacent
|
||||
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, hit, state.getValue(FACING).getAxis());
|
||||
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, hit, state.getValue(FACING)
|
||||
.getAxis());
|
||||
for (Direction d : directions) {
|
||||
BlockPos offset = pos.relative(d);
|
||||
BlockState adjacentState = world.getBlockState(offset);
|
||||
|
@ -182,7 +187,8 @@ public class SailBlock extends WrenchableDirectionalBlock {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) {
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos,
|
||||
Player player) {
|
||||
ItemStack pickBlock = super.getCloneItemStack(state, target, world, pos, player);
|
||||
if (pickBlock.isEmpty())
|
||||
return AllBlocks.SAIL.get()
|
||||
|
|
|
@ -34,7 +34,8 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) {
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state,
|
||||
IModelData tileData) {
|
||||
PipeModelData data = new PipeModelData();
|
||||
FluidTransportBehaviour transport = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE);
|
||||
BracketedTileEntityBehaviour bracket = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE);
|
||||
|
|
|
@ -42,11 +42,12 @@ public class FluidTankModel extends CTModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) {
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state,
|
||||
IModelData tileData) {
|
||||
CullData cullData = new CullData();
|
||||
for (Direction d : Iterate.horizontalDirections)
|
||||
cullData.setCulled(d, ConnectivityHandler.isConnected(world, pos, pos.relative(d)));
|
||||
return super.gatherModelData(builder, world, pos, state).withInitial(CULL_PROPERTY, cullData);
|
||||
return super.gatherModelData(builder, world, pos, state, tileData).withInitial(CULL_PROPERTY, cullData);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,8 +37,10 @@ public class TrainTrapdoorBlock extends TrapDoorBlock implements IWrenchable {
|
|||
}
|
||||
|
||||
public static boolean isConnected(BlockState state, BlockState other, Direction pDirection) {
|
||||
state = state.setValue(WATERLOGGED, false);
|
||||
other = other.setValue(WATERLOGGED, false);
|
||||
state = state.setValue(WATERLOGGED, false)
|
||||
.setValue(POWERED, false);
|
||||
other = other.setValue(WATERLOGGED, false)
|
||||
.setValue(POWERED, false);
|
||||
|
||||
boolean open = state.getValue(OPEN);
|
||||
Half half = state.getValue(HALF);
|
||||
|
|
|
@ -0,0 +1,365 @@
|
|||
package com.simibubi.create.content.curiosities.frames;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTags.AllBlockTags;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||
import com.simibubi.create.foundation.block.ITE;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.color.block.BlockColor;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.SpawnPlacements.Type;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.GrassColor;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.StairBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public abstract class CopycatBlock extends Block implements ITE<CopycatTileEntity>, IWrenchable {
|
||||
|
||||
public CopycatBlock(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <S extends BlockEntity> BlockEntityTicker<S> getTicker(Level p_153212_, BlockState p_153213_,
|
||||
BlockEntityType<S> p_153214_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) {
|
||||
onWrenched(state, context);
|
||||
return IWrenchable.super.onSneakWrenched(state, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
|
||||
return onTileEntityUse(context.getLevel(), context.getClickedPos(), ufte -> {
|
||||
ItemStack consumedItem = ufte.getConsumedItem();
|
||||
if (!ufte.hasCustomMaterial())
|
||||
return InteractionResult.PASS;
|
||||
Player player = context.getPlayer();
|
||||
if (!player.isCreative())
|
||||
player.getInventory()
|
||||
.placeItemBackInInventory(consumedItem);
|
||||
context.getLevel()
|
||||
.levelEvent(2001, context.getClickedPos(), Block.getId(ufte.getBlockState()));
|
||||
ufte.setMaterial(AllBlocks.COPYCAT_BASE.getDefaultState());
|
||||
ufte.setItem(ItemStack.EMPTY);
|
||||
return InteractionResult.SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand,
|
||||
BlockHitResult pHit) {
|
||||
|
||||
if (pPlayer == null)
|
||||
return InteractionResult.PASS;
|
||||
|
||||
Direction face = pHit.getDirection();
|
||||
ItemStack itemInHand = pPlayer.getItemInHand(pHand);
|
||||
BlockState material = getAcceptedBlockState(pLevel, pPos, itemInHand, face);
|
||||
|
||||
if (material == null)
|
||||
return InteractionResult.PASS;
|
||||
|
||||
return onTileEntityUse(pLevel, pPos, ufte -> {
|
||||
if (ufte.getMaterial()
|
||||
.is(material.getBlock())) {
|
||||
if (!ufte.cycleMaterial())
|
||||
return InteractionResult.PASS;
|
||||
ufte.getLevel()
|
||||
.playSound(null, ufte.getBlockPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .75f,
|
||||
.95f);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
if (ufte.hasCustomMaterial())
|
||||
return InteractionResult.PASS;
|
||||
if (pLevel.isClientSide())
|
||||
return InteractionResult.SUCCESS;
|
||||
|
||||
ufte.setMaterial(material);
|
||||
ufte.setItem(itemInHand);
|
||||
ufte.getLevel()
|
||||
.playSound(null, ufte.getBlockPos(), material.getSoundType()
|
||||
.getPlaceSound(), SoundSource.BLOCKS, 1, .75f);
|
||||
|
||||
if (pPlayer.isCreative())
|
||||
return InteractionResult.SUCCESS;
|
||||
|
||||
itemInHand.shrink(1);
|
||||
if (itemInHand.isEmpty())
|
||||
pPlayer.setItemInHand(pHand, ItemStack.EMPTY);
|
||||
return InteractionResult.SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) {
|
||||
if (pPlacer == null)
|
||||
return;
|
||||
ItemStack offhandItem = pPlacer.getItemInHand(InteractionHand.OFF_HAND);
|
||||
BlockState appliedState =
|
||||
getAcceptedBlockState(pLevel, pPos, offhandItem, Direction.orderedByNearest(pPlacer)[0]);
|
||||
|
||||
if (appliedState == null)
|
||||
return;
|
||||
withTileEntityDo(pLevel, pPos, ufte -> {
|
||||
if (ufte.hasCustomMaterial())
|
||||
return;
|
||||
|
||||
ufte.setMaterial(appliedState);
|
||||
ufte.setItem(offhandItem);
|
||||
|
||||
if (pPlacer instanceof Player player && player.isCreative())
|
||||
return;
|
||||
offhandItem.shrink(1);
|
||||
if (offhandItem.isEmpty())
|
||||
pPlacer.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY);
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BlockState getAcceptedBlockState(Level pLevel, BlockPos pPos, ItemStack item, Direction face) {
|
||||
if (!(item.getItem()instanceof BlockItem bi))
|
||||
return null;
|
||||
|
||||
Block block = bi.getBlock();
|
||||
if (block instanceof CopycatBlock)
|
||||
return null;
|
||||
if (AllBlockTags.COPYCAT_DENY.matches(block))
|
||||
return null;
|
||||
|
||||
BlockState appliedState = block.defaultBlockState();
|
||||
|
||||
if (!AllBlockTags.COPYCAT_ALLOW.matches(block)) {
|
||||
if (block instanceof EntityBlock)
|
||||
return null;
|
||||
if (block instanceof StairBlock)
|
||||
return null;
|
||||
|
||||
VoxelShape shape = appliedState.getShape(pLevel, pPos);
|
||||
if (shape.isEmpty() || !shape.bounds()
|
||||
.equals(Shapes.block()
|
||||
.bounds()))
|
||||
return null;
|
||||
|
||||
VoxelShape collisionShape = appliedState.getCollisionShape(pLevel, pPos);
|
||||
if (collisionShape.isEmpty())
|
||||
return null;
|
||||
}
|
||||
|
||||
if (face != null) {
|
||||
Axis axis = face.getAxis();
|
||||
|
||||
if (appliedState.hasProperty(BlockStateProperties.FACING))
|
||||
appliedState = appliedState.setValue(BlockStateProperties.FACING, face);
|
||||
if (appliedState.hasProperty(BlockStateProperties.HORIZONTAL_FACING) && axis != Axis.Y)
|
||||
appliedState = appliedState.setValue(BlockStateProperties.HORIZONTAL_FACING, face);
|
||||
if (appliedState.hasProperty(BlockStateProperties.AXIS))
|
||||
appliedState = appliedState.setValue(BlockStateProperties.AXIS, axis);
|
||||
if (appliedState.hasProperty(BlockStateProperties.HORIZONTAL_AXIS) && axis != Axis.Y)
|
||||
appliedState = appliedState.setValue(BlockStateProperties.HORIZONTAL_AXIS, axis);
|
||||
}
|
||||
|
||||
return appliedState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
|
||||
if (!pState.hasBlockEntity() || pState.getBlock() == pNewState.getBlock())
|
||||
return;
|
||||
if (!pIsMoving)
|
||||
withTileEntityDo(pLevel, pPos, ufte -> Block.popResource(pLevel, pPos, ufte.getConsumedItem()));
|
||||
pLevel.removeBlockEntity(pPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) {
|
||||
super.playerWillDestroy(pLevel, pPos, pState, pPlayer);
|
||||
if (pPlayer.isCreative())
|
||||
withTileEntityDo(pLevel, pPos, ufte -> ufte.setItem(ItemStack.EMPTY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<CopycatTileEntity> getTileEntityClass() {
|
||||
return CopycatTileEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends CopycatTileEntity> getTileEntityType() {
|
||||
return AllTileEntities.UNIVERSAL_FRAME.get();
|
||||
}
|
||||
|
||||
// Connected Textures
|
||||
|
||||
@Nullable
|
||||
/**
|
||||
* The wrapped blockstate at toPos. Wrapper guaranteed to be a block of this
|
||||
* type <br>
|
||||
* Return null if the 'from' state shouldn't connect to this block/face
|
||||
*
|
||||
* @param from
|
||||
* @param reader
|
||||
* @param targetPos
|
||||
* @param face
|
||||
* @return
|
||||
*/
|
||||
public abstract BlockState getConnectiveMaterial(BlockAndTintGetter reader, BlockState otherState, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos);
|
||||
|
||||
public boolean isUnblockableConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static BlockState getMaterial(BlockGetter reader, BlockPos targetPos) {
|
||||
if (reader.getBlockEntity(targetPos)instanceof CopycatTileEntity ufte)
|
||||
return ufte.getMaterial();
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
|
||||
public boolean canFaceBeOccluded(BlockState state, Direction face) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wrapped properties
|
||||
|
||||
@Override
|
||||
public SoundType getSoundType(BlockState state, LevelReader level, BlockPos pos, Entity entity) {
|
||||
return getMaterial(level, pos).getSoundType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFriction(BlockState state, LevelReader level, BlockPos pos, Entity entity) {
|
||||
return getMaterial(level, pos).getFriction(level, pos, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) {
|
||||
return getMaterial(level, pos).getLightEmission(level, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHarvestBlock(BlockState state, BlockGetter level, BlockPos pos, Player player) {
|
||||
return getMaterial(level, pos).canHarvestBlock(level, pos, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getExplosionResistance(BlockState state, BlockGetter level, BlockPos pos, Explosion explosion) {
|
||||
return getMaterial(level, pos).getExplosionResistance(level, pos, explosion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos,
|
||||
Player player) {
|
||||
BlockState material = getMaterial(level, pos);
|
||||
if (AllBlocks.COPYCAT_BASE.has(material))
|
||||
return new ItemStack(this);
|
||||
return material.getCloneItemStack(target, level, pos, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addLandingEffects(BlockState state1, ServerLevel level, BlockPos pos, BlockState state2,
|
||||
LivingEntity entity, int numberOfParticles) {
|
||||
return getMaterial(level, pos).addLandingEffects(level, pos, state2, entity, numberOfParticles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addRunningEffects(BlockState state, Level level, BlockPos pos, Entity entity) {
|
||||
return getMaterial(level, pos).addRunningEffects(level, pos, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) {
|
||||
return getMaterial(level, pos).getEnchantPowerBonus(level, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEntityDestroy(BlockState state, BlockGetter level, BlockPos pos, Entity entity) {
|
||||
return getMaterial(level, pos).canEntityDestroy(level, pos, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidSpawn(BlockState state, BlockGetter level, BlockPos pos, Type type,
|
||||
EntityType<?> entityType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fallOn(Level pLevel, BlockState pState, BlockPos pPos, Entity pEntity, float p_152430_) {
|
||||
BlockState material = getMaterial(pLevel, pPos);
|
||||
material.getBlock()
|
||||
.fallOn(pLevel, material, pPos, pEntity, p_152430_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDestroyProgress(BlockState pState, Player pPlayer, BlockGetter pLevel, BlockPos pPos) {
|
||||
return getMaterial(pLevel, pPos).getDestroyProgress(pPlayer, pLevel, pPos);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static BlockColor wrappedColor() {
|
||||
return new WrappedBlockColor();
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static class WrappedBlockColor implements BlockColor {
|
||||
|
||||
@Override
|
||||
public int getColor(BlockState pState, @Nullable BlockAndTintGetter pLevel, @Nullable BlockPos pPos,
|
||||
int pTintIndex) {
|
||||
if (pLevel == null || pPos == null)
|
||||
return GrassColor.get(0.5D, 1.0D);
|
||||
return Minecraft.getInstance()
|
||||
.getBlockColors()
|
||||
.getColor(getMaterial(pLevel, pPos), pLevel, pPos, pTintIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
package com.simibubi.create.content.curiosities.frames;
|
||||
|
||||
import static com.simibubi.create.content.curiosities.frames.CopycatTileEntity.MATERIAL_PROPERTY;
|
||||
import static com.simibubi.create.foundation.block.render.SpriteShiftEntry.getUnInterpolatedU;
|
||||
import static com.simibubi.create.foundation.block.render.SpriteShiftEntry.getUnInterpolatedV;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.foundation.block.connected.BakedModelWrapperWithData;
|
||||
import com.simibubi.create.foundation.block.render.QuadHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.client.MinecraftForgeClient;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap.Builder;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
public abstract class CopycatModel extends BakedModelWrapperWithData {
|
||||
|
||||
private static final ModelProperty<IModelData> WRAPPED_DATA_PROPERTY = new ModelProperty<>();
|
||||
private static final ModelProperty<OcclusionData> OCCLUSION_PROPERTY = new ModelProperty<>();
|
||||
|
||||
public CopycatModel(BakedModel originalModel) {
|
||||
super(originalModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state,
|
||||
IModelData tileData) {
|
||||
BlockState wrappedState = getMaterial(world, pos, state);
|
||||
|
||||
if (wrappedState == null)
|
||||
return builder;
|
||||
if (tileData instanceof ModelDataMap mdm && mdm.hasProperty(MATERIAL_PROPERTY))
|
||||
builder.withInitial(MATERIAL_PROPERTY, mdm.getData(MATERIAL_PROPERTY));
|
||||
|
||||
OcclusionData occlusionData = new OcclusionData();
|
||||
if (state.getBlock()instanceof CopycatBlock ufb) {
|
||||
MutableBlockPos mutablePos = new MutableBlockPos();
|
||||
for (Direction face : Iterate.directions)
|
||||
if (ufb.canFaceBeOccluded(state, face))
|
||||
if (!Block.shouldRenderFace(wrappedState, world, pos, face, mutablePos.setWithOffset(pos, face)))
|
||||
occlusionData.occlude(face);
|
||||
builder.withInitial(OCCLUSION_PROPERTY, occlusionData);
|
||||
}
|
||||
|
||||
IModelData modelData = getModelOf(wrappedState).getModelData(world, pos, wrappedState, EmptyModelData.INSTANCE);
|
||||
return builder.withInitial(WRAPPED_DATA_PROPERTY, modelData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(BlockState state, Direction side, Random rand, IModelData extraData) {
|
||||
List<BakedQuad> quads = super.getQuads(state, side, rand, extraData);
|
||||
|
||||
BlockState material = getMaterial(extraData);
|
||||
IModelData wrappedData = extraData.getData(WRAPPED_DATA_PROPERTY);
|
||||
|
||||
if (material == null)
|
||||
return quads;
|
||||
|
||||
RenderType renderType = MinecraftForgeClient.getRenderType();
|
||||
if (renderType != null && !ItemBlockRenderTypes.canRenderInLayer(material, renderType))
|
||||
return quads;
|
||||
if (wrappedData == null)
|
||||
wrappedData = EmptyModelData.INSTANCE;
|
||||
|
||||
OcclusionData occlusionData = extraData.getData(OCCLUSION_PROPERTY);
|
||||
if (occlusionData != null && occlusionData.isOccluded(side))
|
||||
return quads;
|
||||
|
||||
return getCroppedQuads(state, side, rand, material, wrappedData);
|
||||
}
|
||||
|
||||
protected abstract List<BakedQuad> getCroppedQuads(BlockState state, Direction side, Random rand,
|
||||
BlockState material, IModelData wrappedData);
|
||||
|
||||
public static boolean cropAndMove(BakedQuad quad, AABB crop, Vec3 move) {
|
||||
int[] vertexData = quad.getVertices();
|
||||
|
||||
Vec3 xyz0 = QuadHelper.getXYZ(vertexData, 0);
|
||||
Vec3 xyz1 = QuadHelper.getXYZ(vertexData, 1);
|
||||
Vec3 xyz2 = QuadHelper.getXYZ(vertexData, 2);
|
||||
Vec3 xyz3 = QuadHelper.getXYZ(vertexData, 3);
|
||||
|
||||
Vec3 uAxis = xyz3.add(xyz2)
|
||||
.scale(.5);
|
||||
Vec3 vAxis = xyz1.add(xyz2)
|
||||
.scale(.5);
|
||||
Vec3 center = xyz3.add(xyz2)
|
||||
.add(xyz0)
|
||||
.add(xyz1)
|
||||
.scale(.25);
|
||||
|
||||
float u0 = QuadHelper.getU(vertexData, 0);
|
||||
float u3 = QuadHelper.getU(vertexData, 3);
|
||||
float v0 = QuadHelper.getV(vertexData, 0);
|
||||
float v1 = QuadHelper.getV(vertexData, 1);
|
||||
|
||||
TextureAtlasSprite sprite = quad.getSprite();
|
||||
|
||||
float uScale = (float) Math
|
||||
.round((getUnInterpolatedU(sprite, u3) - getUnInterpolatedU(sprite, u0)) / xyz3.distanceTo(xyz0));
|
||||
float vScale = (float) Math
|
||||
.round((getUnInterpolatedV(sprite, v1) - getUnInterpolatedV(sprite, v0)) / xyz1.distanceTo(xyz0));
|
||||
|
||||
if (uScale == 0) {
|
||||
float v3 = QuadHelper.getV(vertexData, 3);
|
||||
float u1 = QuadHelper.getU(vertexData, 1);
|
||||
uAxis = xyz1.add(xyz2)
|
||||
.scale(.5);
|
||||
vAxis = xyz3.add(xyz2)
|
||||
.scale(.5);
|
||||
uScale = (float) Math
|
||||
.round((getUnInterpolatedU(sprite, u1) - getUnInterpolatedU(sprite, u0)) / xyz1.distanceTo(xyz0));
|
||||
vScale = (float) Math
|
||||
.round((getUnInterpolatedV(sprite, v3) - getUnInterpolatedV(sprite, v0)) / xyz3.distanceTo(xyz0));
|
||||
|
||||
}
|
||||
|
||||
uAxis = uAxis.subtract(center)
|
||||
.normalize();
|
||||
vAxis = vAxis.subtract(center)
|
||||
.normalize();
|
||||
|
||||
Vec3 min = new Vec3(crop.minX, crop.minY, crop.minZ);
|
||||
Vec3 max = new Vec3(crop.maxX, crop.maxY, crop.maxZ);
|
||||
|
||||
for (int vertex = 0; vertex < 4; vertex++) {
|
||||
Vec3 xyz = QuadHelper.getXYZ(vertexData, vertex);
|
||||
Vec3 newXyz = VecHelper.componentMin(max, VecHelper.componentMax(xyz, min));
|
||||
Vec3 diff = newXyz.subtract(xyz);
|
||||
|
||||
if (diff.lengthSqr() > 0) {
|
||||
float u = QuadHelper.getU(vertexData, vertex);
|
||||
float v = QuadHelper.getV(vertexData, vertex);
|
||||
float uDiff = (float) uAxis.dot(diff) * uScale;
|
||||
float vDiff = (float) vAxis.dot(diff) * vScale;
|
||||
QuadHelper.setU(vertexData, vertex, sprite.getU(getUnInterpolatedU(sprite, u) + uDiff));
|
||||
QuadHelper.setV(vertexData, vertex, sprite.getV(getUnInterpolatedV(sprite, v) + vDiff));
|
||||
}
|
||||
|
||||
QuadHelper.setXYZ(vertexData, vertex, newXyz.add(move));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleIcon(IModelData data) {
|
||||
BlockState material = getMaterial(data);
|
||||
IModelData wrappedData = data.getData(WRAPPED_DATA_PROPERTY);
|
||||
|
||||
if (wrappedData == null)
|
||||
wrappedData = EmptyModelData.INSTANCE;
|
||||
if (material != null)
|
||||
return getModelOf(material).getParticleIcon(wrappedData);
|
||||
|
||||
return super.getParticleIcon(data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockState getMaterial(IModelData extraData) {
|
||||
BlockState material = extraData.getData(MATERIAL_PROPERTY);
|
||||
return material == null ? AllBlocks.COPYCAT_BASE.getDefaultState() : material;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockState getMaterial(BlockAndTintGetter world, BlockPos pos, BlockState state) {
|
||||
if (!(state.getBlock()instanceof CopycatBlock ufb))
|
||||
return null;
|
||||
return ufb.getTileEntityOptional(world, pos)
|
||||
.map(CopycatTileEntity::getMaterial)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public BakedModel getModelOf(BlockState wrappedState) {
|
||||
return Minecraft.getInstance()
|
||||
.getBlockRenderer()
|
||||
.getBlockModel(wrappedState);
|
||||
}
|
||||
|
||||
private static class OcclusionData {
|
||||
private final boolean[] occluded;
|
||||
|
||||
public OcclusionData() {
|
||||
occluded = new boolean[6];
|
||||
Arrays.fill(occluded, false);
|
||||
}
|
||||
|
||||
public void occlude(Direction face) {
|
||||
occluded[face.get3DDataValue()] = true;
|
||||
}
|
||||
|
||||
public boolean isOccluded(Direction face) {
|
||||
return face == null ? false : occluded[face.get3DDataValue()];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
package com.simibubi.create.content.curiosities.frames;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
||||
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
||||
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class CopycatPanelBlock extends WaterloggedCopycatBlock {
|
||||
|
||||
public static final DirectionProperty FACING = BlockStateProperties.FACING;
|
||||
|
||||
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
|
||||
|
||||
public CopycatPanelBlock(Properties pProperties) {
|
||||
super(pProperties);
|
||||
registerDefaultState(defaultBlockState().setValue(FACING, Direction.UP));
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
|
||||
BlockHitResult ray) {
|
||||
|
||||
if (!player.isShiftKeyDown() && player.mayBuild()) {
|
||||
ItemStack heldItem = player.getItemInHand(hand);
|
||||
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
|
||||
if (placementHelper.matchesItem(heldItem)) {
|
||||
placementHelper.getOffset(player, world, state, pos, ray)
|
||||
.placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return super.use(state, world, pos, player, hand, ray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnblockableConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos) {
|
||||
Direction facing = state.getValue(FACING);
|
||||
BlockState toState = reader.getBlockState(toPos);
|
||||
|
||||
if (!toState.is(this))
|
||||
return facing != face.getOpposite();
|
||||
|
||||
BlockPos diff = fromPos.subtract(toPos);
|
||||
int coord = facing.getAxis()
|
||||
.choose(diff.getX(), diff.getY(), diff.getZ());
|
||||
return facing == toState.getValue(FACING)
|
||||
.getOpposite()
|
||||
&& !(coord != 0 && coord == facing.getAxisDirection()
|
||||
.getStep());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFaceBeOccluded(BlockState state, Direction face) {
|
||||
return state.getValue(FACING)
|
||||
.getOpposite() == face;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getConnectiveMaterial(BlockAndTintGetter reader, BlockState otherState, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos) {
|
||||
BlockState panelState = reader.getBlockState(toPos);
|
||||
Direction facing = panelState.getValue(FACING);
|
||||
|
||||
if (!otherState.is(this))
|
||||
return facing == face.getOpposite() ? getMaterial(reader, toPos) : null;
|
||||
|
||||
if (isOccluded(panelState, otherState, facing))
|
||||
return getMaterial(reader, toPos);
|
||||
|
||||
BlockPos diff = fromPos.subtract(toPos);
|
||||
int coord = facing.getAxis()
|
||||
.choose(diff.getX(), diff.getY(), diff.getZ());
|
||||
|
||||
if (otherState.setValue(WATERLOGGED, false) == panelState.setValue(WATERLOGGED, false) && coord == 0)
|
||||
return getMaterial(reader, toPos);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
BlockState stateForPlacement = super.getStateForPlacement(pContext);
|
||||
return stateForPlacement.setValue(FACING, pContext.getNearestLookingDirection()
|
||||
.getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(Builder<Block, BlockState> pBuilder) {
|
||||
super.createBlockStateDefinition(pBuilder.add(FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
return AllShapes.CASING_3PX.get(pState.getValue(FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsExternalFaceHiding(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hidesNeighborFace(BlockGetter level, BlockPos pos, BlockState state, BlockState neighborState,
|
||||
Direction dir) {
|
||||
if (state.is(this) == neighborState.is(this)
|
||||
&& getMaterial(level, pos).skipRendering(getMaterial(level, pos.relative(dir)), dir.getOpposite()))
|
||||
return isOccluded(state, neighborState, dir.getOpposite());
|
||||
return state.getValue(FACING) == dir.getOpposite()
|
||||
&& getMaterial(level, pos).skipRendering(neighborState, dir.getOpposite());
|
||||
}
|
||||
|
||||
public static boolean isOccluded(BlockState state, BlockState other, Direction pDirection) {
|
||||
state = state.setValue(WATERLOGGED, false);
|
||||
other = other.setValue(WATERLOGGED, false);
|
||||
Direction facing = state.getValue(FACING);
|
||||
if (facing.getOpposite() == other.getValue(FACING) && pDirection == facing)
|
||||
return true;
|
||||
if (other.getValue(FACING) != facing)
|
||||
return false;
|
||||
return pDirection.getAxis() != facing.getAxis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState rotate(BlockState state, Rotation rot) {
|
||||
return state.setValue(FACING, rot.rotate(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public BlockState mirror(BlockState state, Mirror mirrorIn) {
|
||||
return state.rotate(mirrorIn.getRotation(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
private static class PlacementHelper implements IPlacementHelper {
|
||||
@Override
|
||||
public Predicate<ItemStack> getItemPredicate() {
|
||||
return AllBlocks.COPYCAT_PANEL::isIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<BlockState> getStatePredicate() {
|
||||
return AllBlocks.COPYCAT_PANEL::has;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
|
||||
BlockHitResult ray) {
|
||||
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(),
|
||||
state.getValue(FACING)
|
||||
.getAxis(),
|
||||
dir -> world.getBlockState(pos.relative(dir))
|
||||
.getMaterial()
|
||||
.isReplaceable());
|
||||
|
||||
if (directions.isEmpty())
|
||||
return PlacementOffset.fail();
|
||||
else {
|
||||
return PlacementOffset.success(pos.relative(directions.get(0)),
|
||||
s -> s.setValue(FACING, state.getValue(FACING)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.simibubi.create.content.curiosities.frames;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.foundation.block.render.QuadHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
public class CopycatPanelModel extends CopycatModel {
|
||||
|
||||
public CopycatPanelModel(BakedModel originalModel) {
|
||||
super(originalModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<BakedQuad> getCroppedQuads(BlockState state, Direction side, Random rand, BlockState material,
|
||||
IModelData wrappedData) {
|
||||
Direction facing = state.getOptionalValue(CopycatPanelBlock.FACING)
|
||||
.orElse(Direction.UP);
|
||||
|
||||
Vec3 normal = Vec3.atLowerCornerOf(facing.getNormal());
|
||||
AABB cube = new AABB(BlockPos.ZERO);
|
||||
|
||||
BakedModel model = getModelOf(material);
|
||||
List<BakedQuad> templateQuads = model.getQuads(material, side, rand, wrappedData);
|
||||
int size = templateQuads.size();
|
||||
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
|
||||
// 2 Pieces
|
||||
for (boolean front : Iterate.trueAndFalse) {
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
BakedQuad quad = templateQuads.get(i);
|
||||
Direction direction = quad.getDirection();
|
||||
|
||||
if (front && direction == facing)
|
||||
continue;
|
||||
if (!front && direction == facing.getOpposite())
|
||||
continue;
|
||||
|
||||
float contract = 16 - (front ? 1 : 2);
|
||||
AABB bb = cube.contract(normal.x * contract / 16, normal.y * contract / 16, normal.z * contract / 16);
|
||||
|
||||
if (!front)
|
||||
bb = bb.move(normal.scale(14 / 16f));
|
||||
|
||||
BakedQuad newQuad = QuadHelper.clone(quad);
|
||||
if (cropAndMove(newQuad, bb, normal.scale(front ? 0 : -13 / 16f)));
|
||||
quads.add(newQuad);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return quads;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
package com.simibubi.create.content.curiosities.frames;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.content.curiosities.tools.ExtendoGripItem;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VoxelShaper;
|
||||
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
||||
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
||||
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.block.state.properties.Half;
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
|
||||
public class CopycatStepBlock extends WaterloggedCopycatBlock {
|
||||
|
||||
public static EnumProperty<Half> HALF = BlockStateProperties.HALF;
|
||||
public static DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
||||
|
||||
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
|
||||
|
||||
public CopycatStepBlock(Properties pProperties) {
|
||||
super(pProperties);
|
||||
registerDefaultState(defaultBlockState().setValue(HALF, Half.BOTTOM)
|
||||
.setValue(FACING, Direction.SOUTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
|
||||
BlockHitResult ray) {
|
||||
|
||||
if (!player.isShiftKeyDown() && player.mayBuild()) {
|
||||
ItemStack heldItem = player.getItemInHand(hand);
|
||||
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
|
||||
if (helper.matchesItem(heldItem))
|
||||
return helper.getOffset(player, world, state, pos, ray)
|
||||
.placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
|
||||
}
|
||||
|
||||
return super.use(state, world, pos, player, hand, ray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getConnectiveMaterial(BlockAndTintGetter reader, BlockState otherState, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos) {
|
||||
if (!otherState.is(this))
|
||||
return null;
|
||||
|
||||
BlockState stepState = reader.getBlockState(toPos);
|
||||
Direction facing = stepState.getValue(FACING);
|
||||
BlockPos diff = fromPos.subtract(toPos);
|
||||
|
||||
if (diff.getY() != 0) {
|
||||
if (isOccluded(stepState, otherState, diff.getY() > 0 ? Direction.UP : Direction.DOWN))
|
||||
return getMaterial(reader, toPos);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isOccluded(stepState, otherState, facing))
|
||||
return getMaterial(reader, toPos);
|
||||
|
||||
int coord = facing.getAxis()
|
||||
.choose(diff.getX(), diff.getY(), diff.getZ());
|
||||
|
||||
if (otherState.setValue(WATERLOGGED, false) == stepState.setValue(WATERLOGGED, false) && coord == 0)
|
||||
return getMaterial(reader, toPos);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnblockableConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
|
||||
BlockPos fromPos, BlockPos toPos) {
|
||||
BlockState toState = reader.getBlockState(toPos);
|
||||
|
||||
if (!toState.is(this)) {
|
||||
if (!canFaceBeOccluded(state, face.getOpposite()))
|
||||
return true;
|
||||
for (Direction d : Iterate.directions)
|
||||
if (fromPos.relative(d)
|
||||
.equals(toPos) && !canFaceBeOccluded(state, d))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Direction facing = state.getValue(FACING);
|
||||
BlockPos diff = fromPos.subtract(toPos);
|
||||
int coord = facing.getAxis()
|
||||
.choose(diff.getX(), diff.getY(), diff.getZ());
|
||||
|
||||
Half half = state.getValue(HALF);
|
||||
if (half != toState.getValue(HALF))
|
||||
return diff.getY() == 0;
|
||||
|
||||
return facing == toState.getValue(FACING)
|
||||
.getOpposite()
|
||||
&& !(coord != 0 && coord != facing.getAxisDirection()
|
||||
.getStep());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFaceBeOccluded(BlockState state, Direction face) {
|
||||
if (face.getAxis() == Axis.Y)
|
||||
return (state.getValue(HALF) == Half.TOP) == (face == Direction.UP);
|
||||
return state.getValue(FACING) == face;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
BlockState stateForPlacement =
|
||||
super.getStateForPlacement(pContext).setValue(FACING, pContext.getHorizontalDirection());
|
||||
Direction direction = pContext.getClickedFace();
|
||||
if (direction == Direction.UP)
|
||||
return stateForPlacement;
|
||||
if (direction == Direction.DOWN || (pContext.getClickLocation().y - pContext.getClickedPos()
|
||||
.getY() > 0.5D))
|
||||
return stateForPlacement.setValue(HALF, Half.TOP);
|
||||
return stateForPlacement;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(Builder<Block, BlockState> pBuilder) {
|
||||
super.createBlockStateDefinition(pBuilder.add(HALF, FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
VoxelShaper voxelShaper = pState.getValue(HALF) == Half.BOTTOM ? AllShapes.STEP_BOTTOM : AllShapes.STEP_TOP;
|
||||
return voxelShaper.get(pState.getValue(FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsExternalFaceHiding(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hidesNeighborFace(BlockGetter level, BlockPos pos, BlockState state, BlockState neighborState,
|
||||
Direction dir) {
|
||||
if (state.is(this) == neighborState.is(this)
|
||||
&& getMaterial(level, pos).skipRendering(getMaterial(level, pos.relative(dir)), dir.getOpposite()))
|
||||
return isOccluded(state, neighborState, dir);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isOccluded(BlockState state, BlockState other, Direction pDirection) {
|
||||
state = state.setValue(WATERLOGGED, false);
|
||||
other = other.setValue(WATERLOGGED, false);
|
||||
|
||||
Half half = state.getValue(HALF);
|
||||
boolean vertical = pDirection.getAxis() == Axis.Y;
|
||||
if (half != other.getValue(HALF))
|
||||
return vertical && (pDirection == Direction.UP) == (half == Half.TOP);
|
||||
if (vertical)
|
||||
return false;
|
||||
|
||||
Direction facing = state.getValue(FACING);
|
||||
if (facing.getOpposite() == other.getValue(FACING) && pDirection == facing)
|
||||
return true;
|
||||
if (other.getValue(FACING) != facing)
|
||||
return false;
|
||||
return pDirection.getAxis() != facing.getAxis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState rotate(BlockState pState, Rotation pRot) {
|
||||
return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public BlockState mirror(BlockState pState, Mirror pMirror) {
|
||||
return pState.rotate(pMirror.getRotation(pState.getValue(FACING)));
|
||||
}
|
||||
|
||||
private static class PlacementHelper implements IPlacementHelper {
|
||||
|
||||
@Override
|
||||
public Predicate<ItemStack> getItemPredicate() {
|
||||
return AllBlocks.COPYCAT_STEP::isIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<BlockState> getStatePredicate() {
|
||||
return AllBlocks.COPYCAT_STEP::has;
|
||||
}
|
||||
|
||||
public int attachedSteps(Level world, BlockPos pos, Direction direction) {
|
||||
BlockPos checkPos = pos.relative(direction);
|
||||
BlockState state = world.getBlockState(checkPos);
|
||||
int count = 0;
|
||||
while (getStatePredicate().test(state)) {
|
||||
count++;
|
||||
checkPos = checkPos.relative(direction);
|
||||
state = world.getBlockState(checkPos);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
|
||||
BlockHitResult ray) {
|
||||
|
||||
Direction dir = null;
|
||||
Direction facing = state.getValue(FACING);
|
||||
|
||||
for (Direction nearest : Direction.orderedByNearest(player)) {
|
||||
if (nearest.getAxis() != facing.getClockWise()
|
||||
.getAxis())
|
||||
continue;
|
||||
dir = nearest;
|
||||
break;
|
||||
}
|
||||
|
||||
int range = AllConfigs.SERVER.curiosities.placementAssistRange.get();
|
||||
if (player != null) {
|
||||
AttributeInstance reach = player.getAttribute(ForgeMod.REACH_DISTANCE.get());
|
||||
if (reach != null && reach.hasModifier(ExtendoGripItem.singleRangeAttributeModifier))
|
||||
range += 4;
|
||||
}
|
||||
|
||||
int row = attachedSteps(world, pos, dir);
|
||||
if (row >= range)
|
||||
return PlacementOffset.fail();
|
||||
|
||||
BlockPos newPos = pos.relative(dir, row + 1);
|
||||
BlockState newState = world.getBlockState(newPos);
|
||||
|
||||
if (!state.canSurvive(world, newPos))
|
||||
return PlacementOffset.fail();
|
||||
|
||||
if (newState.getMaterial()
|
||||
.isReplaceable())
|
||||
return PlacementOffset.success(newPos, bState -> {
|
||||
return bState.setValue(FACING, facing)
|
||||
.setValue(HALF, state.getValue(HALF));
|
||||
});
|
||||
return PlacementOffset.fail();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package com.simibubi.create.content.curiosities.frames;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.foundation.block.render.QuadHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Half;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
public class CopycatStepModel extends CopycatModel {
|
||||
|
||||
public CopycatStepModel(BakedModel originalModel) {
|
||||
super(originalModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<BakedQuad> getCroppedQuads(BlockState state, Direction side, Random rand, BlockState material,
|
||||
IModelData wrappedData) {
|
||||
Direction facing = state.getOptionalValue(CopycatStepBlock.FACING)
|
||||
.orElse(Direction.SOUTH);
|
||||
boolean upperHalf = state.getOptionalValue(CopycatStepBlock.HALF)
|
||||
.orElse(Half.BOTTOM) == Half.TOP;
|
||||
|
||||
Vec3 zero = Vec3.ZERO;
|
||||
Vec3 up = new Vec3(0, 1, 0);
|
||||
Vec3 normal = Vec3.atLowerCornerOf(facing.getNormal());
|
||||
|
||||
BakedModel model = getModelOf(material);
|
||||
List<BakedQuad> templateQuads = model.getQuads(material, side, rand, wrappedData);
|
||||
int size = templateQuads.size();
|
||||
AABB cube = new AABB(BlockPos.ZERO);
|
||||
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
|
||||
// 4 Pieces
|
||||
for (boolean top : Iterate.trueAndFalse) {
|
||||
for (boolean front : Iterate.trueAndFalse) {
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
BakedQuad quad = templateQuads.get(i);
|
||||
Direction direction = quad.getDirection();
|
||||
|
||||
if (front && direction == facing)
|
||||
continue;
|
||||
if (!front && direction == facing.getOpposite())
|
||||
continue;
|
||||
if (!top && direction == Direction.UP)
|
||||
continue;
|
||||
if (top && direction == Direction.DOWN)
|
||||
continue;
|
||||
|
||||
AABB bb = cube.contract(-normal.x * .75, .75, -normal.z * .75);
|
||||
|
||||
if (front)
|
||||
bb = bb.move(normal.scale(-.75));
|
||||
if (top)
|
||||
bb = bb.move(up.scale(.75));
|
||||
|
||||
Vec3 offset = zero;
|
||||
|
||||
if (front)
|
||||
offset = offset.add(normal.scale(.5));
|
||||
if (top != upperHalf)
|
||||
offset = offset.add(up.scale(upperHalf ? .5 : -.5));
|
||||
|
||||
BakedQuad newQuad = QuadHelper.clone(quad);
|
||||
if (cropAndMove(newQuad, bb, offset))
|
||||
quads.add(newQuad);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return quads;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
package com.simibubi.create.content.curiosities.frames;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||
import com.simibubi.create.content.logistics.block.redstone.RoseQuartzLampBlock;
|
||||
import com.simibubi.create.content.schematics.ISpecialBlockEntityItemRequirement;
|
||||
import com.simibubi.create.content.schematics.ItemRequirement;
|
||||
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
public class CopycatTileEntity extends SmartTileEntity implements ISpecialBlockEntityItemRequirement, ITransformableTE {
|
||||
|
||||
ItemStack consumedItem;
|
||||
BlockState baseBlock;
|
||||
|
||||
public CopycatTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
baseBlock = AllBlocks.COPYCAT_BASE.getDefaultState();
|
||||
consumedItem = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
public void setItem(ItemStack item) {
|
||||
consumedItem = ItemHandlerHelper.copyStackWithSize(item, 1);
|
||||
setChanged();
|
||||
}
|
||||
|
||||
public ItemStack getConsumedItem() {
|
||||
return consumedItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemRequirement getRequiredItems(BlockState state) {
|
||||
if (consumedItem.isEmpty())
|
||||
return ItemRequirement.NONE;
|
||||
return new ItemRequirement(ItemUseType.CONSUME, consumedItem);
|
||||
}
|
||||
|
||||
public void setMaterial(BlockState blockState) {
|
||||
BlockState wrapperState = getBlockState();
|
||||
|
||||
if (!baseBlock.is(blockState.getBlock()))
|
||||
for (Direction side : Iterate.directions) {
|
||||
BlockPos neighbour = worldPosition.relative(side);
|
||||
BlockState neighbourState = level.getBlockState(neighbour);
|
||||
if (neighbourState != wrapperState)
|
||||
continue;
|
||||
if (!(level.getBlockEntity(neighbour)instanceof CopycatTileEntity ufte))
|
||||
continue;
|
||||
BlockState otherMaterial = ufte.getMaterial();
|
||||
if (!otherMaterial.is(blockState.getBlock()))
|
||||
continue;
|
||||
blockState = otherMaterial;
|
||||
break;
|
||||
}
|
||||
|
||||
baseBlock = blockState;
|
||||
if (!level.isClientSide()) {
|
||||
notifyUpdate();
|
||||
return;
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
public boolean hasCustomMaterial() {
|
||||
return !AllBlocks.COPYCAT_BASE.has(getMaterial());
|
||||
}
|
||||
|
||||
public BlockState getMaterial() {
|
||||
return baseBlock;
|
||||
}
|
||||
|
||||
public boolean cycleMaterial() {
|
||||
if (baseBlock.hasProperty(BlockStateProperties.FACING))
|
||||
setMaterial(baseBlock.cycle(BlockStateProperties.FACING));
|
||||
else if (baseBlock.hasProperty(BlockStateProperties.HORIZONTAL_FACING))
|
||||
setMaterial(baseBlock.cycle(BlockStateProperties.HORIZONTAL_FACING));
|
||||
else if (baseBlock.hasProperty(BlockStateProperties.AXIS))
|
||||
setMaterial(baseBlock.cycle(BlockStateProperties.AXIS));
|
||||
else if (baseBlock.hasProperty(BlockStateProperties.HORIZONTAL_AXIS))
|
||||
setMaterial(baseBlock.cycle(BlockStateProperties.HORIZONTAL_AXIS));
|
||||
else if (baseBlock.hasProperty(BlockStateProperties.LIT))
|
||||
setMaterial(baseBlock.cycle(BlockStateProperties.LIT));
|
||||
else if (baseBlock.hasProperty(RoseQuartzLampBlock.POWERING))
|
||||
setMaterial(baseBlock.cycle(RoseQuartzLampBlock.POWERING));
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||
super.read(tag, clientPacket);
|
||||
|
||||
consumedItem = ItemStack.of(tag.getCompound("Item"));
|
||||
|
||||
BlockState prevMaterial = baseBlock;
|
||||
if (!tag.contains("Material"))
|
||||
return;
|
||||
|
||||
JsonOps ops = JsonOps.INSTANCE;
|
||||
BlockState.CODEC.decode(ops, JsonParser.parseString(tag.getString("Material")))
|
||||
.result()
|
||||
.ifPresent(p -> baseBlock = p.getFirst());
|
||||
|
||||
if (clientPacket && prevMaterial != baseBlock)
|
||||
redraw();
|
||||
}
|
||||
|
||||
private void redraw() {
|
||||
if (!isVirtual())
|
||||
requestModelDataUpdate();
|
||||
if (hasLevel()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16);
|
||||
level.getChunkSource()
|
||||
.getLightEngine()
|
||||
.checkBlock(worldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||
super.write(tag, clientPacket);
|
||||
|
||||
tag.put("Item", consumedItem.serializeNBT());
|
||||
|
||||
JsonOps ops = JsonOps.INSTANCE;
|
||||
BlockState.CODEC.encode(baseBlock, ops, ops.empty())
|
||||
.result()
|
||||
.map(je -> je.toString())
|
||||
.ifPresent(s -> tag.putString("Material", s));
|
||||
}
|
||||
|
||||
public static final ModelProperty<BlockState> MATERIAL_PROPERTY = new ModelProperty<>();
|
||||
|
||||
@Override
|
||||
public IModelData getModelData() {
|
||||
return new ModelDataMap.Builder().withInitial(MATERIAL_PROPERTY, baseBlock)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
||||
|
||||
@Override
|
||||
public void transform(StructureTransform transform) {
|
||||
baseBlock = transform.apply(baseBlock);
|
||||
notifyUpdate();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.simibubi.create.content.curiosities.frames;
|
||||
|
||||
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
|
||||
public abstract class WaterloggedCopycatBlock extends CopycatBlock implements ProperWaterloggedBlock {
|
||||
|
||||
public WaterloggedCopycatBlock(Properties pProperties) {
|
||||
super(pProperties);
|
||||
registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(Builder<Block, BlockState> pBuilder) {
|
||||
super.createBlockStateDefinition(pBuilder.add(WATERLOGGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockState pState) {
|
||||
return fluidState(pState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return withWater(super.getStateForPlacement(pContext), pContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||
updateWater(pLevel, pState, pCurrentPos);
|
||||
return pState;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,11 +28,13 @@ public class ConnectedGirderModel extends CTModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) {
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state,
|
||||
IModelData tileData) {
|
||||
ConnectionData connectionData = new ConnectionData();
|
||||
for (Direction d : Iterate.horizontalDirections)
|
||||
connectionData.setConnected(d, GirderBlock.isConnected(world, pos, state, d));
|
||||
return super.gatherModelData(builder, world, pos, state).withInitial(CONNECTION_PROPERTY, connectionData);
|
||||
return super.gatherModelData(builder, world, pos, state, tileData).withInitial(CONNECTION_PROPERTY,
|
||||
connectionData);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,14 +16,15 @@ public abstract class BakedModelWrapperWithData extends BakedModelWrapper<BakedM
|
|||
}
|
||||
|
||||
@Override
|
||||
public final IModelData getModelData(BlockAndTintGetter world, BlockPos pos, BlockState state, IModelData tileData) {
|
||||
public final IModelData getModelData(BlockAndTintGetter world, BlockPos pos, BlockState state,
|
||||
IModelData tileData) {
|
||||
Builder builder = new ModelDataMap.Builder();
|
||||
if (originalModel instanceof BakedModelWrapperWithData)
|
||||
((BakedModelWrapperWithData) originalModel).gatherModelData(builder, world, pos, state);
|
||||
return gatherModelData(builder, world, pos, state).build();
|
||||
((BakedModelWrapperWithData) originalModel).gatherModelData(builder, world, pos, state, tileData);
|
||||
return gatherModelData(builder, world, pos, state, tileData).build();
|
||||
}
|
||||
|
||||
protected abstract ModelDataMap.Builder gatherModelData(ModelDataMap.Builder builder, BlockAndTintGetter world,
|
||||
BlockPos pos, BlockState state);
|
||||
BlockPos pos, BlockState state, IModelData tileData);
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatBlock;
|
||||
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext;
|
||||
import com.simibubi.create.foundation.block.render.QuadHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
@ -33,7 +34,8 @@ public class CTModel extends BakedModelWrapperWithData {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) {
|
||||
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state,
|
||||
IModelData tileData) {
|
||||
return builder.withInitial(CT_PROPERTY, createCTData(world, pos, state));
|
||||
}
|
||||
|
||||
|
@ -41,8 +43,11 @@ public class CTModel extends BakedModelWrapperWithData {
|
|||
CTData data = new CTData();
|
||||
MutableBlockPos mutablePos = new MutableBlockPos();
|
||||
for (Direction face : Iterate.directions) {
|
||||
BlockState actualState = world.getBlockState(pos);
|
||||
if (!behaviour.buildContextForOccludedDirections()
|
||||
&& !Block.shouldRenderFace(state, world, pos, face, mutablePos.setWithOffset(pos, face)))
|
||||
&& !Block.shouldRenderFace(state, world, pos, face, mutablePos.setWithOffset(pos, face))
|
||||
&& !(actualState.getBlock()instanceof CopycatBlock ufb
|
||||
&& !ufb.canFaceBeOccluded(actualState, face)))
|
||||
continue;
|
||||
CTType dataType = behaviour.getDataType(state, face);
|
||||
if (dataType == null)
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.simibubi.create.foundation.block.connected;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatBlock;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -14,7 +16,8 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
public abstract class ConnectedTextureBehaviour {
|
||||
|
||||
@Nullable
|
||||
public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, @NotNull TextureAtlasSprite sprite);
|
||||
public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction,
|
||||
@NotNull TextureAtlasSprite sprite);
|
||||
|
||||
// TODO: allow more than one data type per state/face?
|
||||
@Nullable
|
||||
|
@ -27,10 +30,18 @@ public abstract class ConnectedTextureBehaviour {
|
|||
protected boolean isBeingBlocked(BlockState state, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos,
|
||||
Direction face) {
|
||||
BlockPos blockingPos = otherPos.relative(face);
|
||||
BlockState blockState = reader.getBlockState(pos);
|
||||
|
||||
if (blockState.getBlock()instanceof CopycatBlock ufb
|
||||
&& ufb.isUnblockableConnectivitySide(reader, blockState, face, pos, otherPos))
|
||||
return false;
|
||||
|
||||
return face.getAxis()
|
||||
.choose(pos.getX(), pos.getY(), pos.getZ()) == face.getAxis()
|
||||
.choose(otherPos.getX(), otherPos.getY(), otherPos.getZ())
|
||||
&& connectsTo(state, reader.getBlockState(blockingPos), reader, pos, blockingPos, face);
|
||||
&& connectsTo(state,
|
||||
getCTBlockState(reader, blockState, face.getOpposite(), pos.relative(face), blockingPos), reader, pos,
|
||||
blockingPos, face);
|
||||
}
|
||||
|
||||
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos,
|
||||
|
@ -47,10 +58,27 @@ public abstract class ConnectedTextureBehaviour {
|
|||
final Direction horizontal, final Direction vertical, int sh, int sv) {
|
||||
BlockPos p = pos.relative(horizontal, sh)
|
||||
.relative(vertical, sv);
|
||||
boolean test = connectsTo(state, reader.getBlockState(p), reader, pos, p, face,
|
||||
BlockState blockState = reader.getBlockState(pos);
|
||||
|
||||
if (blockState.getBlock()instanceof CopycatBlock ufb
|
||||
&& ufb.isIgnoredConnectivitySide(reader, blockState, face, pos, p))
|
||||
return false;
|
||||
|
||||
return connectsTo(state, getCTBlockState(reader, blockState, face, pos, p), reader, pos, p, face,
|
||||
sh == 0 ? null : sh == -1 ? horizontal.getOpposite() : horizontal,
|
||||
sv == 0 ? null : sv == -1 ? vertical.getOpposite() : vertical);
|
||||
return test;
|
||||
}
|
||||
|
||||
public BlockState getCTBlockState(BlockAndTintGetter reader, BlockState reference, Direction face, BlockPos fromPos,
|
||||
BlockPos toPos) {
|
||||
BlockState blockState = reader.getBlockState(toPos);
|
||||
|
||||
if (blockState.getBlock()instanceof CopycatBlock ufb) {
|
||||
BlockState connectiveMaterial = ufb.getConnectiveMaterial(reader, reference, face, fromPos, toPos);
|
||||
return connectiveMaterial == null ? blockState : connectiveMaterial;
|
||||
}
|
||||
|
||||
return blockState;
|
||||
}
|
||||
|
||||
protected boolean reverseUVs(BlockState state, Direction face) {
|
||||
|
@ -75,7 +103,8 @@ public abstract class ConnectedTextureBehaviour {
|
|||
return axis == Axis.X ? Direction.SOUTH : Direction.WEST;
|
||||
}
|
||||
|
||||
public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face, ContextRequirement requirement) {
|
||||
public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face,
|
||||
ContextRequirement requirement) {
|
||||
boolean positive = face.getAxisDirection() == AxisDirection.POSITIVE;
|
||||
Direction h = getRightDirection(reader, pos, state, face);
|
||||
Direction v = getUpDirection(reader, pos, state, face);
|
||||
|
@ -139,7 +168,8 @@ public abstract class ConnectedTextureBehaviour {
|
|||
public final boolean up, down, left, right;
|
||||
public final boolean topLeft, topRight, bottomLeft, bottomRight;
|
||||
|
||||
public ContextRequirement(boolean up, boolean down, boolean left, boolean right, boolean topLeft, boolean topRight, boolean bottomLeft, boolean bottomRight) {
|
||||
public ContextRequirement(boolean up, boolean down, boolean left, boolean right, boolean topLeft,
|
||||
boolean topRight, boolean bottomLeft, boolean bottomRight) {
|
||||
this.up = up;
|
||||
this.down = down;
|
||||
this.left = left;
|
||||
|
@ -239,7 +269,8 @@ public abstract class ConnectedTextureBehaviour {
|
|||
public static abstract class Base extends ConnectedTextureBehaviour {
|
||||
@Override
|
||||
@Nullable
|
||||
public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite);
|
||||
public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction,
|
||||
@Nullable TextureAtlasSprite sprite);
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.foundation.block.connected;
|
||||
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatBlock;
|
||||
import com.simibubi.create.content.palettes.ConnectedPillarBlock;
|
||||
import com.simibubi.create.content.palettes.LayeredBlock;
|
||||
|
||||
|
@ -27,6 +28,10 @@ public class RotatedPillarCTBehaviour extends HorizontalCTBehaviour {
|
|||
return false;
|
||||
if (isBeingBlocked(state, reader, pos, otherPos, face))
|
||||
return false;
|
||||
if (reader.getBlockState(pos).getBlock() instanceof CopycatBlock)
|
||||
return true;
|
||||
if (reader.getBlockState(otherPos).getBlock() instanceof CopycatBlock)
|
||||
return true;
|
||||
if (primaryOffset != null && primaryOffset.getAxis() != stateAxis
|
||||
&& !ConnectedPillarBlock.getConnection(state, primaryOffset))
|
||||
return false;
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
|||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public final class QuadHelper {
|
||||
|
||||
|
@ -28,6 +29,13 @@ public final class QuadHelper {
|
|||
quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade());
|
||||
}
|
||||
|
||||
public static Vec3 getXYZ(int[] vertexData, int vertex) {
|
||||
float x = Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + X_OFFSET]);
|
||||
float y = Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + Y_OFFSET]);
|
||||
float z = Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + Z_OFFSET]);
|
||||
return new Vec3(x, y, z);
|
||||
}
|
||||
|
||||
public static float getU(int[] vertexData, int vertex) {
|
||||
return Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + U_OFFSET]);
|
||||
}
|
||||
|
@ -35,6 +43,12 @@ public final class QuadHelper {
|
|||
public static float getV(int[] vertexData, int vertex) {
|
||||
return Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + V_OFFSET]);
|
||||
}
|
||||
|
||||
public static void setXYZ(int[] vertexData, int vertex, Vec3 xyz) {
|
||||
vertexData[vertex * VERTEX_STRIDE + X_OFFSET] = Float.floatToRawIntBits((float) xyz.x);
|
||||
vertexData[vertex * VERTEX_STRIDE + Y_OFFSET] = Float.floatToRawIntBits((float) xyz.y);
|
||||
vertexData[vertex * VERTEX_STRIDE + Z_OFFSET] = Float.floatToRawIntBits((float) xyz.z);
|
||||
}
|
||||
|
||||
public static void setU(int[] vertexData, int vertex, float u) {
|
||||
vertexData[vertex * VERTEX_STRIDE + U_OFFSET] = Float.floatToRawIntBits(u);
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.function.Supplier;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTags;
|
||||
import com.simibubi.create.AllTags.AllBlockTags;
|
||||
import com.simibubi.create.AllTags.AllItemTags;
|
||||
import com.simibubi.create.Create;
|
||||
|
@ -30,6 +31,7 @@ import com.simibubi.create.content.contraptions.relays.encased.EncasedCogwheelBl
|
|||
import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock;
|
||||
import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock;
|
||||
import com.simibubi.create.content.curiosities.deco.SlidingDoorMovementBehaviour;
|
||||
import com.simibubi.create.content.curiosities.frames.CopycatBlock;
|
||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
|
||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape;
|
||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelItem;
|
||||
|
@ -62,6 +64,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour;
|
|||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.PistonType;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.material.MaterialColor;
|
||||
import net.minecraft.world.level.storage.loot.LootPool;
|
||||
import net.minecraft.world.level.storage.loot.LootTable;
|
||||
import net.minecraft.world.level.storage.loot.LootTable.Builder;
|
||||
|
@ -101,6 +104,22 @@ public class BuilderTransformers {
|
|||
.onRegister(block -> IBogeyBlock.register(RegisteredObjects.getKeyOrThrow(block)));
|
||||
}
|
||||
|
||||
public static <B extends CopycatBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> copycat() {
|
||||
return b -> b.initialProperties(SharedProperties::softMetal)
|
||||
.blockstate((c, p) -> p.simpleBlock(c.get(), p.models()
|
||||
.getExistingFile(p.mcLoc("air"))))
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.properties(p -> p.noOcclusion()
|
||||
.color(MaterialColor.NONE))
|
||||
.addLayer(() -> RenderType::solid)
|
||||
.addLayer(() -> RenderType::cutout)
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.addLayer(() -> RenderType::translucent)
|
||||
.color(() -> CopycatBlock::wrappedColor)
|
||||
.tag(AllBlockTags.SAFE_NBT.tag)
|
||||
.transform(AllTags.axeOrPickaxe());
|
||||
}
|
||||
|
||||
public static <B extends TrapDoorBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> trapdoor(boolean orientable) {
|
||||
return b -> b.blockstate((c, p) -> {
|
||||
ModelFile bottom = AssetLookup.partialBaseModel(c, p, "bottom");
|
||||
|
|
|
@ -207,6 +207,14 @@ public class VecHelper {
|
|||
return new Vec3(Mth.clamp(vec.x, -maxLength, maxLength), Mth.clamp(vec.y, -maxLength, maxLength),
|
||||
Mth.clamp(vec.z, -maxLength, maxLength));
|
||||
}
|
||||
|
||||
public static Vec3 componentMin(Vec3 vec1, Vec3 vec2) {
|
||||
return new Vec3(Math.min(vec1.x, vec2.x), Math.min(vec1.y, vec2.y), Math.min(vec1.z, vec2.z));
|
||||
}
|
||||
|
||||
public static Vec3 componentMax(Vec3 vec1, Vec3 vec2) {
|
||||
return new Vec3(Math.max(vec1.x, vec2.x), Math.max(vec1.y, vec2.y), Math.max(vec1.z, vec2.z));
|
||||
}
|
||||
|
||||
public static Vec3 project(Vec3 vec, Vec3 ontoVec) {
|
||||
if (ontoVec.equals(Vec3.ZERO))
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "block/cube_all",
|
||||
"textures": {
|
||||
"all": "create:block/copycat_base"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"1": "create:block/copycat_base",
|
||||
"2": "create:block/copycat_base",
|
||||
"particle": "create:block/copycat_base"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 1, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 15, 16, 16], "texture": "#2"},
|
||||
"east": {"uv": [0, 15, 16, 16], "texture": "#2"},
|
||||
"south": {"uv": [0, 15, 16, 16], "texture": "#2"},
|
||||
"west": {"uv": [0, 15, 16, 16], "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 16, 16], "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 1, 0],
|
||||
"to": [16, 3, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 16, 2], "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 16, 2], "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 16, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 16, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 16, 16], "texture": "#1"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"1": "create:block/copycat_base",
|
||||
"2": "create:block/copycat_base",
|
||||
"particle": "create:block/copycat_base"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 4],
|
||||
"to": [16, 4, 8],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 12, 16, 16], "texture": "#1"},
|
||||
"east": {"uv": [12, 12, 16, 16], "texture": "#2"},
|
||||
"west": {"uv": [0, 12, 4, 16], "texture": "#2"},
|
||||
"down": {"uv": [0, 12, 16, 16], "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 0, 8],
|
||||
"to": [16, 4, 12],
|
||||
"faces": {
|
||||
"east": {"uv": [0, 12, 4, 16], "texture": "#2"},
|
||||
"south": {"uv": [0, 12, 16, 16], "texture": "#1"},
|
||||
"west": {"uv": [12, 12, 16, 16], "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 16, 4], "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 4, 8],
|
||||
"to": [16, 8, 12],
|
||||
"faces": {
|
||||
"east": {"uv": [0, 0, 4, 4], "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 16, 4], "texture": "#1"},
|
||||
"west": {"uv": [12, 0, 16, 4], "texture": "#2"},
|
||||
"up": {"uv": [0, 12, 16, 16], "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 4, 4],
|
||||
"to": [16, 8, 8],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 16, 4], "texture": "#1"},
|
||||
"east": {"uv": [12, 0, 16, 4], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 4, 4], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 16, 4], "texture": "#1"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
BIN
src/main/resources/assets/create/textures/block/copycat_base.png
Normal file
BIN
src/main/resources/assets/create/textures/block/copycat_base.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 265 B |
Loading…
Reference in a new issue