Merge branch 'mc1.18/dev' into mc1.18/global-railways

This commit is contained in:
simibubi 2022-05-22 18:10:40 +02:00
commit 841bf3f350
101 changed files with 5877 additions and 4786 deletions

View file

@ -49,6 +49,7 @@ body:
label: Mod Version
description: The version of the mod you were using when the bug occured
options:
- "0.4.1"
- "0.4.0f"
- "0.4.0e"
- "0.4.0d"
@ -101,6 +102,7 @@ body:
label: Minecraft Version
description: The version of Minecraft you were using when the bug occured
options:
- "1.18.2"
- "1.18.1"
- "1.18"
- "1.17.1"

View file

@ -11,14 +11,13 @@ Welcome to Create, a mod offering a variety of tools and blocks for Building, De
The added elements of tech are designed to leave as many design choices to the player as possible, where item processing doesn't happen inside a single block with funny textures, it requires a set of actors working together in many possible arrangements.
Check out the wiki and in-game Tool-tips for further info on how to use these features, and stay tuned for an ever-growing selection of possibilities for Creative and Survival Minecraft.
Check out the in-game Documentation for further info on how to use the added features, and stay tuned for an ever-growing selection of possibilities for Creative and Survival Minecraft.
[<img src="https://i.imgur.com/0lLX9Oy.jpg" width="200">](https://github.com/Creators-of-Create/Create/issues "Report Issues")
[<img src="https://i.imgur.com/bjEZraY.jpg" width="200">](https://www.youtube.com/channel/UCrKV2QTuyGcv4E3eSJpBiYA/playlists "Watch Videos")
[<img src="https://i.imgur.com/aWrjfKJ.jpg" width="200">](https://discord.gg/hmaD7Se "Feedback & Help")
[<img src="https://i.imgur.com/xj8o2xC.jpg" width="200">](https://www.patreon.com/simibubi "Support Us")
- Support for Minecraft 1.12: Not planned
- Support for Fabric: Not planned
<hr>
<h4 align="center">Find out more about Create on our <a href="https://www.curseforge.com/minecraft/mc-mods/create">Project Page</a></h4>
<h4 align="center">Looking for the Fabric port? <a href="https://github.com/Fabricators-of-Create/Create">Find it here</a></h4>

View file

@ -135,6 +135,10 @@ repositories {
//location of the maven for dynamic trees
url 'https://harleyoconnor.com/maven'
}
maven {
//location of the maven for curios api
url = "https://maven.theillusivec4.top/"
}
}
configurations {
@ -157,6 +161,9 @@ dependencies {
compileOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}:${jei_version}:api")
runtimeOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}:${jei_version}")
compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}:api")
runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}")
// implementation fg.deobf("curse.maven:druidcraft-340991:3101903")
// implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta25")
// runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69")

View file

@ -6,7 +6,7 @@ org.gradle.daemon = false
# mod version info
mod_version = 0.5.0
minecraft_version = 1.18.2
forge_version = 40.0.34
forge_version = 40.1.0
# build dependency versions
forgegradle_version = 5.1.+
@ -19,9 +19,11 @@ parchment_version = 2022.03.13
# dependency versions
registrate_version = MC1.18.2-1.0.25
flywheel_version = 1.18-0.6.2.66
flywheel_version = 1.18-0.7.0.67
jei_minecraft_version = 1.18.2
jei_version = 9.5.3.143
curios_minecraft_version = 1.18.2
curios_version = 5.0.7.0
# curseforge information
projectId = 328085

View file

@ -546,20 +546,20 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
bc34b2c5574a903a43729369b32c8981a4098ac1 assets/create/lang/en_ud.json
8ff43211f8611542dc2b80125eabe13153bc1fbf assets/create/lang/en_us.json
4c857eab126af9dba639b6483e02628f81cc46fb assets/create/lang/unfinished/de_de.json
8bf1cfb8b68fd54b9cb796360beba73d83b2ec7f assets/create/lang/unfinished/de_de.json
0ce3a240ac9fa0b44674cf886a71dfe43f2bd164 assets/create/lang/unfinished/es_cl.json
bc0318d36ad5249bcfe7dd526372137fd8af86b6 assets/create/lang/unfinished/es_es.json
3b28c641fdb7ff5eee3b81ffc7b6f37ce38194e3 assets/create/lang/unfinished/es_es.json
c15da57f79901b1cddbf6fa3d94e953480ab9467 assets/create/lang/unfinished/fr_fr.json
c2e763d4e611143f9a42c0a6a0b8cfa58f254b37 assets/create/lang/unfinished/it_it.json
5a173ee5e1f6b5a6ffeff2b301c28e9f75eb762c assets/create/lang/unfinished/ja_jp.json
a1d09b3588d98762d0fa56fece59e600507311da assets/create/lang/unfinished/ko_kr.json
9ad05595229b0ac2ef8d8b21d43dc86396167485 assets/create/lang/unfinished/nl_nl.json
76052baa07a1c9d34a5e98e75e1c7f8a935076c9 assets/create/lang/unfinished/pl_pl.json
d6fc8c6f6a1e88021d21546d5363c425863e4204 assets/create/lang/unfinished/pt_br.json
f7dd233fa675c1c2c1ff6c4402c16744c6189616 assets/create/lang/unfinished/pt_br.json
541b9a302d8ddf3827f29a7ab67b482e345bc207 assets/create/lang/unfinished/pt_pt.json
69ba5f485d16706f5438856162fcc337d23c5400 assets/create/lang/unfinished/ro_ro.json
64431b39b4cfa1fe1988ec8c4f36145e66714847 assets/create/lang/unfinished/ru_ru.json
1dd6ff7ee8d61c16bed0583a5f5d4567f5c76257 assets/create/lang/unfinished/zh_cn.json
54faaacfdf8aa4ee3575fbc9ee6e81b5f9bcffe0 assets/create/lang/unfinished/zh_cn.json
e8db253724c9b2eeb07b4587d3efb10811941df5 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
@ -4180,7 +4180,7 @@ a7c97582bae243ab04ff5ff9914b24af25d40d59 data/create/recipes/crushing/iron_horse
554b6555888fe01de349efaaab36b68a338ac397 data/create/recipes/crushing/iron_ore.json
c9a9d6d28a7eac1210108d52840b60b26d58bcfe data/create/recipes/crushing/lapis_ore.json
e870d049abc5cd5f389f70414c67e76ddc14060d data/create/recipes/crushing/leather_horse_armor.json
cc5a817901d6f0d68e4ceb3e65d7f2187ab37ceb data/create/recipes/crushing/nether_gold_ore.json
cab15acd2d62f1d70e0972b443f7987048d5183a data/create/recipes/crushing/nether_gold_ore.json
6cd97c6f12687790943db810f85036b02586c753 data/create/recipes/crushing/nether_quartz_ore.json
6e424d7e9f7d8b585384053a713db28f9d36448b data/create/recipes/crushing/nether_wart_block.json
8003e7db3ee11066b365c251f04f84028820de94 data/create/recipes/crushing/netherrack.json

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 240",
"_": "Missing Localizations: 233",
"_": "->------------------------] Game Elements [------------------------<-",
@ -582,12 +582,12 @@
"item.create.chromatic_compound": "Compuesto cromático",
"item.create.cinder_flour": "Harina del Nether",
"item.create.copper_backtank": "Depósito trasero de cobre",
"item.create.copper_backtank_placeable": "UNLOCALIZED: Copper Backtank Placeable",
"item.create.copper_backtank_placeable": "Depósito de cobre colocable",
"item.create.copper_nugget": "Pepita de cobre",
"item.create.copper_sheet": "Lámina de cobre",
"item.create.crafter_slot_cover": "Tapa de ranura del ensamblador mecánico",
"item.create.crafting_blueprint": "Plano de elaboración",
"item.create.creative_blaze_cake": "´Pastel de blaze creativo",
"item.create.creative_blaze_cake": "Pastel de blaze creativo",
"item.create.crushed_aluminum_ore": "Mineral de aluminio molido",
"item.create.crushed_copper_ore": "Mineral de cobre molido",
"item.create.crushed_gold_ore": "Mineral de oro molido",
@ -654,7 +654,7 @@
"advancement.create.root": "Bienvenido a Create",
"advancement.create.root.desc": "¡Es hora de empezar a construir increíbles artefactos animados!",
"advancement.create.andesite_alloy": "UNLOCALIZED: Alliterations Aplenty",
"advancement.create.andesite_alloy": "Aliteraciones a montones",
"advancement.create.andesite_alloy.desc": "Los materiales de Create tienen nombres extraños, la aleación de andesita es uno de ellos.",
"advancement.create.its_alive": "¡Está vivo!",
"advancement.create.its_alive.desc": "Mira cómo gira tu primer componente cinético.",
@ -840,8 +840,8 @@
"create.recipe.fan_washing.fan": "Ventilador detrás del agua fluyente",
"create.recipe.fan_smoking": "Ahumador a granel",
"create.recipe.fan_smoking.fan": "Ventilador detrás del fuego",
"create.recipe.fan_haunting": "UNLOCALIZED: Bulk Haunting",
"create.recipe.fan_haunting.fan": "UNLOCALIZED: Fan behind Soul Fire",
"create.recipe.fan_haunting": "Maldecidor a granel",
"create.recipe.fan_haunting.fan": "Ventilador detrás del fuego de alma",
"create.recipe.fan_blasting": "Voladuras a granel",
"create.recipe.fan_blasting.fan": "Ventilador detrás de la lava",
"create.recipe.pressing": "Prensando",
@ -1193,8 +1193,8 @@
"create.item_attributes.furnace_fuel.inverted": "no es combustible para hornos",
"create.item_attributes.washable": "se puede lavar",
"create.item_attributes.washable.inverted": "no se puede lavar",
"create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted",
"create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted",
"create.item_attributes.hauntable": "puede ser maldito",
"create.item_attributes.hauntable.inverted": "no puede ser maldito",
"create.item_attributes.crushable": "puede ser molido",
"create.item_attributes.crushable.inverted": "no puede ser molido",
"create.item_attributes.smeltable": "se puede fundir",
@ -1259,7 +1259,7 @@
"create.tooltip.keyCtrl": "Ctrl",
"create.tooltip.speedRequirement": "Requisitos de velocidad: %1$s",
"create.tooltip.speedRequirement.none": "Ninguno",
"create.tooltip.speedRequirement.slow": "UNLOCALIZED: Slow",
"create.tooltip.speedRequirement.slow": "Lento",
"create.tooltip.speedRequirement.medium": "Moderado",
"create.tooltip.speedRequirement.fast": "Rápido",
"create.tooltip.stressImpact": "Impacto de estrés: %1$s",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1409",
"_": "Missing Localizations: 1103",
"_": "->------------------------] Game Elements [------------------------<-",
@ -823,16 +823,16 @@
"death.attack.create.cuckoo_clock_explosion.player": "%1$s foi explodido por relógio cuco adulterado",
"death.attack.create.run_over": "UNLOCALIZED: %1$s was run over by %2$s",
"create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer",
"create.block.cart_assembler.invalid": "UNLOCALIZED: Place your Cart Assembler on a rail block",
"create.block.deployer.damage_source_name": "Implantador rebelde",
"create.block.cart_assembler.invalid": "Coloque o seu montador de carrinho de minas num trilho",
"create.menu.return": "UNLOCALIZED: Return to Menu",
"create.menu.configure": "UNLOCALIZED: Configure...",
"create.menu.ponder_index": "UNLOCALIZED: Ponder Index",
"create.menu.only_ingame": "UNLOCALIZED: Available in the Pause Menu",
"create.menu.project_page": "UNLOCALIZED: Project Page",
"create.menu.report_bugs": "UNLOCALIZED: Report Issues",
"create.menu.support": "UNLOCALIZED: Support Us",
"create.menu.return": "Retornar ao menu",
"create.menu.configure": "Configurar...",
"create.menu.ponder_index": "Tabela do ponderamento",
"create.menu.only_ingame": "Disponível no menu de pausa",
"create.menu.project_page": "Página do projeto",
"create.menu.report_bugs": "Informar um erro",
"create.menu.support": "Suporte nós",
"create.recipe.crushing": "Triturando",
"create.recipe.milling": "Moendo",
@ -848,7 +848,7 @@
"create.recipe.mixing": "Misturando",
"create.recipe.deploying": "Implantando",
"create.recipe.automatic_shapeless": "Fabricação sem forma automático",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.automatic_brewing": "Produção de poções",
"create.recipe.packing": "Compactando",
"create.recipe.automatic_packing": "Compactamento automático",
"create.recipe.sawing": "Serrando",
@ -909,22 +909,22 @@
"create.action.discard": "Descartar",
"create.keyinfo.toolmenu": "Menu Focal da Ferramenta",
"create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes",
"create.keyinfo.scrollup": "UNLOCALIZED: Simulate Mousewheel Up (inworld)",
"create.keyinfo.scrolldown": "UNLOCALIZED: Simulate Mousewheel Down (inworld)",
"create.keyinfo.toolbelt": "Acessa caixas de ferramenta próximas",
"create.keyinfo.scrollup": "Simular a roda do mouse (para cima) (no mundo)",
"create.keyinfo.scrolldown": "Simular a roda do mouse (para baixo) (no mundo)",
"create.gui.scrollInput.defaultTitle": "Escolha uma Opção:",
"create.gui.scrollInput.scrollToModify": "Role o mouse para Modificar",
"create.gui.scrollInput.scrollToAdjustAmount": "Role o mouse para ajustar a quantidade",
"create.gui.scrollInput.scrollToSelect": "Role o mouse para Selecionar",
"create.gui.scrollInput.shiftScrollsFaster": "UNLOCALIZED: Shift to Scroll Faster",
"create.gui.scrollInput.shiftScrollsFaster": "Shift para rolar o mouse mais rapido",
"create.gui.toolmenu.focusKey": "Segure [%1$s] para Focar",
"create.gui.toolmenu.cycle": "[SCROLL] para Circular",
"create.toolbox.unequip": "Desequipar: %1$s",
"create.toolbox.outOfRange": "Caixa de ferramentas do item segurado fora de alcance",
"create.toolbox.detach": "Parar de rastrear e manter item",
"create.toolbox.depositAll": "Retornar itens para caixa de ferramenta próxima",
"create.toolbox.depositAll": "Retorna itens para caixa de ferramenta próxima",
"create.toolbox.depositBox": "Retornar itens para caixa de ferramenta",
"create.gui.symmetryWand.mirrorType": "Espelhar",
@ -972,90 +972,90 @@
"create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s",
"create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material",
"create.minecart_coupling.two_couplings_max": "UNLOCALIZED: Minecarts cannot have more than two couplings each",
"create.minecart_coupling.unloaded": "UNLOCALIZED: Parts of your train seem to be in unloaded chunks",
"create.minecart_coupling.no_loops": "UNLOCALIZED: Couplings cannot form a loop",
"create.minecart_coupling.removed": "UNLOCALIZED: Removed all couplings from minecart",
"create.minecart_coupling.too_far": "UNLOCALIZED: Minecarts are too far apart",
"create.minecart_coupling.two_couplings_max": "Carrinhos de mina não podem ter mais de dois acoplamentos cada",
"create.minecart_coupling.unloaded": "Partes do seu trem aparentam estar em um chunk descarregado",
"create.minecart_coupling.no_loops": "Acoplamentos não podem formar um loop",
"create.minecart_coupling.removed": "Removeu todos os acoplamentos do carrinho de mina",
"create.minecart_coupling.too_far": "Carrinhos de mina estão muito distanciados",
"create.contraptions.movement_mode": "UNLOCALIZED: Movement Mode",
"create.contraptions.movement_mode.move_place": "UNLOCALIZED: Always Place when Stopped",
"create.contraptions.movement_mode.move_place_returned": "UNLOCALIZED: Place only in Starting Position",
"create.contraptions.movement_mode.move_never_place": "UNLOCALIZED: Place only when Anchor Destroyed",
"create.contraptions.movement_mode.rotate_place": "UNLOCALIZED: Always Place when Stopped",
"create.contraptions.movement_mode.rotate_place_returned": "UNLOCALIZED: Only Place near Initial Angle",
"create.contraptions.movement_mode.rotate_never_place": "UNLOCALIZED: Only Place when Anchor Destroyed",
"create.contraptions.cart_movement_mode": "UNLOCALIZED: Cart Movement Mode",
"create.contraptions.cart_movement_mode.rotate": "UNLOCALIZED: Always face toward motion",
"create.contraptions.cart_movement_mode.rotate_paused": "UNLOCALIZED: Pause actors while rotating",
"create.contraptions.cart_movement_mode.rotation_locked": "UNLOCALIZED: Lock rotation",
"create.contraptions.windmill.rotation_direction": "UNLOCALIZED: Rotation Direction",
"create.contraptions.clockwork.clock_hands": "UNLOCALIZED: Clock Hands",
"create.contraptions.clockwork.hour_first": "UNLOCALIZED: Hour hand first",
"create.contraptions.clockwork.minute_first": "UNLOCALIZED: Minute hand first",
"create.contraptions.clockwork.hour_first_24": "UNLOCALIZED: 24-Hour hand first",
"create.contraptions.movement_mode": "Modo de movimento",
"create.contraptions.movement_mode.move_place": "Sempre colocar quando parado",
"create.contraptions.movement_mode.move_place_returned": "Colocar apenas na posição inicial",
"create.contraptions.movement_mode.move_never_place": "Colocar apenas caso a âncora seja destruída",
"create.contraptions.movement_mode.rotate_place": "Sempre colocar quando parado",
"create.contraptions.movement_mode.rotate_place_returned": "Apenas colocar perto do angulo inicial",
"create.contraptions.movement_mode.rotate_never_place": "Colocar apenas caso a âncora seja destruída",
"create.contraptions.cart_movement_mode": "Modo de movimento do carrinho",
"create.contraptions.cart_movement_mode.rotate": "Sempre apontar para a direção do movimento",
"create.contraptions.cart_movement_mode.rotate_paused": "Pausar atores quando girando",
"create.contraptions.cart_movement_mode.rotation_locked": "Travar a rotação",
"create.contraptions.windmill.rotation_direction": "Direção da rotação",
"create.contraptions.clockwork.clock_hands": "Ponteiros do relogio",
"create.contraptions.clockwork.hour_first": "Ponteiro da hora primeiro",
"create.contraptions.clockwork.minute_first": "Ponteiro do minuto primeiro",
"create.contraptions.clockwork.hour_first_24": "Ponteiro das 24 horas primeiro",
"create.logistics.filter": "UNLOCALIZED: Filter",
"create.logistics.recipe_filter": "UNLOCALIZED: Recipe Filter",
"create.logistics.fluid_filter": "UNLOCALIZED: Fluid Filter",
"create.logistics.firstFrequency": "UNLOCALIZED: Freq. #1",
"create.logistics.secondFrequency": "UNLOCALIZED: Freq. #2",
"create.logistics.filter.apply": "UNLOCALIZED: Applied filter to %1$s.",
"create.logistics.filter.apply_click_again": "UNLOCALIZED: Applied filter to %1$s, click again to copy the amount.",
"create.logistics.filter.apply_count": "UNLOCALIZED: Applied extraction count to filter.",
"create.logistics.filter": "Filtro",
"create.logistics.recipe_filter": "Filtro de receitas",
"create.logistics.fluid_filter": "Filtro de fluido",
"create.logistics.firstFrequency": "Freq. #1",
"create.logistics.secondFrequency": "Freq. #2",
"create.logistics.filter.apply": "Aplicou filtro para %1$s.",
"create.logistics.filter.apply_click_again": "Aplicou filtro para %1$s, Clique denovo para copiar quantidade.",
"create.logistics.filter.apply_count": "Aplicou quantidade de extração para o filtro.",
"create.gui.goggles.generator_stats": "Estatísticas do gerador:",
"create.gui.goggles.kinetic_stats": "Estatísticas cinéticas:",
"create.gui.goggles.at_current_speed": "Na velocidade atual",
"create.gui.goggles.pole_length": "Comprimento da vara:",
"create.gui.goggles.fluid_container": "UNLOCALIZED: Fluid Container Info:",
"create.gui.goggles.fluid_container.capacity": "UNLOCALIZED: Capacity: ",
"create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:",
"create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s,%2$s,%3$s]",
"create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s,%2$s,%3$s] was not in a loaded chunk",
"create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles",
"create.gui.assembly.exception.not_enough_sails": "UNLOCALIZED: Attached structure does not include enough sail-like blocks: %1$s\nA minimum of %2$s are required",
"create.gui.gauge.info_header": "UNLOCALIZED: Gauge Information:",
"create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed",
"create.gui.stressometer.title": "UNLOCALIZED: Network Stress",
"create.gui.stressometer.capacity": "UNLOCALIZED: Remaining Capacity",
"create.gui.stressometer.overstressed": "UNLOCALIZED: Overstressed",
"create.gui.stressometer.no_rotation": "UNLOCALIZED: No Rotation",
"create.gui.contraptions.not_fast_enough": "UNLOCALIZED: It appears that this %1$s is _not_ rotating with _enough_ _speed_.",
"create.gui.contraptions.network_overstressed": "UNLOCALIZED: It appears that this contraption is _overstressed_. Add more sources or _slow_ _down_ the components with a high _stress_ _impact_.",
"create.gui.goggles.fluid_container": "Informação do recipiente de fluido:",
"create.gui.goggles.fluid_container.capacity": "Capacidade: ",
"create.gui.assembly.exception": "Não foi possível montar essa engenhoca:",
"create.gui.assembly.exception.unmovableBlock": "Bloco imovel (%4$s) em [%1$s,%2$s,%3$s]",
"create.gui.assembly.exception.chunkNotLoaded": "O bloco em [%1$s,%2$s,%3$s] não estava em um chunk carregado",
"create.gui.assembly.exception.structureTooLarge": "Tem muitos blocos incluídos na engenhoca. O limite configurado é: %1$s",
"create.gui.assembly.exception.tooManyPistonPoles": "Tem muitas varetas de extensão colocadas nesse pistão. O limite configurado é: %1$s",
"create.gui.assembly.exception.noPistonPoles": "O pistão esta faltando algumas varetas de extensão",
"create.gui.assembly.exception.not_enough_sails": "A estrutura conectada não possui o número suficiente de blocos tipo vela: %1$s\nUm mínimo de %2$s são requeridos",
"create.gui.gauge.info_header": "Informação do medidor:",
"create.gui.speedometer.title": "Velocidade de rotação",
"create.gui.stressometer.title": "Estresse do sistema",
"create.gui.stressometer.capacity": "Capacidade restante",
"create.gui.stressometer.overstressed": "Sobre estressado",
"create.gui.stressometer.no_rotation": "Nenhuma rotação",
"create.gui.contraptions.not_fast_enough": "Aparenta que esse %1$s não _está_ girando com _a velocidade_ _necessária_.",
"create.gui.contraptions.network_overstressed": "Aparenta que essa engenhoca está _sobre estressada_. Adicione mais fontes ou _desacelere_ __ os componentes que tem um _impacto de_ _stress alto_.",
"create.gui.adjustable_crate.title": "UNLOCALIZED: Adjustable Crate",
"create.gui.adjustable_crate.storageSpace": "UNLOCALIZED: Storage Space",
"create.gui.stockpile_switch.title": "UNLOCALIZED: Stockpile Switch",
"create.gui.stockpile_switch.invert_signal": "UNLOCALIZED: Invert Signal",
"create.gui.stockpile_switch.move_to_lower_at": "UNLOCALIZED: Move to lower lane at %1$s%%",
"create.gui.stockpile_switch.move_to_upper_at": "UNLOCALIZED: Move to upper lane at %1$s%%",
"create.gui.sequenced_gearshift.title": "UNLOCALIZED: Sequenced Gearshift",
"create.gui.sequenced_gearshift.instruction": "UNLOCALIZED: Instruction",
"create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle",
"create.gui.sequenced_gearshift.instruction.turn_angle": "UNLOCALIZED: Turn",
"create.gui.sequenced_gearshift.instruction.turn_angle.angle": "UNLOCALIZED: Angle",
"create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry",
"create.gui.sequenced_gearshift.instruction.turn_distance": "UNLOCALIZED: Piston",
"create.gui.sequenced_gearshift.instruction.turn_distance.distance": "UNLOCALIZED: Distance",
"create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay",
"create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay",
"create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration",
"create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End",
"create.gui.sequenced_gearshift.instruction.end": "UNLOCALIZED: End",
"create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse",
"create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await",
"create.gui.sequenced_gearshift.speed": "UNLOCALIZED: Speed, Direction",
"create.gui.sequenced_gearshift.speed.forward": "UNLOCALIZED: Input speed, Forwards",
"create.gui.sequenced_gearshift.speed.forward_fast": "UNLOCALIZED: Double speed, Forwards",
"create.gui.sequenced_gearshift.speed.back": "UNLOCALIZED: Input speed, Reversed",
"create.gui.sequenced_gearshift.speed.back_fast": "UNLOCALIZED: Double speed, Reversed",
"create.gui.stockpile_switch.title": "Dijuntor de armazenamento",
"create.gui.stockpile_switch.invert_signal": "Inverter sinal",
"create.gui.stockpile_switch.move_to_lower_at": "Mover para a faixa mais baixa %1$s%%",
"create.gui.stockpile_switch.move_to_upper_at": "Mover para a faixa mais alta %1$s%%",
"create.gui.sequenced_gearshift.title": "Câmbio sequenciado",
"create.gui.sequenced_gearshift.instruction": "Instruções",
"create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "Rotacionar por angulo",
"create.gui.sequenced_gearshift.instruction.turn_angle": "Giro",
"create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Angulo",
"create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "Rotacionar par mover Pistão/Polia/Portico",
"create.gui.sequenced_gearshift.instruction.turn_distance": "Pistão",
"create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distancia",
"create.gui.sequenced_gearshift.instruction.delay.descriptive": "Espera",
"create.gui.sequenced_gearshift.instruction.delay": "Esperar",
"create.gui.sequenced_gearshift.instruction.delay.duration": "Duração",
"create.gui.sequenced_gearshift.instruction.end.descriptive": "Terminar",
"create.gui.sequenced_gearshift.instruction.end": "Termino",
"create.gui.sequenced_gearshift.instruction.await.descriptive": "Esperar novo pulso de redstone",
"create.gui.sequenced_gearshift.instruction.await": "Espera",
"create.gui.sequenced_gearshift.speed": "Velocidade, Direção",
"create.gui.sequenced_gearshift.speed.forward": "Velocidade inicial, Para frente",
"create.gui.sequenced_gearshift.speed.forward_fast": "Dobro da velocidade, Para frente",
"create.gui.sequenced_gearshift.speed.back": "Velocidade inicial, Para trás",
"create.gui.sequenced_gearshift.speed.back_fast": "Dobro da velocidade, Para trás",
"create.schematicAndQuill.dimensions": "Tamanho Esquema: %1$sx%2$sx%3$s",
"create.schematicAndQuill.firstPos": "Primeira posição feita.",
"create.schematicAndQuill.secondPos": "Segunda posição feita.",
"create.schematicAndQuill.noTarget": "Seguro [Ctrl] para selecionar Blocos de Ar.",
"create.schematicAndQuill.noTarget": "Seguro [Ctrl] para seleccionar Blocos de Ar.",
"create.schematicAndQuill.abort": "Seleção removida.",
"create.schematicAndQuill.title": "Nome do esquema:",
"create.schematicAndQuill.convert": "Salvar e carregar arquivo imediatamente",
@ -1095,7 +1095,7 @@
"create.schematic.tool.rotate.description.1": "[CTRL]-Rolar para rolar 90 Graus",
"create.schematic.tool.rotate.description.2": "",
"create.schematic.tool.rotate.description.3": "",
"create.schematic.tool.print.description.0": "Coloca estrutura no mundo instantaneamente",
"create.schematic.tool.print.description.0": "Colocá estrutura no mundo instantaneamente",
"create.schematic.tool.print.description.1": "[Botão-Direito] para confirmar a posição atual.",
"create.schematic.tool.print.description.2": "Esta ferramenta é para o Modo Criativo apenas.",
"create.schematic.tool.print.description.3": "",
@ -1108,11 +1108,11 @@
"create.schematics.uploadTooLarge": "Seu esquema é muito grande",
"create.schematics.maxAllowedSize": "O tamanho máximo permitido para o esquema é:",
"create.gui.schematicTable.refresh": "UNLOCALIZED: Refresh Files",
"create.gui.schematicTable.open_folder": "UNLOCALIZED: Open Folder",
"create.gui.schematicTable.refresh": "atualizar arquivos",
"create.gui.schematicTable.open_folder": "Abrir pasta",
"create.gui.schematicTable.title": "Mesa de Desenho",
"create.gui.schematicTable.availableSchematics": "UNLOCALIZED: Available Schematics",
"create.gui.schematicTable.noSchematics": "UNLOCALIZED: No Schematics Saved",
"create.gui.schematicTable.availableSchematics": "Esquema disponíveis",
"create.gui.schematicTable.noSchematics": "Nenhum esquema salvo",
"create.gui.schematicTable.uploading": "Importando...",
"create.gui.schematicTable.finished": "Envio Concluído!",
"create.gui.schematicannon.title": "Canhão de esquema",
@ -1122,18 +1122,18 @@
"create.gui.schematicannon.shotsRemainingWithBackup": "Com backup: %1$s",
"create.gui.schematicannon.optionEnabled": "Habilitado Atualmente",
"create.gui.schematicannon.optionDisabled": "Desabilitado Atualmente",
"create.gui.schematicannon.showOptions": "UNLOCALIZED: Show Printer Settings",
"create.gui.schematicannon.showOptions": "Mostrar as configurações da impressora",
"create.gui.schematicannon.option.dontReplaceSolid": "Não Substituir Blocos Sólidos",
"create.gui.schematicannon.option.replaceWithSolid": "Substituir Blocos Sólidos",
"create.gui.schematicannon.option.replaceWithAny": "Substituir Sólidos com Qualquer",
"create.gui.schematicannon.option.replaceWithEmpty": "Substituir Sólidos com Vazio",
"create.gui.schematicannon.option.skipMissing": "Pulando Blocos faltantes",
"create.gui.schematicannon.option.skipTileEntities": "Proteger Entidades Entalhadas",
"create.gui.schematicannon.slot.gunpowder": "UNLOCALIZED: Add gunpowder to fuel the cannon",
"create.gui.schematicannon.slot.listPrinter": "UNLOCALIZED: Place books here to print a Checklist for your Schematic",
"create.gui.schematicannon.slot.schematic": "UNLOCALIZED: Add your Schematic here. Make sure it is deployed at a specific location.",
"create.gui.schematicannon.option.skipMissing.description": "Se o Canhão de esquema não encontrar o Bloco para colocar, ele irá continuar para a próx. Posição.",
"create.gui.schematicannon.option.skipTileEntities.description": "O Canhão de esquema vai evitar substituir blocos que contêm dados como Baus.",
"create.gui.schematicannon.option.skipTileEntities": "Proteger tile entities",
"create.gui.schematicannon.slot.gunpowder": "Adicionar pólvora para carregar o canhão",
"create.gui.schematicannon.slot.listPrinter": "Coloque livros aqui para imprimir uma lista para o seu esquema",
"create.gui.schematicannon.slot.schematic": "Adicione o seu esquema aqui. Tenha certeza que ele está colocado em um lugar especifico.",
"create.gui.schematicannon.option.skipMissing.description": "Se o Canhão de esquema não encontrar o Bloco para colocar, ele irá continuar para a próxima. Posição.",
"create.gui.schematicannon.option.skipTileEntities.description": "O Canhão de esquema vai evitar substituir blocos que contêm dados como Baús.",
"create.gui.schematicannon.option.dontReplaceSolid.description": "O Canhão de esquema nunca irá substituir Blocos sólidos na área em trabalho, apenas não-Sólidos e Ar.",
"create.gui.schematicannon.option.replaceWithSolid.description": "O Canhão de esquema irá apenas substituir Blocos sólidos na área de trabalho, se o Esquema conter um bloco Sólido naquela posição.",
"create.gui.schematicannon.option.replaceWithAny.description": "O Canhão de esquema irá substituir Blocos sólidos na área de trabalho, se o Esquema conter qualquer Bloco naquela posição.",
@ -1157,187 +1157,187 @@
"create.schematicannon.status.schematicNotPlaced": "Esquema não Colocado",
"create.schematicannon.status.schematicExpired": "Arquivo de Esquema Expirado",
"create.materialChecklist": "UNLOCALIZED: Material Checklist",
"create.materialChecklist": "Lista de materiais",
"create.materialChecklist.blocksNotLoaded": "UNLOCALIZED: * Disclaimer *\n\nMaterial List may be inaccurate due to relevant chunks not being loaded.",
"create.gui.filter.deny_list": "UNLOCALIZED: Deny-List",
"create.gui.filter.deny_list.description": "UNLOCALIZED: Items pass if they do NOT match any of the above. An empty Deny-List accepts everything.",
"create.gui.filter.allow_list": "UNLOCALIZED: Allow-List",
"create.gui.filter.allow_list.description": "UNLOCALIZED: Items pass if they match any of the above. An empty Allow-List rejects everything.",
"create.gui.filter.respect_data": "UNLOCALIZED: Respect Data",
"create.gui.filter.respect_data.description": "UNLOCALIZED: Items only match if their durability, enchantments, and other attributes match as well.",
"create.gui.filter.ignore_data": "UNLOCALIZED: Ignore Data",
"create.gui.filter.ignore_data.description": "UNLOCALIZED: Items match regardless of their attributes.",
"create.gui.filter.deny_list": "Lista de negação",
"create.gui.filter.deny_list.description": "Itens passam se eles não encaixam em nenhum dos acima. Uma lista de negação vazia aceita tudo.",
"create.gui.filter.allow_list": "Lista de permissão",
"create.gui.filter.allow_list.description": "Itens passam se eles se encaixam em algum dos acima. Uma lista de permissão vazia rejeita tudo.",
"create.gui.filter.respect_data": "Respeitar informação",
"create.gui.filter.respect_data.description": "Itens apenas se encaixam caso a durabilidade, encantamentos e outros atributos se encaixam também.",
"create.gui.filter.ignore_data": "Ignorar informação",
"create.gui.filter.ignore_data.description": "Itens se enquadram não importa os seus atributos.",
"create.item_attributes.placeable": "UNLOCALIZED: is placeable",
"create.item_attributes.placeable.inverted": "UNLOCALIZED: is not placeable",
"create.item_attributes.consumable": "UNLOCALIZED: can be eaten",
"create.item_attributes.consumable.inverted": "UNLOCALIZED: cannot be eaten",
"create.item_attributes.fluid_container": "UNLOCALIZED: can store fluids",
"create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids",
"create.item_attributes.enchanted": "UNLOCALIZED: is enchanted",
"create.item_attributes.enchanted.inverted": "UNLOCALIZED: is unenchanted",
"create.item_attributes.max_enchanted": "UNLOCALIZED: is enchanted at max level",
"create.item_attributes.max_enchanted.inverted": "UNLOCALIZED: is not enchanted at max level",
"create.item_attributes.renamed": "UNLOCALIZED: has a custom name",
"create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name",
"create.item_attributes.damaged": "UNLOCALIZED: is damaged",
"create.item_attributes.damaged.inverted": "UNLOCALIZED: is not damaged",
"create.item_attributes.badly_damaged": "UNLOCALIZED: is heavily damaged",
"create.item_attributes.badly_damaged.inverted": "UNLOCALIZED: is not heavily damaged",
"create.item_attributes.not_stackable": "UNLOCALIZED: cannot stack",
"create.item_attributes.not_stackable.inverted": "UNLOCALIZED: can be stacked",
"create.item_attributes.equipable": "UNLOCALIZED: can be equipped",
"create.item_attributes.equipable.inverted": "UNLOCALIZED: cannot be equipped",
"create.item_attributes.furnace_fuel": "UNLOCALIZED: is furnace fuel",
"create.item_attributes.furnace_fuel.inverted": "UNLOCALIZED: is not furnace fuel",
"create.item_attributes.washable": "UNLOCALIZED: can be Washed",
"create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed",
"create.item_attributes.hauntable": "UNLOCALIZED: can be Haunted",
"create.item_attributes.hauntable.inverted": "UNLOCALIZED: cannot be Haunted",
"create.item_attributes.crushable": "UNLOCALIZED: can be Crushed",
"create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed",
"create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted",
"create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted",
"create.item_attributes.smokable": "UNLOCALIZED: can be Smoked",
"create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked",
"create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace",
"create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace",
"create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s",
"create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s",
"create.item_attributes.shulker_level.full": "UNLOCALIZED: full",
"create.item_attributes.shulker_level.empty": "UNLOCALIZED: empty",
"create.item_attributes.shulker_level.partial": "UNLOCALIZED: partially filled",
"create.item_attributes.in_tag": "UNLOCALIZED: is tagged %1$s",
"create.item_attributes.in_tag.inverted": "UNLOCALIZED: is not tagged %1$s",
"create.item_attributes.in_item_group": "UNLOCALIZED: is in group '%1$s'",
"create.item_attributes.in_item_group.inverted": "UNLOCALIZED: is not in group '%1$s'",
"create.item_attributes.added_by": "UNLOCALIZED: was added by %1$s",
"create.item_attributes.added_by.inverted": "UNLOCALIZED: was not added by %1$s",
"create.item_attributes.has_enchant": "UNLOCALIZED: is enchanted with %1$s",
"create.item_attributes.has_enchant.inverted": "UNLOCALIZED: is not enchanted with %1$s",
"create.item_attributes.color": "UNLOCALIZED: is dyed %1$s",
"create.item_attributes.color.inverted": "UNLOCALIZED: is not dyed %1$s",
"create.item_attributes.has_fluid": "UNLOCALIZED: contains %1$s",
"create.item_attributes.has_fluid.inverted": "UNLOCALIZED: does not contain %1$s",
"create.item_attributes.has_name": "UNLOCALIZED: has the custom name %1$s",
"create.item_attributes.has_name.inverted": "UNLOCALIZED: does not have the custom name %1$s",
"create.item_attributes.book_author": "UNLOCALIZED: was authored by %1$s",
"create.item_attributes.book_author.inverted": "UNLOCALIZED: was not authored by %1$s",
"create.item_attributes.book_copy_original": "UNLOCALIZED: is an original",
"create.item_attributes.book_copy_original.inverted": "UNLOCALIZED: is not an original",
"create.item_attributes.book_copy_first": "UNLOCALIZED: is a first-generation copy",
"create.item_attributes.book_copy_first.inverted": "UNLOCALIZED: is not a first-generation copy",
"create.item_attributes.book_copy_second": "UNLOCALIZED: is a second-generation copy",
"create.item_attributes.book_copy_second.inverted": "UNLOCALIZED: is not a second-generation copy",
"create.item_attributes.book_copy_tattered": "UNLOCALIZED: is a tattered mess",
"create.item_attributes.book_copy_tattered.inverted": "UNLOCALIZED: is not a tattered mess",
"create.item_attributes.astralsorcery_amulet": "UNLOCALIZED: improves %1$s",
"create.item_attributes.astralsorcery_amulet.inverted": "UNLOCALIZED: does not improve %1$s",
"create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s",
"create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s",
"create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s",
"create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s",
"create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s",
"create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s",
"create.item_attributes.placeable": "É colocavel",
"create.item_attributes.placeable.inverted": "Não é colocavel",
"create.item_attributes.consumable": "É comestivel",
"create.item_attributes.consumable.inverted": "Não é comestivel",
"create.item_attributes.fluid_container": "Pode armazenar fluidos",
"create.item_attributes.fluid_container.inverted": "Não pode armazenar fluidos",
"create.item_attributes.enchanted": "Está encantado",
"create.item_attributes.enchanted.inverted": "Não está encantado",
"create.item_attributes.max_enchanted": "Está encantado no nível máximo",
"create.item_attributes.max_enchanted.inverted": "Não está encantado no nível maximo",
"create.item_attributes.renamed": "Tem nome customizado",
"create.item_attributes.renamed.inverted": "Não tem nome customizado",
"create.item_attributes.damaged": "Está danificado",
"create.item_attributes.damaged.inverted": "Não está danificado",
"create.item_attributes.badly_damaged": "Está severamente danificado",
"create.item_attributes.badly_damaged.inverted": "Não esta severamente danificado",
"create.item_attributes.not_stackable": "Não pode ser empilhado",
"create.item_attributes.not_stackable.inverted": "Pode ser empilhado",
"create.item_attributes.equipable": "Pode ser equipado",
"create.item_attributes.equipable.inverted": "Não pode ser equipado",
"create.item_attributes.furnace_fuel": "è combustivel",
"create.item_attributes.furnace_fuel.inverted": "Não é combustivel",
"create.item_attributes.washable": "Pode ser lavado",
"create.item_attributes.washable.inverted": "Não pode ser lavado",
"create.item_attributes.hauntable": "Pode ser amaldiçoado",
"create.item_attributes.hauntable.inverted": "Não pode ser amaldiçoado",
"create.item_attributes.crushable": "Pode ser triturado",
"create.item_attributes.crushable.inverted": "Não pode ser triturado",
"create.item_attributes.smeltable": "Pode ser fundido",
"create.item_attributes.smeltable.inverted": "Não pode ser fundido",
"create.item_attributes.smokable": "Pode ser defumado",
"create.item_attributes.smokable.inverted": "Não pode ser defumado",
"create.item_attributes.blastable": "È fundível no alto-forno",
"create.item_attributes.blastable.inverted": "Não é fundível no alto-forno",
"create.item_attributes.shulker_level": "O shulker é %1$s",
"create.item_attributes.shulker_level.inverted": "O shulker não é %1$s",
"create.item_attributes.shulker_level.full": "Cheio",
"create.item_attributes.shulker_level.empty": "Vazio",
"create.item_attributes.shulker_level.partial": "Parcialmente cheio",
"create.item_attributes.in_tag": "è marcado %1$s",
"create.item_attributes.in_tag.inverted": "Não é marcado %1$s",
"create.item_attributes.in_item_group": "Está no grupo '%1$s'",
"create.item_attributes.in_item_group.inverted": "Não esta no grupo '%1$s'",
"create.item_attributes.added_by": "Foi adicionado por %1$s",
"create.item_attributes.added_by.inverted": "Não foi adicionado por %1$s",
"create.item_attributes.has_enchant": "Está encantado com %1$s",
"create.item_attributes.has_enchant.inverted": "Não esta encantado com %1$s",
"create.item_attributes.color": "Esta tingido de %1$s",
"create.item_attributes.color.inverted": "Não está tingido de %1$s",
"create.item_attributes.has_fluid": "Contem %1$s",
"create.item_attributes.has_fluid.inverted": "Não contem %1$s",
"create.item_attributes.has_name": "Tem o nome %1$s",
"create.item_attributes.has_name.inverted": "Não tem o nome %1$s",
"create.item_attributes.book_author": "Tem a autoria de %1$s",
"create.item_attributes.book_author.inverted": "Não tem a autoria de %1$s",
"create.item_attributes.book_copy_original": "É original",
"create.item_attributes.book_copy_original.inverted": "Não é original",
"create.item_attributes.book_copy_first": "É uma cópia da primeira geração",
"create.item_attributes.book_copy_first.inverted": "Não é uma copia de primeira geração",
"create.item_attributes.book_copy_second": "É uma cópia de segunda geração",
"create.item_attributes.book_copy_second.inverted": "Não é uma copia de segunda geração",
"create.item_attributes.book_copy_tattered": "É uma bagunça esfarrapada",
"create.item_attributes.book_copy_tattered.inverted": "Não é uma bagunça esfarrapada",
"create.item_attributes.astralsorcery_amulet": "Melhora %1$s",
"create.item_attributes.astralsorcery_amulet.inverted": "Não melhora %1$s",
"create.item_attributes.astralsorcery_constellation": "Esta sintonizado a %1$s",
"create.item_attributes.astralsorcery_constellation.inverted": "Não esta sintonizado a %1$s",
"create.item_attributes.astralsorcery_crystal": "Tem atributos de cristais %1$s",
"create.item_attributes.astralsorcery_crystal.inverted": "Não tem atributos de cristais %1$s",
"create.item_attributes.astralsorcery_perk_gem": " %1$s Tem um atributo de benefio",
"create.item_attributes.astralsorcery_perk_gem.inverted": "%1$s Não tem um atributo de benefio",
"create.gui.attribute_filter.no_selected_attributes": "UNLOCALIZED: No attributes selected",
"create.gui.attribute_filter.selected_attributes": "UNLOCALIZED: Selected attributes:",
"create.gui.attribute_filter.add_attribute": "UNLOCALIZED: Add attribute to List",
"create.gui.attribute_filter.add_inverted_attribute": "UNLOCALIZED: Add opposite attribute to List",
"create.gui.attribute_filter.allow_list_disjunctive": "UNLOCALIZED: Allow-List (Any)",
"create.gui.attribute_filter.allow_list_disjunctive.description": "UNLOCALIZED: Items pass if they have any of the selected attributes.",
"create.gui.attribute_filter.allow_list_conjunctive": "UNLOCALIZED: Allow-List (All)",
"create.gui.attribute_filter.allow_list_conjunctive.description": "UNLOCALIZED: Items pass only if they have ALL of the selected attributes.",
"create.gui.attribute_filter.deny_list": "UNLOCALIZED: Deny-List",
"create.gui.attribute_filter.deny_list.description": "UNLOCALIZED: Items pass if they do NOT have any of the selected attributes.",
"create.gui.attribute_filter.add_reference_item": "UNLOCALIZED: Add Reference Item",
"create.gui.attribute_filter.no_selected_attributes": "Nenhum atributo selecionado",
"create.gui.attribute_filter.selected_attributes": "Atributos selecionados:",
"create.gui.attribute_filter.add_attribute": "Adicionar atributo a lista",
"create.gui.attribute_filter.add_inverted_attribute": "Adicionar atributo oposto a lista",
"create.gui.attribute_filter.allow_list_disjunctive": "Lista de permissão (Qualquer)",
"create.gui.attribute_filter.allow_list_disjunctive.description": "Itens passam se eles tiverem qualquer atributo selecionado.",
"create.gui.attribute_filter.allow_list_conjunctive": "Lista de permissão (Todos)",
"create.gui.attribute_filter.allow_list_conjunctive.description": "Itens passam se eles tiverem TODOS atributos selecionados.",
"create.gui.attribute_filter.deny_list": "lista de negação",
"create.gui.attribute_filter.deny_list.description": "Itens passam se eles NÃO tiverem qualquer atributo selecionado.",
"create.gui.attribute_filter.add_reference_item": "Adicionar item referência",
"create.tooltip.holdForDescription": "UNLOCALIZED: Hold [%1$s] for Summary",
"create.tooltip.holdForControls": "UNLOCALIZED: Hold [%1$s] for Controls",
"create.tooltip.keyShift": "UNLOCALIZED: Shift",
"create.tooltip.keyCtrl": "UNLOCALIZED: Ctrl",
"create.tooltip.speedRequirement": "UNLOCALIZED: Speed Requirement: %1$s",
"create.tooltip.speedRequirement.none": "UNLOCALIZED: None",
"create.tooltip.speedRequirement.slow": "UNLOCALIZED: Slow",
"create.tooltip.speedRequirement.medium": "UNLOCALIZED: Moderate",
"create.tooltip.speedRequirement.fast": "UNLOCALIZED: Fast",
"create.tooltip.stressImpact": "UNLOCALIZED: Kinetic Stress Impact: %1$s",
"create.tooltip.stressImpact.low": "UNLOCALIZED: Low",
"create.tooltip.stressImpact.medium": "UNLOCALIZED: Moderate",
"create.tooltip.stressImpact.high": "UNLOCALIZED: High",
"create.tooltip.stressImpact.overstressed": "UNLOCALIZED: Overstressed",
"create.tooltip.capacityProvided": "UNLOCALIZED: Kinetic Stress Capacity: %1$s",
"create.tooltip.capacityProvided.low": "UNLOCALIZED: Small",
"create.tooltip.capacityProvided.medium": "UNLOCALIZED: Medium",
"create.tooltip.capacityProvided.high": "UNLOCALIZED: Large",
"create.tooltip.generationSpeed": "UNLOCALIZED: Generates at %1$s %2$s",
"create.tooltip.analogStrength": "UNLOCALIZED: Analog Strength: %1$s/15",
"create.tooltip.holdForDescription": "Segure [%1$s] para o sumário",
"create.tooltip.holdForControls": "Segure [%1$s] para os controles",
"create.tooltip.keyShift": "Shift",
"create.tooltip.keyCtrl": "Ctrl",
"create.tooltip.speedRequirement": "Requerimento de velocidade: %1$s",
"create.tooltip.speedRequirement.none": "Nenhum",
"create.tooltip.speedRequirement.slow": "Devagar",
"create.tooltip.speedRequirement.medium": "Modereado",
"create.tooltip.speedRequirement.fast": "Rapido",
"create.tooltip.stressImpact": "Impacto de stress: %1$s",
"create.tooltip.stressImpact.low": " Baixo",
"create.tooltip.stressImpact.medium": " Moderado",
"create.tooltip.stressImpact.high": " Alto",
"create.tooltip.stressImpact.overstressed": ": Sobre estresse",
"create.tooltip.capacityProvided": "Capacidade de stress cinético: %1$s",
"create.tooltip.capacityProvided.low": " Pequeno",
"create.tooltip.capacityProvided.medium": " Médio",
"create.tooltip.capacityProvided.high": " Grande",
"create.tooltip.generationSpeed": " Gera em %1$s %2$s",
"create.tooltip.analogStrength": " Força analogica: %1$s/15",
"create.mechanical_arm.extract_from": "UNLOCALIZED: Take items from %1$s",
"create.mechanical_arm.deposit_to": "UNLOCALIZED: Deposit items to %1$s",
"create.mechanical_arm.summary": "UNLOCALIZED: Mechanical Arm has %1$s input(s) and %2$s output(s).",
"create.mechanical_arm.points_outside_range": "UNLOCALIZED: %1$s selected interaction point(s) removed due to range limitations.",
"create.mechanical_arm.extract_from": " Pegar itens de %1$s",
"create.mechanical_arm.deposit_to": " Depositar itens para %1$s",
"create.mechanical_arm.summary": "Braço mecânico tem %1$s entrada(s) e %2$s saida(s).",
"create.mechanical_arm.points_outside_range": "%1$s Ponto(s) de interação removidos pelas limitações de alcance.",
"create.weighted_ejector.target_set": "UNLOCALIZED: Target Selected",
"create.weighted_ejector.target_not_valid": "UNLOCALIZED: Ejecting to Adjacent block (Target was not Valid)",
"create.weighted_ejector.no_target": "UNLOCALIZED: Ejecting to Adjacent block (No Target was Selected)",
"create.weighted_ejector.targeting": "UNLOCALIZED: Ejecting to [%1$s,%2$s,%3$s]",
"create.weighted_ejector.stack_size": "UNLOCALIZED: Ejected Stack Size",
"create.weighted_ejector.target_set": "Alvo selecionado",
"create.weighted_ejector.target_not_valid": "Ejetando para o bloco adjacente (Alvo não foi valido)",
"create.weighted_ejector.no_target": "Ejetando para o bloco adjacente (Nenhum alvo foi selecionado)",
"create.weighted_ejector.targeting": "Ejetando para [%1$s,%2$s,%3$s]",
"create.weighted_ejector.stack_size": "Tamanho da pilha ejetada",
"create.logistics.when_multiple_outputs_available": "UNLOCALIZED: When Multiple Outputs Available",
"create.logistics.when_multiple_outputs_available": "Quando multiplas saidas selecionadas",
"create.mechanical_arm.selection_mode.round_robin": "UNLOCALIZED: Round Robin",
"create.mechanical_arm.selection_mode.forced_round_robin": "UNLOCALIZED: Forced Round Robin",
"create.mechanical_arm.selection_mode.prefer_first": "UNLOCALIZED: Prefer First Target",
"create.mechanical_arm.selection_mode.round_robin": "Rodízio",
"create.mechanical_arm.selection_mode.forced_round_robin": "Rodízio forçado",
"create.mechanical_arm.selection_mode.prefer_first": "Preferir primeiro alvo",
"create.tunnel.selection_mode.split": "UNLOCALIZED: Split",
"create.tunnel.selection_mode.forced_split": "UNLOCALIZED: Forced Split",
"create.tunnel.selection_mode.round_robin": "UNLOCALIZED: Round Robin",
"create.tunnel.selection_mode.forced_round_robin": "UNLOCALIZED: Forced Round Robin",
"create.tunnel.selection_mode.prefer_nearest": "UNLOCALIZED: Prefer Nearest",
"create.tunnel.selection_mode.randomize": "UNLOCALIZED: Randomize",
"create.tunnel.selection_mode.synchronize": "UNLOCALIZED: Synchronize Inputs",
"create.tunnel.selection_mode.split": "Dividir",
"create.tunnel.selection_mode.forced_split": "Divisão forçada",
"create.tunnel.selection_mode.round_robin": "Rodízio",
"create.tunnel.selection_mode.forced_round_robin": "Rodízio forçado",
"create.tunnel.selection_mode.prefer_nearest": "Preferir o mais perto",
"create.tunnel.selection_mode.randomize": "Aleatorizar",
"create.tunnel.selection_mode.synchronize": "Sincronizar as entradas",
"create.tooltip.chute.header": "UNLOCALIZED: Chute Information",
"create.tooltip.chute.items_move_down": "UNLOCALIZED: Items move Downward",
"create.tooltip.chute.items_move_up": "UNLOCALIZED: Items move Upward",
"create.tooltip.chute.no_fans_attached": "UNLOCALIZED: No attached fans",
"create.tooltip.chute.fans_push_up": "UNLOCALIZED: Fans push from Below",
"create.tooltip.chute.fans_push_down": "UNLOCALIZED: Fans push from Above",
"create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above",
"create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below",
"create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s",
"create.tooltip.brass_tunnel.contains": "UNLOCALIZED: Currently distributing:",
"create.tooltip.brass_tunnel.contains_entry": "UNLOCALIZED: > %1$s x%2$s",
"create.tooltip.brass_tunnel.retrieve": "UNLOCALIZED: Right-Click to retrieve",
"create.tooltip.chute.header": "Informação da calha",
"create.tooltip.chute.items_move_down": "Itens movimentam para baixo",
"create.tooltip.chute.items_move_up": "Itens movem para cima",
"create.tooltip.chute.no_fans_attached": "Não conectado com um ventilador",
"create.tooltip.chute.fans_push_up": "Ventiladores sopram de baixo",
"create.tooltip.chute.fans_push_down": "Ventiladores sopram de cima",
"create.tooltip.chute.fans_pull_up": "Ventiladores sugam de cima",
"create.tooltip.chute.fans_pull_down": "Ventiladores sugam de baixo",
"create.tooltip.chute.contains": "Contem: %1$s x%2$s",
"create.tooltip.brass_tunnel.contains": "Distribuindo:",
"create.tooltip.brass_tunnel.contains_entry": " > %1$s x%2$s",
"create.tooltip.brass_tunnel.retrieve": "Clique direito para recuperar item",
"create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active",
"create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key",
"create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s",
"create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1",
"create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2",
"create.linked_controller.bind_mode": "Modo de vinculação",
"create.linked_controller.press_keybind": "Aperte %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, para vincular essa frequencia para tecla respectiva",
"create.linked_controller.key_bound": "Frequência vinculada com %1$s",
"create.linked_controller.frequency_slot_1": "Tecla: %1$s, Freq. #1",
"create.linked_controller.frequency_slot_2": "Tecla: %1$s, Freq. #2",
"create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"create.crafting_blueprint.crafting_slot": "Slot de ingrediente",
"create.crafting_blueprint.filter_items_viable": "Filtros avançados são viaveis",
"create.crafting_blueprint.display_slot": "Slot de exibição",
"create.crafting_blueprint.inferred": "Deduzido pela receita",
"create.crafting_blueprint.manually_assigned": "Designado manualmente",
"create.crafting_blueprint.secondary_display_slot": "Slot de exibição secundario",
"create.crafting_blueprint.optional": "Opcional",
"create.potato_cannon.ammo.attack_damage": "UNLOCALIZED: %1$s Attack Damage",
"create.potato_cannon.ammo.reload_ticks": "UNLOCALIZED: %1$s Reload Ticks",
"create.potato_cannon.ammo.knockback": "UNLOCALIZED: %1$s Knockback",
"create.potato_cannon.ammo.attack_damage": " %1$s Dano de ataque",
"create.potato_cannon.ammo.reload_ticks": " %1$s Velocidade de recarregamento",
"create.potato_cannon.ammo.knockback": " %1$s Repulsão do projetil",
"create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply",
"create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.",
"create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets",
"create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.",
"create.hint.empty_bearing.title": "UNLOCALIZED: Update Bearing",
"create.hint.empty_bearing": "UNLOCALIZED: _Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.",
"create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow",
"create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.",
"create.hint.hose_pulley.title": "Abastecimento sem fundo",
"create.hint.hose_pulley": "O corpo de fluido selecionado é considerado infinito.",
"create.hint.mechanical_arm_no_targets.title": "Sem alvos",
"create.hint.mechanical_arm_no_targets": "Aparentemente esse _Braço_ _Mecânico_ não foi designado nenhum _alvo._ Selecione esteiras, depósitos, funis e outros blocos com o _botão direito do mouse_ enquanto _segurando_ o _Braço_ _Mecanico_ na sua _mão_.",
"create.hint.empty_bearing.title": "Atualizar o rolamento",
"create.hint.empty_bearing": " _clique com o botão direito_ o rolamento com a _mão_ _vazia_ para _conectar_ a estrutura que você construiu não frente disso.",
"create.hint.full_deployer.title": "Implantador transbordando de itens",
"create.hint.full_deployer": "Aparenta que esse _inplantador_ contém _itens_ em _excesso_ que precisam ser _extraídos._ Use um _funil,_ _funil de andesito/latão_ ou outros meios para extrair os itens excedentes.",
"create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train",
"create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.",
@ -1551,7 +1551,7 @@
"create.super_glue.not_enough": "UNLOCALIZED: Not enough glue in inventory",
"create.super_glue.sucess": "UNLOCALIZED: Applying Glue...",
"create.gui.config.overlay1": "UNLOCALIZED: Hi :)",
"create.gui.config.overlay1": "Oi :)",
"create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay",
"create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse",
"create.gui.config.overlay4": "UNLOCALIZED: to move this preview",
@ -1560,62 +1560,62 @@
"create.gui.config.overlay7": "UNLOCALIZED: Run /create overlay reset",
"create.gui.config.overlay8": "UNLOCALIZED: to reset to the default position",
"create.command.killTPSCommand": "UNLOCALIZED: killtps",
"create.command.killTPSCommand.status.slowed_by.0": "UNLOCALIZED: [Create]: Server tick is currently slowed by %s ms :o",
"create.command.killTPSCommand.status.slowed_by.1": "UNLOCALIZED: [Create]: Server tick is slowed by %s ms now >:)",
"create.command.killTPSCommand.status.slowed_by.2": "UNLOCALIZED: [Create]: Server tick is back to regular speed :D",
"create.command.killTPSCommand.status.usage.0": "UNLOCALIZED: [Create]: use /killtps stop to bring back server tick to regular speed",
"create.command.killTPSCommand.status.usage.1": "UNLOCALIZED: [Create]: use /killtps start <tickTime> to artificially slow down the server tick",
"create.command.killTPSCommand.argument.tickTime": "UNLOCALIZED: tickTime",
"create.command.killTPSCommand": " killtps",
"create.command.killTPSCommand.status.slowed_by.0": " [Create]: Server tick is currently slowed by %s ms :o",
"create.command.killTPSCommand.status.slowed_by.1": " [Create]: Server tick is slowed by %s ms now >:)",
"create.command.killTPSCommand.status.slowed_by.2": " [Create]: Server tick is back to regular speed :D",
"create.command.killTPSCommand.status.usage.0": " [Create]: use /killtps stop to bring back server tick to regular speed",
"create.command.killTPSCommand.status.usage.1": " [Create]: use /killtps start <tickTime> to artificially slow down the server tick",
"create.command.killTPSCommand.argument.tickTime": "tickTime",
"create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up",
"create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world",
"create.contraption.minecart_contraption_too_big": "Essa engenhoca de carrinho aparenta ser muita grande para pegar",
"create.contraption.minecart_contraption_illegal_pickup": "Uma força mistica esta segurando esta engenhoca de carrinho",
"_": "->------------------------] Subtitles [------------------------<-",
"create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops",
"create.subtitle.peculiar_bell_use": "UNLOCALIZED: Peculiar Bell tolls",
"create.subtitle.mixing": "UNLOCALIZED: Mixing noises",
"create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks",
"create.subtitle.fwoomp": "UNLOCALIZED: Potato Launcher fwoomps",
"create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps",
"create.subtitle.sanding_long": "UNLOCALIZED: Sanding noises",
"create.subtitle.crushing_1": "UNLOCALIZED: Crushing noises",
"create.subtitle.depot_slide": "UNLOCALIZED: Item slides",
"create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates",
"create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel flaps",
"create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings",
"create.subtitle.haunted_bell_use": "UNLOCALIZED: Haunted Bell tolls",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts",
"create.subtitle.controller_put": "UNLOCALIZED: Controller thumps",
"create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns",
"create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks",
"create.subtitle.sanding_short": "UNLOCALIZED: Sanding noises",
"create.subtitle.contraption_disassemble": "Engenhoca para",
"create.subtitle.peculiar_bell_use": "Sino peculiar toca",
"create.subtitle.mixing": "Sons de mistura",
"create.subtitle.mechanical_press_activation_belt": "Bonks da prensa mecanica",
"create.subtitle.fwoomp": "Fwoomps do canhão de batata",
"create.subtitle.worldshaper_place": "Zaps do terraformador",
"create.subtitle.sanding_long": "Sons de lixa",
"create.subtitle.crushing_1": "Sons de trituração",
"create.subtitle.depot_slide": "Item escorrega",
"create.subtitle.saw_activate_stone": "Serra mecânica ativa",
"create.subtitle.blaze_munch": "Queimador de blazer mastiga",
"create.subtitle.funnel_flap": "Abas do funil batendo",
"create.subtitle.schematicannon_finish": "Ding do canhão de esquema",
"create.subtitle.haunted_bell_use": "Sino assombrado toca",
"create.subtitle.scroll_value": "click do scroll",
"create.subtitle.crafter_craft": "Fabricador fábrica",
"create.subtitle.controller_put": "Thumps do controle",
"create.subtitle.cranking": "Manivela gira",
"create.subtitle.wrench_remove": "Componente quebra",
"create.subtitle.sanding_short": "Sons de lixa",
"create.subtitle.whistle": "UNLOCALIZED: Whistling",
"create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble",
"create.subtitle.slime_added": "UNLOCALIZED: Slime squishes",
"create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used",
"create.subtitle.potato_hit": "UNLOCALIZED: Vegetable impacts",
"create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates",
"create.subtitle.cogs": "tremer da rodas dentadas",
"create.subtitle.slime_added": "Slime sendo espremido",
"create.subtitle.wrench_rotate": "Chave inglesa usada",
"create.subtitle.potato_hit": "Impacto vegetal",
"create.subtitle.saw_activate_wood": "Serra mecânica ativa",
"create.subtitle.whistle_high": "UNLOCALIZED: High whistling",
"create.subtitle.whistle_train": "UNLOCALIZED: Whistling",
"create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens",
"create.subtitle.haunted_bell_convert": "Sino assombrado acorda",
"create.subtitle.whistle_train_high": "UNLOCALIZED: High whistling",
"create.subtitle.whistle_train_low": "UNLOCALIZED: Low whistling",
"create.subtitle.deny": "UNLOCALIZED: Declining boop",
"create.subtitle.controller_click": "UNLOCALIZED: Controller clicks",
"create.subtitle.deny": "Boop de negação",
"create.subtitle.controller_click": "Clicks do controle",
"create.subtitle.whistle_low": "UNLOCALIZED: Low whistling",
"create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.controller_take": "UNLOCALIZED: Lectern empties",
"create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs",
"create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves",
"create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks",
"create.subtitle.depot_plop": "UNLOCALIZED: Item lands",
"create.subtitle.confirm": "UNLOCALIZED: Affirmative ding",
"create.subtitle.schematicannon_launch_block": "Canhão de esquema atira",
"create.subtitle.copper_armor_equip": "Tilintar dos equipamentos de mergulho",
"create.subtitle.controller_take": "Atril esvaziado",
"create.subtitle.mechanical_press_activation": "Clang da prensa mecânica",
"create.subtitle.contraption_assemble": "Engenhoca move",
"create.subtitle.crafter_click": "Clicks do fabricador",
"create.subtitle.depot_plop": "Item pousa",
"create.subtitle.confirm": "Ding afirmativo",
"_": "->------------------------] Item Descriptions [------------------------<-",

View file

@ -8,11 +8,7 @@
"results": [
{
"item": "minecraft:gold_nugget",
"count": 7
},
{
"item": "minecraft:gold_nugget",
"chance": 0.5
"count": 18
},
{
"item": "create:experience_nugget",

View file

@ -8,11 +8,14 @@ import org.apache.logging.log4j.Logger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour;
import com.simibubi.create.compat.Mods;
import com.simibubi.create.compat.curios.Curios;
import com.simibubi.create.content.CreateItemGroup;
import com.simibubi.create.content.contraptions.TorquePropagator;
import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes;
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler;
import com.simibubi.create.content.logistics.block.display.AllDisplayBehaviours;
import com.simibubi.create.content.logistics.block.mechanicalArm.AllArmInteractionPointTypes;
import com.simibubi.create.content.logistics.trains.GlobalRailwayManager;
import com.simibubi.create.content.palettes.AllPaletteBlocks;
import com.simibubi.create.content.palettes.PalettesItemGroup;
@ -98,6 +101,7 @@ public class Create {
AllMovementBehaviours.register();
AllDisplayBehaviours.register();
AllInteractionBehaviours.register();
AllArmInteractionPointTypes.register();
AllWorldFeatures.register();
AllEnchantments.register();
AllConfigs.register(modLoadingContext);
@ -120,6 +124,8 @@ public class Create {
modEventBus.addGenericListener(DataSerializerEntry.class, AllEntityDataSerializers::register);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
Mods.CURIOS.executeIfInstalled(() -> Curios::init);
}
public static void init(final FMLCommonSetupEvent event) {

View file

@ -0,0 +1,447 @@
package com.simibubi.create.api.connectivity;
import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity;
import com.simibubi.create.foundation.tileEntity.IMultiTileContainer;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.PriorityQueue;
import java.util.Set;
public class ConnectivityHandler {
public static <T extends BlockEntity & IMultiTileContainer> void formMulti(T be) {
SearchCache<T> cache = new SearchCache<>();
List<T> frontier = new ArrayList<>();
frontier.add(be);
formMulti(be.getType(), be.getLevel(), cache, frontier);
}
private static <T extends BlockEntity & IMultiTileContainer> void formMulti(BlockEntityType<?> type,
BlockGetter level, SearchCache<T> cache, List<T> frontier) {
PriorityQueue<Pair<Integer, T>> creationQueue = makeCreationQueue();
Set<BlockPos> visited = new HashSet<>();
Direction.Axis mainAxis = frontier.get(0)
.getMainConnectionAxis();
// essentially, if it's a vertical multi then the search won't be restricted by
// Y
// alternately, a horizontal multi search shouldn't be restricted by X or Z
int minX = (mainAxis == Direction.Axis.Y ? Integer.MAX_VALUE : Integer.MIN_VALUE);
int minY = (mainAxis != Direction.Axis.Y ? Integer.MAX_VALUE : Integer.MIN_VALUE);
int minZ = (mainAxis == Direction.Axis.Y ? Integer.MAX_VALUE : Integer.MIN_VALUE);
for (T be : frontier) {
BlockPos pos = be.getBlockPos();
minX = Math.min(pos.getX(), minX);
minY = Math.min(pos.getY(), minY);
minZ = Math.min(pos.getZ(), minZ);
}
if (mainAxis == Direction.Axis.Y)
minX -= frontier.get(0)
.getMaxWidth();
if (mainAxis != Direction.Axis.Y)
minY -= frontier.get(0)
.getMaxWidth();
if (mainAxis == Direction.Axis.Y)
minZ -= frontier.get(0)
.getMaxWidth();
while (!frontier.isEmpty()) {
T part = frontier.remove(0);
BlockPos partPos = part.getBlockPos();
if (visited.contains(partPos))
continue;
visited.add(partPos);
int amount = tryToFormNewMulti(part, cache, true);
if (amount > 1) {
creationQueue.add(Pair.of(amount, part));
}
for (Direction.Axis axis : Iterate.axes) {
Direction dir = Direction.get(Direction.AxisDirection.NEGATIVE, axis);
BlockPos next = partPos.relative(dir);
if (next.getX() <= minX || next.getY() <= minY || next.getZ() <= minZ)
continue;
if (visited.contains(next))
continue;
T nextBe = partAt(type, level, next);
if (nextBe == null)
continue;
if (nextBe.isRemoved())
continue;
frontier.add(nextBe);
}
}
visited.clear();
while (!creationQueue.isEmpty()) {
Pair<Integer, T> next = creationQueue.poll();
T toCreate = next.getValue();
if (visited.contains(toCreate.getBlockPos()))
continue;
visited.add(toCreate.getBlockPos());
tryToFormNewMulti(toCreate, cache, false);
}
}
private static <T extends BlockEntity & IMultiTileContainer> int tryToFormNewMulti(T be, SearchCache<T> cache,
boolean simulate) {
int bestWidth = 1;
int bestAmount = -1;
if (!be.isController())
return 0;
int radius = be.getMaxWidth();
for (int w = 1; w <= radius; w++) {
int amount = tryToFormNewMultiOfWidth(be, w, cache, true);
if (amount < bestAmount)
continue;
bestWidth = w;
bestAmount = amount;
}
if (!simulate) {
int beWidth = be.getWidth();
if (beWidth == bestWidth && beWidth * beWidth * be.getHeight() == bestAmount)
return bestAmount;
splitMultiAndInvalidate(be, cache, false);
if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank())
ifluid.setTankSize(0, bestAmount);
tryToFormNewMultiOfWidth(be, bestWidth, cache, false);
be.preventConnectivityUpdate();
be.setWidth(bestWidth);
be.setHeight(bestAmount / bestWidth / bestWidth);
be.notifyMultiUpdated();
}
return bestAmount;
}
private static <T extends BlockEntity & IMultiTileContainer> int tryToFormNewMultiOfWidth(T be, int width,
SearchCache<T> cache, boolean simulate) {
int amount = 0;
int height = 0;
BlockEntityType<?> type = be.getType();
Level level = be.getLevel();
if (level == null)
return 0;
BlockPos origin = be.getBlockPos();
// optional fluid handling
IFluidTank beTank = null;
FluidStack fluid = FluidStack.EMPTY;
if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank()) {
beTank = ifluid.getTank(0);
fluid = beTank.getFluid();
}
Direction.Axis axis = be.getMainConnectionAxis();
Search: for (int yOffset = 0; yOffset < be.getMaxLength(axis, width); yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos = switch (axis) {
case X -> origin.offset(yOffset, xOffset, zOffset);
case Y -> origin.offset(xOffset, yOffset, zOffset);
case Z -> origin.offset(xOffset, zOffset, yOffset);
};
Optional<T> part = cache.getOrCache(type, level, pos);
if (part.isEmpty())
break Search;
T controller = part.get();
int otherWidth = controller.getWidth();
if (otherWidth > width)
break Search;
if (otherWidth == width && controller.getHeight() == be.getMaxLength(axis, width))
break Search;
Direction.Axis conAxis = controller.getMainConnectionAxis();
if (axis != conAxis)
break Search;
BlockPos conPos = controller.getBlockPos();
if (!conPos.equals(origin)) {
if (axis == Direction.Axis.Y) { // vertical multi, like a FluidTank
if (conPos.getX() < origin.getX())
break Search;
if (conPos.getZ() < origin.getZ())
break Search;
if (conPos.getX() + otherWidth > origin.getX() + width)
break Search;
if (conPos.getZ() + otherWidth > origin.getZ() + width)
break Search;
} else { // horizontal multi, like an ItemVault
if (axis == Direction.Axis.Z && conPos.getX() < origin.getX())
break Search;
if (conPos.getY() < origin.getY())
break Search;
if (axis == Direction.Axis.X && conPos.getZ() < origin.getZ())
break Search;
if (axis == Direction.Axis.Z && conPos.getX() + otherWidth > origin.getX() + width)
break Search;
if (conPos.getY() + otherWidth > origin.getY() + width)
break Search;
if (axis == Direction.Axis.X && conPos.getZ() + otherWidth > origin.getZ() + width)
break Search;
}
}
if (controller instanceof IMultiTileContainer.Fluid ifluidCon && ifluidCon.hasTank()) {
FluidStack otherFluid = ifluidCon.getFluid(0);
if (!fluid.isEmpty() && !otherFluid.isEmpty() && !fluid.isFluidEqual(otherFluid))
break Search;
}
}
}
amount += width * width;
height++;
}
if (simulate)
return amount;
Object extraData = be.getExtraData();
for (int yOffset = 0; yOffset < height; yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos = switch (axis) {
case X -> origin.offset(yOffset, xOffset, zOffset);
case Y -> origin.offset(xOffset, yOffset, zOffset);
case Z -> origin.offset(xOffset, zOffset, yOffset);
};
T part = partAt(type, level, pos);
if (part == null)
continue;
if (part == be)
continue;
extraData = be.modifyExtraData(extraData);
if (part instanceof IMultiTileContainer.Fluid ifluidPart && ifluidPart.hasTank()) {
IFluidTank tankAt = ifluidPart.getTank(0);
FluidStack fluidAt = tankAt.getFluid();
if (!fluidAt.isEmpty()) {
// making this generic would be a rather large mess, unfortunately
if (beTank != null && fluid.isEmpty()
&& beTank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank) {
((CreativeFluidTankTileEntity.CreativeSmartFluidTank) beTank)
.setContainedFluid(fluidAt);
}
if (be instanceof IMultiTileContainer.Fluid ifluidBE && ifluidBE.hasTank()
&& beTank != null) {
beTank.fill(fluidAt, IFluidHandler.FluidAction.EXECUTE);
}
}
tankAt.drain(tankAt.getCapacity(), IFluidHandler.FluidAction.EXECUTE);
}
splitMultiAndInvalidate(part, cache, false);
part.setController(origin);
part.preventConnectivityUpdate();
cache.put(pos, be);
part.setHeight(height);
part.setWidth(width);
part.notifyMultiUpdated();
}
}
}
be.setExtraData(extraData);
be.notifyMultiUpdated();
return amount;
}
public static <T extends BlockEntity & IMultiTileContainer> void splitMulti(T be) {
splitMultiAndInvalidate(be, null, false);
}
// tryReconnect helps whenever only a few tanks have been removed
private static <T extends BlockEntity & IMultiTileContainer> void splitMultiAndInvalidate(T be,
@Nullable SearchCache<T> cache, boolean tryReconnect) {
Level level = be.getLevel();
if (level == null)
return;
be = be.getControllerTE();
if (be == null)
return;
int height = be.getHeight();
int width = be.getWidth();
if (width == 1 && height == 1)
return;
BlockPos origin = be.getBlockPos();
List<T> frontier = new ArrayList<>();
Direction.Axis axis = be.getMainConnectionAxis();
// fluid handling, if present
FluidStack toDistribute = FluidStack.EMPTY;
int maxCapacity = 0;
if (be instanceof IMultiTileContainer.Fluid ifluidBE && ifluidBE.hasTank()) {
toDistribute = ifluidBE.getFluid(0);
maxCapacity = ifluidBE.getTankSize(0);
if (!toDistribute.isEmpty() && !be.isRemoved())
toDistribute.shrink(maxCapacity);
ifluidBE.setTankSize(0, 1);
}
for (int yOffset = 0; yOffset < height; yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos = switch (axis) {
case X -> origin.offset(yOffset, xOffset, zOffset);
case Y -> origin.offset(xOffset, yOffset, zOffset);
case Z -> origin.offset(xOffset, zOffset, yOffset);
};
T partAt = partAt(be.getType(), level, pos);
if (partAt == null)
continue;
if (!partAt.getController()
.equals(origin))
continue;
T controllerBE = partAt.getControllerTE();
partAt.setExtraData((controllerBE == null ? null : controllerBE.getExtraData()));
partAt.removeController(true);
if (!toDistribute.isEmpty() && partAt != be) {
FluidStack copy = toDistribute.copy();
IFluidTank tank =
(partAt instanceof IMultiTileContainer.Fluid ifluidPart ? ifluidPart.getTank(0) : null);
// making this generic would be a rather large mess, unfortunately
if (tank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank creativeTank) {
if (creativeTank.isEmpty())
creativeTank.setContainedFluid(toDistribute);
} else {
int split = Math.min(maxCapacity, toDistribute.getAmount());
copy.setAmount(split);
toDistribute.shrink(split);
if (tank != null)
tank.fill(copy, IFluidHandler.FluidAction.EXECUTE);
}
}
if (tryReconnect) {
frontier.add(partAt);
partAt.preventConnectivityUpdate();
}
if (cache != null) {
cache.put(pos, partAt);
}
}
}
}
if (be instanceof IMultiTileContainer.Inventory iinv && iinv.hasInventory()) {
be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
.invalidate();
}
if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank()) {
be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
.invalidate();
}
if (tryReconnect) {
formMulti(be.getType(), level, cache == null ? new SearchCache<>() : cache, frontier);
}
}
private static <T extends BlockEntity & IMultiTileContainer> PriorityQueue<Pair<Integer, T>> makeCreationQueue() {
return new PriorityQueue<>((one, two) -> two.getKey() - one.getKey());
}
@Nullable
public static <T extends BlockEntity & IMultiTileContainer> T partAt(BlockEntityType<?> type, BlockGetter level,
BlockPos pos) {
BlockEntity be = level.getBlockEntity(pos);
if (be != null && be.getType() == type)
return checked(be);
return null;
}
public static <T extends BlockEntity & IMultiTileContainer> boolean isConnected(BlockGetter level, BlockPos pos,
BlockPos other) {
T one = checked(level.getBlockEntity(pos));
T two = checked(level.getBlockEntity(other));
if (one == null || two == null)
return false;
return one.getController()
.equals(two.getController());
}
@Nullable
@SuppressWarnings("unchecked")
private static <T extends BlockEntity & IMultiTileContainer> T checked(BlockEntity be) {
if (be instanceof IMultiTileContainer)
return (T) be;
return null;
}
private static class SearchCache<T extends BlockEntity & IMultiTileContainer> {
Map<BlockPos, Optional<T>> controllerMap;
public SearchCache() {
controllerMap = new HashMap<>();
}
void put(BlockPos pos, T target) {
controllerMap.put(pos, Optional.of(target));
}
void putEmpty(BlockPos pos) {
controllerMap.put(pos, Optional.empty());
}
boolean hasVisited(BlockPos pos) {
return controllerMap.containsKey(pos);
}
Optional<T> getOrCache(BlockEntityType<?> type, BlockGetter level, BlockPos pos) {
if (hasVisited(pos))
return controllerMap.get(pos);
T partAt = partAt(type, level, pos);
if (partAt == null) {
putEmpty(pos);
return Optional.empty();
}
T controller = checked(level.getBlockEntity(partAt.getController()));
if (controller == null) {
putEmpty(pos);
return Optional.empty();
}
put(pos, controller);
return Optional.of(controller);
}
}
}

View file

@ -12,7 +12,8 @@ import net.minecraftforge.fml.ModList;
*/
public enum Mods {
DYNAMICTREES,
TCONSTRUCT;
TCONSTRUCT,
CURIOS;
/**
* @return a boolean of whether the mod is loaded or not based on mod id

View file

@ -0,0 +1,43 @@
package com.simibubi.create.compat.curios;
import java.util.concurrent.atomic.AtomicBoolean;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.contraptions.goggles.GogglesItem;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.InterModComms;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import top.theillusivec4.curios.api.CuriosCapability;
import top.theillusivec4.curios.api.SlotTypeMessage;
import top.theillusivec4.curios.api.SlotTypePreset;
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
public class Curios {
public static void init() {
FMLJavaModLoadingContext.get().getModEventBus().addListener(Curios::onInterModEnqueue);
FMLJavaModLoadingContext.get().getModEventBus().addListener(Curios::onClientSetup);
GogglesItem.addIsWearingPredicate(player -> {
AtomicBoolean hasGoggles = new AtomicBoolean(false);
player.getCapability(CuriosCapability.INVENTORY).ifPresent(handler -> {
ICurioStacksHandler stacksHandler = handler.getCurios().get("head");
if(stacksHandler != null) hasGoggles.set(stacksHandler.getStacks().getStackInSlot(0).getItem() == AllItems.GOGGLES.get());
});
return hasGoggles.get();
});
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FMLJavaModLoadingContext.get().getModEventBus().addListener(CuriosRenderers::onLayerRegister));
}
private static void onInterModEnqueue(final InterModEnqueueEvent event) {
InterModComms.sendTo("curios", SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.HEAD.getMessageBuilder().build());
}
private static void onClientSetup(final FMLClientSetupEvent event) {
CuriosRenderers.register();
}
}

View file

@ -0,0 +1,21 @@
package com.simibubi.create.compat.curios;
import com.simibubi.create.AllItems;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.EntityRenderersEvent;
import top.theillusivec4.curios.api.client.CuriosRendererRegistry;
@OnlyIn(Dist.CLIENT)
public class CuriosRenderers {
public static void register() {
CuriosRendererRegistry.register(AllItems.GOGGLES.get(), () -> new GogglesCurioRenderer(Minecraft.getInstance().getEntityModels().bakeLayer(GogglesCurioRenderer.LAYER)));
}
public static void onLayerRegister(final EntityRenderersEvent.RegisterLayerDefinitions event) {
event.registerLayerDefinition(GogglesCurioRenderer.LAYER, () -> LayerDefinition.create(GogglesCurioRenderer.mesh(), 1, 1));
}
}

View file

@ -0,0 +1,73 @@
package com.simibubi.create.compat.curios;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Vector3f;
import com.simibubi.create.Create;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.CubeDeformation;
import net.minecraft.client.model.geom.builders.CubeListBuilder;
import net.minecraft.client.model.geom.builders.MeshDefinition;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import top.theillusivec4.curios.api.SlotContext;
import top.theillusivec4.curios.api.client.ICurioRenderer;
@OnlyIn(Dist.CLIENT)
public class GogglesCurioRenderer implements ICurioRenderer {
public static final ModelLayerLocation LAYER = new ModelLayerLocation(new ResourceLocation(Create.ID, "goggles"), "goggles");
private final HumanoidModel<LivingEntity> model;
public GogglesCurioRenderer(ModelPart part) {
this.model = new HumanoidModel<>(part);
}
@Override
public <T extends LivingEntity, M extends EntityModel<T>> void render(ItemStack stack, SlotContext slotContext, PoseStack matrixStack, RenderLayerParent<T, M> renderLayerParent, MultiBufferSource renderTypeBuffer, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) {
// Prepare values for transformation
model.setupAnim(slotContext.entity(), limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch);
model.prepareMobModel(slotContext.entity(), limbSwing, limbSwingAmount, partialTicks);
ICurioRenderer.followHeadRotations(slotContext.entity(), model.head);
// Translate and rotate with our head
matrixStack.pushPose();
matrixStack.translate(model.head.x / 16.0, model.head.y / 16.0, model.head.z / 16.0);
matrixStack.mulPose(Vector3f.YP.rotation(model.head.yRot));
matrixStack.mulPose(Vector3f.XP.rotation(model.head.xRot));
// Translate and scale to our head
matrixStack.translate(0, -0.25, 0);
matrixStack.mulPose(Vector3f.ZP.rotationDegrees(180.0f));
matrixStack.scale(0.625f, 0.625f, 0.625f);
if(!slotContext.entity().getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
matrixStack.mulPose(Vector3f.ZP.rotationDegrees(180.0f));
matrixStack.translate(0, -0.25, 0);
}
// Render
Minecraft.getInstance().getItemRenderer().renderStatic(stack, ItemTransforms.TransformType.HEAD, light, OverlayTexture.NO_OVERLAY, matrixStack, renderTypeBuffer, 0);
matrixStack.popPose();
}
public static MeshDefinition mesh() {
CubeListBuilder builder = new CubeListBuilder();
MeshDefinition mesh = HumanoidModel.createMesh(CubeDeformation.NONE, 0);
mesh.getRoot().addOrReplaceChild("head", builder, PartPose.ZERO);
return mesh;
}
}

View file

@ -16,7 +16,7 @@ public class HalfShaftInstance extends SingleRotatingInstance {
@Override
protected Instancer<RotatingData> getModel() {
Direction dir = getShaftDirection();
return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, dir);
return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, dir);
}
protected Direction getShaftDirection() {

View file

@ -39,14 +39,14 @@ public class DrillActorInstance extends ActorInstance {
else
eulerY = facing.toYRot() + ((axis == Direction.Axis.X) ? 180 : 0);
drillHead = material.getModel(AllBlockPartials.DRILL_HEAD, state).createInstance();
drillHead.setPosition(context.localPos)
.setBlockLight(localBlockLight())
.setRotationOffset(0)
.setRotationAxis(0, 0, 1)
.setLocalRotation(new Quaternion(eulerX, eulerY, 0, true))
.setSpeed(getSpeed(facing));
drillHead = material.getModel(AllBlockPartials.DRILL_HEAD)
.createInstance()
.setPosition(context.localPos)
.setBlockLight(localBlockLight())
.setRotationOffset(0)
.setRotationAxis(0, 0, 1)
.setLocalRotation(new Quaternion(eulerX, eulerY, 0, true))
.setSpeed(getSpeed(facing));
}
@Override

View file

@ -21,6 +21,6 @@ public class DrillInstance extends SingleRotatingInstance {
protected Instancer<RotatingData> getModel() {
BlockState referenceState = blockEntity.getBlockState();
Direction facing = referenceState.getValue(BlockStateProperties.FACING);
return getRotatingMaterial().getModel(AllBlockPartials.DRILL_HEAD, referenceState, facing);
return getRotatingMaterial().getModel(AllBlockPartials.DRILL_HEAD, facing);
}
}

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.actors;
import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.Models;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
import com.simibubi.create.AllBlockPartials;
@ -41,7 +42,8 @@ public class HarvesterActorInstance extends ActorInstance {
facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
harvester = material.getModel(AllBlockPartials.HARVESTER_BLADE, state).createInstance();
harvester = material.model(Models.partial(AllBlockPartials.HARVESTER_BLADE))
.createInstance();
horizontalAngle = facing.toYRot() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0);

View file

@ -33,11 +33,11 @@ public class PIInstance {
this.lit = lit;
middle = materialManager.defaultSolid()
.material(Materials.TRANSFORMED)
.getModel(PortableStorageInterfaceRenderer.getMiddleForState(blockState, lit), blockState)
.getModel(PortableStorageInterfaceRenderer.getMiddleForState(blockState, lit))
.createInstance();
top = materialManager.defaultSolid()
.material(Materials.TRANSFORMED)
.getModel(PortableStorageInterfaceRenderer.getTopForState(blockState), blockState)
.getModel(PortableStorageInterfaceRenderer.getTopForState(blockState))
.createInstance();
}
@ -66,7 +66,7 @@ public class PIInstance {
this.lit = lit;
materialManager.defaultSolid()
.material(Materials.TRANSFORMED)
.getModel(PortableStorageInterfaceRenderer.getMiddleForState(blockState, lit), blockState)
.getModel(PortableStorageInterfaceRenderer.getMiddleForState(blockState, lit))
.stealInstance(middle);
}
}

View file

@ -23,7 +23,7 @@ public class MechanicalCrafterInstance extends SingleRotatingInstance {
protected Instancer<RotatingData> getModel() {
Direction facing = blockState.getValue(MechanicalCrafterBlock.HORIZONTAL_FACING);
return getRotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, blockState, facing, rotateToFace(facing));
return getRotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, facing, rotateToFace(facing));
}
private Supplier<PoseStack> rotateToFace(Direction facing) {

View file

@ -31,7 +31,7 @@ public class HandCrankInstance extends SingleRotatingInstance implements Dynamic
facing = blockState.getValue(BlockStateProperties.FACING);
Direction opposite = facing.getOpposite();
Instancer<ModelData> model = getTransformMaterial().getModel(renderedHandle, blockState, opposite);
Instancer<ModelData> model = getTransformMaterial().getModel(renderedHandle, opposite);
crank = model.createInstance();
rotateCrank();

View file

@ -61,8 +61,8 @@ public class DeployerActorInstance extends ActorInstance {
xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0;
zRot = rotatePole ? 90 : 0;
pole = mat.getModel(AllBlockPartials.DEPLOYER_POLE, state).createInstance();
hand = mat.getModel(handPose, state).createInstance();
pole = mat.getModel(AllBlockPartials.DEPLOYER_POLE).createInstance();
hand = mat.getModel(handPose).createInstance();
Direction.Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
shaft = materialManager.defaultSolid()

View file

@ -47,11 +47,11 @@ public class DeployerInstance extends ShaftInstance implements DynamicInstance,
xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0;
zRot = rotatePole ? 90 : 0;
pole = getOrientedMaterial().getModel(AllBlockPartials.DEPLOYER_POLE, blockState).createInstance();
pole = getOrientedMaterial().getModel(AllBlockPartials.DEPLOYER_POLE).createInstance();
currentHand = this.tile.getHandPose();
hand = getOrientedMaterial().getModel(currentHand, blockState).createInstance();
hand = getOrientedMaterial().getModel(currentHand).createInstance();
progress = getProgress(AnimationTickHolder.getPartialTicks());
updateRotation(pole, hand, yRot, xRot, zRot);
@ -64,7 +64,7 @@ public class DeployerInstance extends ShaftInstance implements DynamicInstance,
if (currentHand != handPose) {
currentHand = handPose;
getOrientedMaterial().getModel(currentHand, blockState)
getOrientedMaterial().getModel(currentHand)
.stealInstance(hand);
}
}

View file

@ -25,10 +25,10 @@ public class FanInstance extends KineticTileInstance<EncasedFanTileEntity> {
direction = blockState.getValue(FACING);
opposite = direction.getOpposite();
shaft = getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, opposite).createInstance();
shaft = getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, opposite).createInstance();
fan = modelManager.defaultCutout()
.material(AllMaterialSpecs.ROTATING)
.getModel(AllBlockPartials.ENCASED_FAN_INNER, blockState, opposite)
.getModel(AllBlockPartials.ENCASED_FAN_INNER, opposite)
.createInstance();
setup(shaft);

View file

@ -15,6 +15,6 @@ public class MillStoneCogInstance extends SingleRotatingInstance {
@Override
protected Instancer<RotatingData> getModel() {
return getRotatingMaterial().getModel(AllBlockPartials.MILLSTONE_COG, blockEntity.getBlockState());
return getRotatingMaterial().getModel(AllBlockPartials.MILLSTONE_COG);
}
}

View file

@ -22,13 +22,13 @@ public class MixerInstance extends EncasedCogInstance implements DynamicInstance
super(dispatcher, tile, false);
this.mixer = tile;
mixerHead = getRotatingMaterial().getModel(AllBlockPartials.MECHANICAL_MIXER_HEAD, blockState)
mixerHead = getRotatingMaterial().getModel(AllBlockPartials.MECHANICAL_MIXER_HEAD)
.createInstance();
mixerHead.setRotationAxis(Direction.Axis.Y);
mixerPole = getOrientedMaterial()
.getModel(AllBlockPartials.MECHANICAL_MIXER_POLE, blockState)
.getModel(AllBlockPartials.MECHANICAL_MIXER_POLE)
.createInstance();
@ -42,7 +42,7 @@ public class MixerInstance extends EncasedCogInstance implements DynamicInstance
protected Instancer<RotatingData> getCogModel() {
return materialManager.defaultSolid()
.material(AllMaterialSpecs.ROTATING)
.getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, blockEntity.getBlockState());
.getModel(AllBlockPartials.SHAFTLESS_COGWHEEL);
}
@Override

View file

@ -22,7 +22,7 @@ public class PressInstance extends ShaftInstance implements DynamicInstance {
pressHead = dispatcher.defaultSolid()
.material(Materials.ORIENTED)
.getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState)
.getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD)
.createInstance();
Quaternion q = Vector3f.YP

View file

@ -25,7 +25,7 @@ public class SawInstance extends SingleRotatingInstance {
.isHorizontal()) {
BlockState referenceState = blockState.rotate(blockEntity.getLevel(), blockEntity.getBlockPos(), Rotation.CLOCKWISE_180);
Direction facing = referenceState.getValue(BlockStateProperties.FACING);
return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, referenceState, facing);
return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, facing);
} else {
return getRotatingMaterial().getModel(shaft());
}

View file

@ -5,6 +5,7 @@ import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.content.contraptions.components.actors.AttachedActorBlock;
import com.simibubi.create.content.contraptions.components.actors.HarvesterBlock;
import com.simibubi.create.content.contraptions.components.actors.PloughBlock;
@ -28,10 +29,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pis
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankConnectivityHandler;
import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock;
import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock;
import com.simibubi.create.content.logistics.block.vault.ItemVaultConnectivityHandler;
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
@ -338,9 +337,9 @@ public class BlockMovementChecks {
return direction.getAxis() != state.getValue(SailBlock.FACING)
.getAxis();
if (state.getBlock() instanceof FluidTankBlock)
return FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(direction));
return ConnectivityHandler.isConnected(world, pos, pos.relative(direction));
if (state.getBlock() instanceof ItemVaultBlock)
return ItemVaultConnectivityHandler.isConnected(world, pos, pos.relative(direction));
return ConnectivityHandler.isConnected(world, pos, pos.relative(direction));
if (AllBlocks.STICKER.has(state) && state.getValue(StickerBlock.EXTENDED)) {
return direction == state.getValue(StickerBlock.FACING)
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());

View file

@ -35,7 +35,7 @@ public class BearingInstance<B extends KineticTileEntity & IBearingTileEntity> e
PartialModel top =
bearing.isWoodenTop() ? AllBlockPartials.BEARING_TOP_WOODEN : AllBlockPartials.BEARING_TOP;
topInstance = getOrientedMaterial().getModel(top, blockState).createInstance();
topInstance = getOrientedMaterial().getModel(top).createInstance();
topInstance.setPosition(getInstancePosition()).setRotation(blockOrientation);
}

View file

@ -38,7 +38,7 @@ public class StabilizedBearingInstance extends ActorInstance {
topInstance = materialManager.defaultSolid()
.material(Materials.ORIENTED)
.getModel(AllBlockPartials.BEARING_TOP, blockState)
.getModel(AllBlockPartials.BEARING_TOP)
.createInstance();
int blockLight = localBlockLight();
@ -48,7 +48,7 @@ public class StabilizedBearingInstance extends ActorInstance {
shaft = materialManager.defaultSolid()
.material(AllMaterialSpecs.ROTATING)
.getModel(AllBlockPartials.SHAFT_HALF, blockState, blockState.getValue(BlockStateProperties.FACING).getOpposite())
.getModel(AllBlockPartials.SHAFT_HALF, blockState.getValue(BlockStateProperties.FACING).getOpposite())
.createInstance();
// not rotating so no need to set speed, axis, etc.

View file

@ -17,20 +17,20 @@ public class StickerInstance extends BlockEntityInstance<StickerTileEntity> impl
float lastOffset = Float.NaN;
final Direction facing;
final boolean fakeWorld;
final int offset;
final int extended;
private final ModelData head;
public StickerInstance(MaterialManager modelManager, StickerTileEntity tile) {
super(modelManager, tile);
head = getTransformMaterial().getModel(AllBlockPartials.STICKER_HEAD, blockState).createInstance();
head = getTransformMaterial().getModel(AllBlockPartials.STICKER_HEAD).createInstance();
fakeWorld = tile.getLevel() != Minecraft.getInstance().level;
facing = blockState.getValue(StickerBlock.FACING);
offset = blockState.getValue(StickerBlock.EXTENDED) ? 1 : 0;
extended = blockState.getValue(StickerBlock.EXTENDED) ? 1 : 0;
animateHead(offset);
animateHead(extended);
}
@Override
@ -38,7 +38,7 @@ public class StickerInstance extends BlockEntityInstance<StickerTileEntity> impl
float offset = blockEntity.piston.getValue(AnimationTickHolder.getPartialTicks());
if (fakeWorld)
offset = this.offset;
offset = this.extended;
if (Mth.equal(offset, lastOffset))
return;

View file

@ -30,7 +30,7 @@ public class GantryCarriageInstance extends ShaftInstance implements DynamicInst
super(dispatcher, tile);
gantryCogs = getTransformMaterial()
.getModel(AllBlockPartials.GANTRY_COGS, blockState)
.getModel(AllBlockPartials.GANTRY_COGS)
.createInstance();
facing = blockState.getValue(GantryCarriageBlock.FACING);

View file

@ -162,7 +162,7 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay
OrientedContraptionEntity entity = OrientedContraptionEntity.create(world, contraption, initialOrientation);
if (couplingFound)
entity.setCouplingId(cart.getUUID());
entity.setPos(pos.getX(), pos.getY(), pos.getZ());
entity.setPos(pos.getX() + .5, pos.getY(), pos.getZ() + .5);
world.addFreshEntity(entity);
entity.startRiding(cart);

View file

@ -15,27 +15,27 @@ public class HosePulleyInstance extends AbstractPulleyInstance {
}
protected Instancer<OrientedData> getRopeModel() {
return getOrientedMaterial().getModel(AllBlockPartials.HOSE, blockState);
return getOrientedMaterial().getModel(AllBlockPartials.HOSE);
}
protected Instancer<OrientedData> getMagnetModel() {
return materialManager.defaultCutout()
.material(Materials.ORIENTED)
.getModel(AllBlockPartials.HOSE_MAGNET, blockState);
.getModel(AllBlockPartials.HOSE_MAGNET);
}
protected Instancer<OrientedData> getHalfMagnetModel() {
return materialManager.defaultCutout()
.material(Materials.ORIENTED)
.getModel(AllBlockPartials.HOSE_HALF_MAGNET, blockState);
.getModel(AllBlockPartials.HOSE_HALF_MAGNET);
}
protected Instancer<OrientedData> getCoilModel() {
return getOrientedMaterial().getModel(AllBlockPartials.HOSE_COIL, blockState, rotatingAbout);
return getOrientedMaterial().getModel(AllBlockPartials.HOSE_COIL, rotatingAbout);
}
protected Instancer<OrientedData> getHalfRopeModel() {
return getOrientedMaterial().getModel(AllBlockPartials.HOSE_HALF, blockState);
return getOrientedMaterial().getModel(AllBlockPartials.HOSE_HALF);
}
protected float getOffset() {

View file

@ -22,15 +22,15 @@ public class RopePulleyInstance extends AbstractPulleyInstance {
}
protected Instancer<OrientedData> getHalfMagnetModel() {
return getOrientedMaterial().getModel(AllBlockPartials.ROPE_HALF_MAGNET, blockState);
return getOrientedMaterial().getModel(AllBlockPartials.ROPE_HALF_MAGNET);
}
protected Instancer<OrientedData> getCoilModel() {
return getOrientedMaterial().getModel(AllBlockPartials.ROPE_COIL, blockState, rotatingAbout);
return getOrientedMaterial().getModel(AllBlockPartials.ROPE_COIL, rotatingAbout);
}
protected Instancer<OrientedData> getHalfRopeModel() {
return getOrientedMaterial().getModel(AllBlockPartials.ROPE_HALF, blockState);
return getOrientedMaterial().getModel(AllBlockPartials.ROPE_HALF);
}
protected float getOffset() {

View file

@ -4,7 +4,7 @@ import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.RenderLayer;
import com.jozufozu.flywheel.api.RenderLayer;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
import com.jozufozu.flywheel.config.BackendType;

View file

@ -32,7 +32,7 @@ public class PumpCogInstance extends SingleRotatingInstance implements DynamicIn
materialManager.defaultSolid()
.material(Materials.TRANSFORMED)
.getModel(AllBlockPartials.MECHANICAL_PUMP_ARROW, blockState)
.getModel(AllBlockPartials.MECHANICAL_PUMP_ARROW)
.createInstances(arrows);
}
@ -63,7 +63,7 @@ public class PumpCogInstance extends SingleRotatingInstance implements DynamicIn
protected Instancer<RotatingData> getModel() {
BlockState referenceState = blockEntity.getBlockState();
Direction facing = referenceState.getValue(BlockStateProperties.FACING);
return getRotatingMaterial().getModel(AllBlockPartials.MECHANICAL_PUMP_COG, referenceState, facing);
return getRotatingMaterial().getModel(AllBlockPartials.MECHANICAL_PUMP_COG, facing);
}
@Override

View file

@ -30,6 +30,8 @@ import net.minecraftforge.fluids.FluidStack;
public class FluidDrainingBehaviour extends FluidManipulationBehaviour {
public static final BehaviourType<FluidDrainingBehaviour> TYPE = new BehaviourType<>();
Fluid fluid;
// Execution
@ -322,8 +324,6 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour {
tileEntity.sendData();
}
public static BehaviourType<FluidDrainingBehaviour> TYPE = new BehaviourType<>();
@Override
public BehaviourType<?> getType() {
return TYPE;

View file

@ -41,6 +41,8 @@ import net.minecraft.world.ticks.LevelTicks;
public class FluidFillingBehaviour extends FluidManipulationBehaviour {
public static final BehaviourType<FluidFillingBehaviour> TYPE = new BehaviourType<>();
PriorityQueue<BlockPosEntry> queue;
List<BlockPosEntry> infinityCheckFrontier;
@ -72,7 +74,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
(p, d) -> infinityCheckFrontier.add(new BlockPosEntry(p, d)), true);
int maxBlocks = maxBlocks();
if (infinityCheckVisited.size() > maxBlocks && maxBlocks != -1) {
if (infinityCheckVisited.size() > maxBlocks && maxBlocks != -1 && !fillInfinite()) {
if (!infinite) {
reset();
infinite = true;
@ -163,9 +165,11 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
if (visited.size() >= maxBlocks && maxBlocks != -1) {
infinite = true;
visited.clear();
queue.clear();
return false;
if (!fillInfinite()) {
visited.clear();
queue.clear();
return false;
}
}
SpaceType spaceType = getAtPos(world, currentPos, fluid);
@ -298,8 +302,6 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
infinityCheckVisited.clear();
}
public static BehaviourType<FluidFillingBehaviour> TYPE = new BehaviourType<>();
@Override
public BehaviourType<?> getType() {
return TYPE;

View file

@ -76,6 +76,7 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI
return returned;
transportedStack = transportedStack.copy();
transportedStack.stack = inserted.copy();
transportedStack.beltPosition = side.getAxis()
.isVertical() ? .5f : 0;
transportedStack.prevSideOffset = transportedStack.sideOffset;
@ -277,7 +278,7 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI
heldItem = TransportedItemStack.read(compound.getCompound("HeldItem"));
super.read(compound, clientPacket);
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (side != null && side.getAxis()

View file

@ -40,7 +40,7 @@ public class FluidValveInstance extends ShaftInstance implements DynamicInstance
pointer = materialManager.defaultSolid()
.material(Materials.TRANSFORMED)
.getModel(AllBlockPartials.FLUID_VALVE_POINTER, blockState).createInstance();
.getModel(AllBlockPartials.FLUID_VALVE_POINTER).createInstance();
transformPointer();
}

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.fluids.tank;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling;
import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity.CreativeSmartFluidTank;
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
@ -95,7 +96,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankT
@Override
public int getLightEmission(BlockState state, BlockGetter world, BlockPos pos) {
FluidTankTileEntity tankAt = FluidTankConnectivityHandler.anyTankAt(world, pos);
FluidTankTileEntity tankAt = ConnectivityHandler.partAt(getTileEntityType(), world, pos);
if (tankAt == null)
return 0;
FluidTankTileEntity controllerTE = tankAt.getControllerTE();
@ -130,7 +131,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankT
return InteractionResult.PASS;
FluidExchange exchange = null;
FluidTankTileEntity te = FluidTankConnectivityHandler.anyTankAt(world, pos);
FluidTankTileEntity te = ConnectivityHandler.partAt(getTileEntityType(), world, pos);
if (te == null)
return InteractionResult.FAIL;
@ -240,7 +241,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankT
return;
FluidTankTileEntity tankTE = (FluidTankTileEntity) te;
world.removeBlockEntity(pos);
FluidTankConnectivityHandler.splitTank(tankTE);
ConnectivityHandler.splitMulti(tankTE);
}
}

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.fluids.tank;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour;
@ -21,6 +22,6 @@ public class FluidTankCTBehaviour extends HorizontalCTBehaviour {
@Override
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos,
Direction face) {
return state.getBlock() == other.getBlock() && FluidTankConnectivityHandler.isConnected(reader, pos, otherPos);
return state.getBlock() == other.getBlock() && ConnectivityHandler.isConnected(reader, pos, otherPos); //FluidTankConnectivityHandler.isConnected(reader, pos, otherPos);
}
}

View file

@ -1,376 +0,0 @@
package com.simibubi.create.content.contraptions.fluids.tank;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.PriorityQueue;
import java.util.Set;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity.CreativeSmartFluidTank;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.templates.FluidTank;
public class FluidTankConnectivityHandler {
public static void formTanks(FluidTankTileEntity te) {
TankSearchCache cache = new TankSearchCache();
List<FluidTankTileEntity> frontier = new ArrayList<>();
frontier.add(te);
formTanks(te.getType(), te.getLevel(), cache, frontier);
}
private static void formTanks(BlockEntityType<?> type, BlockGetter world, TankSearchCache cache,
List<FluidTankTileEntity> frontier) {
PriorityQueue<Pair<Integer, FluidTankTileEntity>> creationQueue = makeCreationQueue();
Set<BlockPos> visited = new HashSet<>();
int minX = Integer.MAX_VALUE;
int minZ = Integer.MAX_VALUE;
for (FluidTankTileEntity fluidTankTileEntity : frontier) {
BlockPos pos = fluidTankTileEntity.getBlockPos();
minX = Math.min(pos.getX(), minX);
minZ = Math.min(pos.getZ(), minZ);
}
minX -= FluidTankTileEntity.getMaxSize();
minZ -= FluidTankTileEntity.getMaxSize();
while (!frontier.isEmpty()) {
FluidTankTileEntity tank = frontier.remove(0);
BlockPos tankPos = tank.getBlockPos();
if (visited.contains(tankPos))
continue;
visited.add(tankPos);
int amount = tryToFormNewTank(tank, cache, true);
if (amount > 1)
creationQueue.add(Pair.of(amount, tank));
for (Axis axis : Iterate.axes) {
Direction d = Direction.get(AxisDirection.NEGATIVE, axis);
BlockPos next = tankPos.relative(d);
if (next.getX() <= minX || next.getZ() <= minZ)
continue;
if (visited.contains(next))
continue;
FluidTankTileEntity nextTank = tankAt(type, world, next);
if (nextTank == null)
continue;
if (nextTank.isRemoved())
continue;
frontier.add(nextTank);
}
}
visited.clear();
while (!creationQueue.isEmpty()) {
Pair<Integer, FluidTankTileEntity> next = creationQueue.poll();
FluidTankTileEntity toCreate = next.getValue();
if (visited.contains(toCreate.getBlockPos()))
continue;
visited.add(toCreate.getBlockPos());
tryToFormNewTank(toCreate, cache, false);
}
}
public static void splitTank(FluidTankTileEntity te) {
splitTankAndInvalidate(te, null, false);
}
private static int tryToFormNewTank(FluidTankTileEntity te, TankSearchCache cache, boolean simulate) {
int bestWidth = 1;
int bestAmount = -1;
if (!te.isController())
return 0;
for (int w = 1; w <= FluidTankTileEntity.getMaxSize(); w++) {
int amount = tryToFormNewTankOfWidth(te, w, cache, true);
if (amount < bestAmount)
continue;
bestWidth = w;
bestAmount = amount;
}
if (!simulate) {
if (te.width == bestWidth && te.width * te.width * te.height == bestAmount)
return bestAmount;
splitTankAndInvalidate(te, cache, false);
te.applyFluidTankSize(bestAmount);
tryToFormNewTankOfWidth(te, bestWidth, cache, simulate);
te.updateConnectivity = false;
te.width = bestWidth;
te.height = bestAmount / bestWidth / bestWidth;
BlockState state = te.getBlockState();
if (FluidTankBlock.isTank(state)) {
state = state.setValue(FluidTankBlock.BOTTOM, true);
state = state.setValue(FluidTankBlock.TOP, te.height == 1);
te.getLevel()
.setBlock(te.getBlockPos(), state, 22);
}
te.setWindows(te.window);
te.onFluidStackChanged(te.tankInventory.getFluid());
te.updateBoilerState();
te.setChanged();
}
return bestAmount;
}
private static int tryToFormNewTankOfWidth(FluidTankTileEntity te, int width, TankSearchCache cache,
boolean simulate) {
int amount = 0;
int height = 0;
BlockEntityType<?> type = te.getType();
Level world = te.getLevel();
BlockPos origin = te.getBlockPos();
FluidTank teTank = te.tankInventory;
FluidStack fluid = te.tankInventory.getFluidInTank(0);
Search:
for (int yOffset = 0; yOffset < FluidTankTileEntity.getMaxHeight(); yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos = origin.offset(xOffset, yOffset, zOffset);
Optional<FluidTankTileEntity> tank = cache.getOrCache(type, world, pos);
if (!tank.isPresent())
break Search;
FluidTankTileEntity controller = tank.get();
int otherWidth = controller.width;
if (otherWidth > width)
break Search;
BlockPos controllerPos = controller.getBlockPos();
if (!controllerPos.equals(origin)) {
if (controllerPos.getX() < origin.getX())
break Search;
if (controllerPos.getZ() < origin.getZ())
break Search;
if (controllerPos.getX() + otherWidth > origin.getX() + width)
break Search;
if (controllerPos.getZ() + otherWidth > origin.getZ() + width)
break Search;
}
FluidStack otherFluid = controller.getTankInventory()
.getFluid();
if (!fluid.isEmpty() && !otherFluid.isEmpty() && !fluid.isFluidEqual(otherFluid))
break Search;
}
}
amount += width * width;
height++;
}
if (simulate)
return amount;
boolean opaque = false;
for (int yOffset = 0; yOffset < height; yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos = origin.offset(xOffset, yOffset, zOffset);
FluidTankTileEntity tank = tankAt(type, world, pos);
if (tank == te)
continue;
opaque |= !tank.window;
FluidTank tankTank = tank.tankInventory;
FluidStack fluidInTank = tankTank.getFluid();
if (!fluidInTank.isEmpty()) {
if (teTank.isEmpty() && teTank instanceof CreativeSmartFluidTank)
((CreativeSmartFluidTank) teTank).setContainedFluid(fluidInTank);
teTank.fill(fluidInTank, FluidAction.EXECUTE);
}
tankTank.setFluid(FluidStack.EMPTY);
splitTankAndInvalidate(tank, cache, false);
tank.setController(origin);
tank.updateConnectivity = false;
cache.put(pos, te);
BlockState state = world.getBlockState(pos);
if (!FluidTankBlock.isTank(state))
continue;
state = state.setValue(FluidTankBlock.BOTTOM, yOffset == 0);
state = state.setValue(FluidTankBlock.TOP, yOffset == height - 1);
world.setBlock(pos, state, 22);
}
}
}
te.setWindows(!opaque);
return amount;
}
private static void splitTankAndInvalidate(FluidTankTileEntity te, @Nullable TankSearchCache cache,
boolean tryReconnect) {
// tryReconnect helps whenever only few tanks have been removed
te = te.getControllerTE();
if (te == null)
return;
int height = te.height;
int width = te.width;
if (width == 1 && height == 1)
return;
Level world = te.getLevel();
BlockPos origin = te.getBlockPos();
List<FluidTankTileEntity> frontier = new ArrayList<>();
FluidStack toDistribute = te.tankInventory.getFluid()
.copy();
int maxCapacity = FluidTankTileEntity.getCapacityMultiplier();
if (!toDistribute.isEmpty() && !te.isRemoved())
toDistribute.shrink(maxCapacity);
te.applyFluidTankSize(1);
for (int yOffset = 0; yOffset < height; yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos = origin.offset(xOffset, yOffset, zOffset);
FluidTankTileEntity tankAt = tankAt(te.getType(), world, pos);
if (tankAt == null)
continue;
if (!tankAt.getController()
.equals(origin))
continue;
FluidTankTileEntity controllerTE = tankAt.getControllerTE();
tankAt.window = controllerTE == null || controllerTE.window;
tankAt.removeController(true);
if (!toDistribute.isEmpty() && tankAt != te) {
FluidStack copy = toDistribute.copy();
FluidTank tankInventory = tankAt.tankInventory;
if (tankInventory.isEmpty() && tankInventory instanceof CreativeSmartFluidTank)
((CreativeSmartFluidTank) tankInventory).setContainedFluid(toDistribute);
else {
int split = Math.min(maxCapacity, toDistribute.getAmount());
copy.setAmount(split);
toDistribute.shrink(split);
tankInventory.fill(copy, FluidAction.EXECUTE);
}
}
if (tryReconnect) {
frontier.add(tankAt);
tankAt.updateConnectivity = false;
}
if (cache != null)
cache.put(pos, tankAt);
}
}
}
te.fluidCapability.invalidate();
if (tryReconnect)
formTanks(te.getType(), world, cache == null ? new TankSearchCache() : cache, frontier);
}
private static PriorityQueue<Pair<Integer, FluidTankTileEntity>> makeCreationQueue() {
return new PriorityQueue<>(new Comparator<Pair<Integer, FluidTankTileEntity>>() {
@Override
public int compare(Pair<Integer, FluidTankTileEntity> o1, Pair<Integer, FluidTankTileEntity> o2) {
return o2.getKey() - o1.getKey();
}
});
}
@Nullable
public static FluidTankTileEntity tankAt(BlockEntityType<?> type, BlockGetter world, BlockPos pos) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof FluidTankTileEntity && te.getType() == type)
return (FluidTankTileEntity) te;
return null;
}
@Nullable
public static FluidTankTileEntity anyTankAt(BlockGetter world, BlockPos pos) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof FluidTankTileEntity)
return (FluidTankTileEntity) te;
return null;
}
private static class TankSearchCache {
Map<BlockPos, Optional<FluidTankTileEntity>> controllerMap;
public TankSearchCache() {
controllerMap = new HashMap<>();
}
void put(BlockPos pos, FluidTankTileEntity target) {
controllerMap.put(pos, Optional.of(target));
}
void putEmpty(BlockPos pos) {
controllerMap.put(pos, Optional.empty());
}
boolean hasVisited(BlockPos pos) {
return controllerMap.containsKey(pos);
}
Optional<FluidTankTileEntity> getOrCache(BlockEntityType<?> type, BlockGetter world, BlockPos pos) {
if (hasVisited(pos))
return controllerMap.get(pos);
FluidTankTileEntity tankAt = tankAt(type, world, pos);
if (tankAt == null) {
putEmpty(pos);
return Optional.empty();
}
FluidTankTileEntity controller = tankAt.getControllerTE();
if (controller == null) {
putEmpty(pos);
return Optional.empty();
}
put(pos, controller);
return Optional.of(controller);
}
}
public static boolean isConnected(BlockGetter world, BlockPos tankPos, BlockPos otherTankPos) {
BlockEntity te1 = world.getBlockEntity(tankPos);
BlockEntity te2 = world.getBlockEntity(otherTankPos);
if (!(te1 instanceof FluidTankTileEntity) || !(te2 instanceof FluidTankTileEntity))
return false;
return ((FluidTankTileEntity) te1).getController()
.equals(((FluidTankTileEntity) te2).getController());
}
}

View file

@ -1,5 +1,9 @@
package com.simibubi.create.content.contraptions.fluids.tank;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
@ -71,7 +75,10 @@ public class FluidTankItem extends BlockItem {
if (!FluidTankBlock.isTank(placedOnState))
return;
FluidTankTileEntity tankAt = FluidTankConnectivityHandler.anyTankAt(world, placedOnPos);
boolean creative = getBlock().equals(AllBlocks.CREATIVE_FLUID_TANK.get());
FluidTankTileEntity tankAt = ConnectivityHandler.partAt(
creative ? AllTileEntities.CREATIVE_FLUID_TANK.get() : AllTileEntities.FLUID_TANK.get(), world, placedOnPos
);
if (tankAt == null)
return;
FluidTankTileEntity controllerTE = tankAt.getControllerTE();

View file

@ -7,6 +7,7 @@ import java.util.List;
import java.util.Random;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.block.connected.CTModel;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.utility.Iterate;
@ -28,20 +29,20 @@ public class FluidTankModel extends CTModel {
public static FluidTankModel standard(BakedModel originalModel) {
return new FluidTankModel(originalModel, AllSpriteShifts.FLUID_TANK, AllSpriteShifts.COPPER_CASING);
}
public static FluidTankModel creative(BakedModel originalModel) {
return new FluidTankModel(originalModel, AllSpriteShifts.CREATIVE_FLUID_TANK, AllSpriteShifts.CREATIVE_CASING);
}
private FluidTankModel(BakedModel originalModel, CTSpriteShiftEntry side, CTSpriteShiftEntry top) {
super(originalModel, new FluidTankCTBehaviour(side, top));
}
@Override
protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) {
CullData cullData = new CullData();
for (Direction d : Iterate.horizontalDirections)
cullData.setCulled(d, FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(d)));
cullData.setCulled(d, ConnectivityHandler.isConnected(world, pos, pos.relative(d))); //FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(d)));
return super.gatherModelData(builder, world, pos, state).withInitial(CULL_PROPERTY, cullData);
}

View file

@ -7,6 +7,7 @@ import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock.Shape;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.foundation.config.AllConfigs;
@ -36,7 +37,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.templates.FluidTank;
public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleInformation, IMultiTileContainer {
public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleInformation, IMultiTileContainer.Fluid {
private static final int MAX_SIZE = 3;
@ -83,7 +84,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
return;
if (!isController())
return;
FluidTankConnectivityHandler.formTanks(this);
ConnectivityHandler.formMulti(this);
}
@Override
@ -151,7 +152,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset);
FluidTankTileEntity tankAt = FluidTankConnectivityHandler.anyTankAt(level, pos);
FluidTankTileEntity tankAt = ConnectivityHandler.partAt(getType(), level, pos);
if (tankAt == null)
continue;
level.updateNeighbourForOutputSignal(pos, tankAt.getBlockState()
@ -507,4 +508,82 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
this.fluidLevel = fluidLevel;
}
@Override
public void preventConnectivityUpdate() { updateConnectivity = false; }
@Override
public void notifyMultiUpdated() {
BlockState state = this.getBlockState();
if (FluidTankBlock.isTank(state)) { // safety
state = state.setValue(FluidTankBlock.BOTTOM, getController().getY() == getBlockPos().getY());
state = state.setValue(FluidTankBlock.TOP, getController().getY() + height - 1 == getBlockPos().getY());
level.setBlock(getBlockPos(), state, 22);
}
setWindows(window);
onFluidStackChanged(tankInventory.getFluid());
setChanged();
}
@Override
public void setExtraData(@Nullable Object data) {
if (data instanceof Boolean) window = (boolean)data;
}
@Override
@Nullable
public Object getExtraData() { return window; }
@Override
public Object modifyExtraData(Object data) {
if (data instanceof Boolean windows) {
windows |= window;
return windows;
}
return data;
}
@Override
public Direction.Axis getMainConnectionAxis() { return Direction.Axis.Y; }
@Override
public int getMaxLength(Direction.Axis longAxis, int width) {
if (longAxis == Direction.Axis.Y) return getMaxHeight();
return getMaxWidth();
}
@Override
public int getMaxWidth() { return MAX_SIZE; }
@Override
public int getHeight() { return height; }
@Override
public void setHeight(int height) { this.height = height; }
@Override
public int getWidth() { return width; }
@Override
public void setWidth(int width) { this.width = width; }
@Override
public boolean hasTank() { return true; }
@Override
public int getTankSize(int tank) { return getCapacityMultiplier(); }
@Override
public void setTankSize(int tank, int blocks) {
applyFluidTankSize(blocks);
}
@Override
public IFluidTank getTank(int tank) {
return tankInventory;
}
@Override
public FluidStack getFluid(int tank) {
return tankInventory.getFluid().copy();
}
}

View file

@ -8,6 +8,8 @@ import java.util.List;
import javax.annotation.Nonnull;
import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
@ -173,7 +175,7 @@ public class BasinRecipe extends ProcessingRecipe<SmartInventory> {
return basinRecipe;
}
protected BasinRecipe(AllRecipeTypes type, ProcessingRecipeParams params) {
protected BasinRecipe(IRecipeTypeInfo type, ProcessingRecipeParams params) {
super(type, params);
}

View file

@ -62,9 +62,9 @@ public class BeltInstance extends KineticTileInstance<BeltTileEntity> {
PartialModel beltPartial = BeltRenderer.getBeltPartial(diagonal, start, end, bottom);
SpriteShiftEntry spriteShift = BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom);
Instancer<BeltData> beltModel = materialManager.defaultSolid()
.material(AllMaterialSpecs.BELTS)
.getModel(beltPartial, blockState);
Instancer<BeltData> beltModel = materialManager.defaultSolid()
.material(AllMaterialSpecs.BELTS)
.getModel(beltPartial);
keys.add(setup(beltModel.createInstance(), bottom, spriteShift));
@ -143,7 +143,7 @@ public class BeltInstance extends KineticTileInstance<BeltTileEntity> {
return modelTransform;
};
return getRotatingMaterial().getModel(AllBlockPartials.BELT_PULLEY, blockState, dir, ms);
return getRotatingMaterial().getModel(AllBlockPartials.BELT_PULLEY, dir, ms);
}
private Direction getOrientation() {

View file

@ -38,8 +38,7 @@ public class BracketedKineticTileInstance extends SingleRotatingInstance {
BlockPos pos = blockEntity.getBlockPos();
float offset = BracketedKineticTileRenderer.getShaftAngleOffset(axis, pos);
Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE);
Instancer<RotatingData> half = getRotatingMaterial().getModel(AllBlockPartials.COGWHEEL_SHAFT, blockState,
facing, () -> this.rotateToAxis(axis));
Instancer<RotatingData> half = getRotatingMaterial().getModel(AllBlockPartials.COGWHEEL_SHAFT, facing, () -> this.rotateToAxis(axis));
additionalShaft = setup(half.createInstance(), speed);
additionalShaft.setRotationOffset(offset);
@ -52,7 +51,7 @@ public class BracketedKineticTileInstance extends SingleRotatingInstance {
Axis axis = KineticTileEntityRenderer.getRotationAxisOf(blockEntity);
Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE);
return getRotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_LARGE_COGWHEEL, blockState, facing,
return getRotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_LARGE_COGWHEEL, facing,
() -> this.rotateToAxis(axis));
}

View file

@ -58,7 +58,7 @@ public class EncasedCogInstance extends KineticTileInstance<KineticTileEntity> {
for (Direction d : Iterate.directionsInAxis(axis)) {
if (!def.hasShaftTowards(blockEntity.getLevel(), blockEntity.getBlockPos(), blockState, d))
continue;
RotatingData data = setup(getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, d)
RotatingData data = setup(getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, d)
.createInstance());
if (d.getAxisDirection() == AxisDirection.POSITIVE)
rotatingTopShaft = Optional.of(data);
@ -94,7 +94,7 @@ public class EncasedCogInstance extends KineticTileInstance<KineticTileEntity> {
Direction.fromAxisAndDirection(referenceState.getValue(BlockStateProperties.AXIS), AxisDirection.POSITIVE);
PartialModel partial = large ? AllBlockPartials.SHAFTLESS_LARGE_COGWHEEL : AllBlockPartials.SHAFTLESS_COGWHEEL;
return getRotatingMaterial().getModel(partial, referenceState, facing, () -> {
return getRotatingMaterial().getModel(partial, facing, () -> {
PoseStack poseStack = new PoseStack();
TransformStack.cast(poseStack)
.centre()

View file

@ -30,7 +30,7 @@ public class SplitShaftInstance extends KineticTileInstance<SplitShaftTileEntity
for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) {
Instancer<RotatingData> half = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, dir);
Instancer<RotatingData> half = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, dir);
float splitSpeed = speed * tile.getRotationSpeedModifier(dir);

View file

@ -32,7 +32,7 @@ public abstract class GaugeInstance extends ShaftInstance implements DynamicInst
GaugeTileEntity gaugeTile = (GaugeTileEntity) tile;
GaugeBlock gaugeBlock = (GaugeBlock) blockState.getBlock();
Instancer<ModelData> dialModel = getTransformMaterial().getModel(AllBlockPartials.GAUGE_DIAL, blockState);
Instancer<ModelData> dialModel = getTransformMaterial().getModel(AllBlockPartials.GAUGE_DIAL);
Instancer<ModelData> headModel = getHeadModel();
ms = new PoseStack();
@ -150,7 +150,7 @@ public abstract class GaugeInstance extends ShaftInstance implements DynamicInst
@Override
protected Instancer<ModelData> getHeadModel() {
return getTransformMaterial().getModel(AllBlockPartials.GAUGE_HEAD_SPEED, blockState);
return getTransformMaterial().getModel(AllBlockPartials.GAUGE_HEAD_SPEED);
}
}
@ -161,7 +161,7 @@ public abstract class GaugeInstance extends ShaftInstance implements DynamicInst
@Override
protected Instancer<ModelData> getHeadModel() {
return getTransformMaterial().getModel(AllBlockPartials.GAUGE_HEAD_STRESS, blockState);
return getTransformMaterial().getModel(AllBlockPartials.GAUGE_HEAD_STRESS);
}
}
}

View file

@ -40,7 +40,7 @@ public class GearboxInstance extends KineticTileInstance<GearboxTileEntity> {
if (boxAxis == axis)
continue;
Instancer<RotatingData> shaft = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, direction);
Instancer<RotatingData> shaft = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, direction);
RotatingData key = shaft.createInstance();

View file

@ -4,14 +4,18 @@ import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationS
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.BoneMealItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.block.AzaleaBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BonemealableBlock;
import net.minecraft.world.level.block.SaplingBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class TreeFertilizerItem extends Item {
@ -24,7 +28,7 @@ public class TreeFertilizerItem extends Item {
BlockState state = context.getLevel()
.getBlockState(context.getClickedPos());
Block block = state.getBlock();
if (block instanceof SaplingBlock) {
if (block instanceof BonemealableBlock bonemealableBlock && state.is(BlockTags.SAPLINGS)) {
if (context.getLevel().isClientSide) {
BoneMealItem.addGrowthParticles(context.getLevel(), context.getClickedPos(), 100);
@ -38,11 +42,11 @@ public class TreeFertilizerItem extends Item {
if (context.getLevel()
.getBlockState(saplingPos.offset(pos))
.getBlock() == block)
world.setBlockAndUpdate(pos.above(10), state.setValue(SaplingBlock.STAGE, 1));
world.setBlockAndUpdate(pos.above(10), withStage(state, 1));
}
((SaplingBlock) block).performBonemeal(world, world.getRandom(), BlockPos.ZERO.above(10),
state.setValue(SaplingBlock.STAGE, 1));
bonemealableBlock.performBonemeal(world, world.getRandom(), BlockPos.ZERO.above(10),
withStage(state, 1));
for (BlockPos pos : world.blocksAdded.keySet()) {
BlockPos actualPos = pos.offset(saplingPos).below(10);
@ -76,6 +80,12 @@ public class TreeFertilizerItem extends Item {
return super.useOn(context);
}
private BlockState withStage(BlockState original, int stage) {
if (!original.hasProperty(BlockStateProperties.STAGE))
return original;
return original.setValue(BlockStateProperties.STAGE, 1);
}
private static class TreesDreamWorld extends PlacementSimulationServerWorld {
private final BlockPos saplingPos;
private final BlockState soil;

View file

@ -15,7 +15,7 @@ public class CopperBacktankInstance extends SingleRotatingInstance {
@Override
protected Instancer<RotatingData> getModel() {
return getRotatingMaterial().getModel(AllBlockPartials.COPPER_BACKTANK_SHAFT, blockState);
return getRotatingMaterial().getModel(AllBlockPartials.COPPER_BACKTANK_SHAFT);
}
}

View file

@ -32,12 +32,12 @@ public class ToolBoxInstance extends BlockEntityInstance<ToolboxTileEntity> impl
Instancer<ModelData> drawerModel = materialManager.defaultSolid()
.material(Materials.TRANSFORMED)
.getModel(AllBlockPartials.TOOLBOX_DRAWER, blockState);
.getModel(AllBlockPartials.TOOLBOX_DRAWER);
drawers = new ModelData[]{drawerModel.createInstance(), drawerModel.createInstance()};
lid = materialManager.defaultCutout()
.material(Materials.TRANSFORMED)
.getModel(AllBlockPartials.TOOLBOX_LIDS.get(blockEntity.getColor()), blockState)
.getModel(AllBlockPartials.TOOLBOX_LIDS.get(blockEntity.getColor()))
.createInstance();
}

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.curiosities.toolbox;
import java.util.List;
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.stream.Collectors;
@ -111,6 +112,7 @@ public class ToolboxHandler {
.sorted((p1, p2) -> Double.compare(distance(location, p1), distance(location, p2)))
.limit(maxAmount)
.map(toolboxes.get(world)::get)
.filter(ToolboxTileEntity::isFullyInitialized)
.collect(Collectors.toList());
}

View file

@ -6,6 +6,7 @@ import static com.simibubi.create.foundation.gui.AllGuiTextures.TOOLBELT_SELECTE
import static com.simibubi.create.foundation.gui.AllGuiTextures.TOOLBELT_SELECTED_ON;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.google.common.collect.ImmutableList;
@ -111,10 +112,7 @@ public class ToolboxHandlerClient {
Level level = player.level;
List<ToolboxTileEntity> toolboxes = ToolboxHandler.getNearest(player.level, player, 8);
if (!toolboxes.isEmpty())
Collections.sort(toolboxes, (te1, te2) -> te1.getUniqueId()
.compareTo(te2.getUniqueId()));
toolboxes.sort(Comparator.comparing(ToolboxTileEntity::getUniqueId));
CompoundTag compound = player.getPersistentData()
.getCompound("CreateToolboxData");

View file

@ -380,6 +380,11 @@ public class ToolboxTileEntity extends SmartTileEntity implements MenuProvider,
return uniqueId;
}
public boolean isFullyInitialized() {
// returns true when uniqueId has been initialized
return uniqueId != null;
}
public void setCustomName(Component customName) {
this.customName = customName;
}

View file

@ -29,8 +29,8 @@ public class BeltTunnelInstance extends BlockEntityInstance<BeltTunnelTileEntity
tunnelFlaps = new EnumMap<>(Direction.class);
Instancer<FlapData> model = modelManager.defaultSolid()
.material(AllMaterialSpecs.FLAPS)
.getModel(AllBlockPartials.BELT_TUNNEL_FLAP, blockState);
.material(AllMaterialSpecs.FLAPS)
.getModel(AllBlockPartials.BELT_TUNNEL_FLAP);
int blockLight = world.getBrightness(LightLayer.BLOCK, pos);
int skyLight = world.getBrightness(LightLayer.SKY, pos);

View file

@ -41,7 +41,7 @@ import net.minecraftforge.items.ItemStackHandler;
public class DepotBehaviour extends TileEntityBehaviour {
public static BehaviourType<DepotBehaviour> TYPE = new BehaviourType<>();
public static final BehaviourType<DepotBehaviour> TYPE = new BehaviourType<>();
TransportedItemStack heldItem;
List<TransportedItemStack> incoming;

View file

@ -21,7 +21,7 @@ public class EjectorInstance extends ShaftInstance implements DynamicInstance {
super(dispatcher, tile);
this.tile = tile;
plate = getTransformMaterial().getModel(AllBlockPartials.EJECTOR_TOP, blockState).createInstance();
plate = getTransformMaterial().getModel(AllBlockPartials.EJECTOR_TOP).createInstance();
pivotPlate();
}

View file

@ -19,7 +19,7 @@ public class BrassDiodeInstance extends BlockEntityInstance<BrassDiodeTileEntity
indicator = modelManager.defaultSolid()
.material(Materials.TRANSFORMED)
.getModel(AllBlockPartials.FLEXPEATER_INDICATOR, blockState).createInstance();
.getModel(AllBlockPartials.FLEXPEATER_INDICATOR).createInstance();
indicator.loadIdentity()
.translate(getInstancePosition())

View file

@ -30,8 +30,8 @@ public class FunnelInstance extends BlockEntityInstance<FunnelTileEntity> implem
PartialModel flapPartial = (blockState.getBlock() instanceof FunnelBlock ? AllBlockPartials.FUNNEL_FLAP
: AllBlockPartials.BELT_FUNNEL_FLAP);
Instancer<FlapData> model = modelManager.defaultSolid()
.material(AllMaterialSpecs.FLAPS)
.getModel(flapPartial, blockState);
.material(AllMaterialSpecs.FLAPS)
.getModel(flapPartial);
int blockLight = world.getBrightness(LightLayer.BLOCK, pos);
int skyLight = world.getBrightness(LightLayer.SKY, pos);

View file

@ -0,0 +1,689 @@
package com.simibubi.create.content.logistics.block.mechanicalArm;
import java.util.Optional;
import java.util.function.Function;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlock;
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity;
import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock;
import com.simibubi.create.content.contraptions.components.saw.SawBlock;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
import com.simibubi.create.content.logistics.block.funnel.AbstractFunnelBlock;
import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock;
import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape;
import com.simibubi.create.content.logistics.block.funnel.FunnelBlock;
import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Containers;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.WorldlyContainer;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.RecordItem;
import net.minecraft.world.item.crafting.CampfireCookingRecipe;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.level.block.ComposterBlock;
import net.minecraft.world.level.block.JukeboxBlock;
import net.minecraft.world.level.block.RespawnAnchorBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import net.minecraft.world.level.block.entity.JukeboxBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
public class AllArmInteractionPointTypes {
public static final BasinType BASIN = register("basin", BasinType::new);
public static final BeltType BELT = register("belt", BeltType::new);
public static final BlazeBurnerType BLAZE_BURNER = register("blaze_burner", BlazeBurnerType::new);
public static final ChuteType CHUTE = register("chute", ChuteType::new);
public static final CrafterType CRAFTER = register("crafter", CrafterType::new);
public static final CrushingWheelsType CRUSHING_WHEELS = register("crushing_wheels", CrushingWheelsType::new);
public static final DeployerType DEPLOYER = register("deployer", DeployerType::new);
public static final DepotType DEPOT = register("depot", DepotType::new);
public static final FunnelType FUNNEL = register("funnel", FunnelType::new);
public static final MillstoneType MILLSTONE = register("millstone", MillstoneType::new);
public static final SawType SAW = register("saw", SawType::new);
public static final CampfireType CAMPFIRE = register("campfire", CampfireType::new);
public static final ComposterType COMPOSTER = register("composter", ComposterType::new);
public static final JukeboxType JUKEBOX = register("jukebox", JukeboxType::new);
public static final RespawnAnchorType RESPAWN_ANCHOR = register("respawn_anchor", RespawnAnchorType::new);
private static <T extends ArmInteractionPointType> T register(String id, Function<ResourceLocation, T> factory) {
T type = factory.apply(Create.asResource(id));
ArmInteractionPointType.register(type);
return type;
}
public static void register() {
}
//
public static class BasinType extends ArmInteractionPointType {
public BasinType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.BASIN.has(state);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new ArmInteractionPoint(this, level, pos, state);
}
}
public static class BeltType extends ArmInteractionPointType {
public BeltType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.BELT.has(state) && !(level.getBlockState(pos.above())
.getBlock() instanceof BeltTunnelBlock);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new BeltPoint(this, level, pos, state);
}
}
public static class BlazeBurnerType extends ArmInteractionPointType {
public BlazeBurnerType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.BLAZE_BURNER.has(state);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new BlazeBurnerPoint(this, level, pos, state);
}
}
public static class ChuteType extends ArmInteractionPointType {
public ChuteType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AbstractChuteBlock.isChute(state);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new TopFaceArmInteractionPoint(this, level, pos, state);
}
}
public static class CrafterType extends ArmInteractionPointType {
public CrafterType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.MECHANICAL_CRAFTER.has(state);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new CrafterPoint(this, level, pos, state);
}
}
public static class CrushingWheelsType extends ArmInteractionPointType {
public CrushingWheelsType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(state);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new TopFaceArmInteractionPoint(this, level, pos, state);
}
}
public static class DeployerType extends ArmInteractionPointType {
public DeployerType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.DEPLOYER.has(state);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new DeployerPoint(this, level, pos, state);
}
}
public static class DepotType extends ArmInteractionPointType {
public DepotType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.DEPOT.has(state) || AllBlocks.WEIGHTED_EJECTOR.has(state);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new DepotPoint(this, level, pos, state);
}
}
public static class FunnelType extends ArmInteractionPointType {
public FunnelType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return state.getBlock() instanceof AbstractFunnelBlock
&& !(state.hasProperty(FunnelBlock.EXTRACTING) && state.getValue(FunnelBlock.EXTRACTING))
&& !(state.hasProperty(BeltFunnelBlock.SHAPE) && state.getValue(BeltFunnelBlock.SHAPE) == Shape.PUSHING);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new FunnelPoint(this, level, pos, state);
}
}
public static class MillstoneType extends ArmInteractionPointType {
public MillstoneType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.MILLSTONE.has(state);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new ArmInteractionPoint(this, level, pos, state);
}
}
public static class SawType extends ArmInteractionPointType {
public SawType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return AllBlocks.MECHANICAL_SAW.has(state) && state.getValue(SawBlock.FACING) == Direction.UP
&& ((KineticTileEntity) level.getBlockEntity(pos)).getSpeed() != 0;
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new DepotPoint(this, level, pos, state);
}
}
public static class CampfireType extends ArmInteractionPointType {
public CampfireType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return state.getBlock() instanceof CampfireBlock;
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new CampfirePoint(this, level, pos, state);
}
}
public static class ComposterType extends ArmInteractionPointType {
public ComposterType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return state.is(Blocks.COMPOSTER);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new ComposterPoint(this, level, pos, state);
}
}
public static class JukeboxType extends ArmInteractionPointType {
public JukeboxType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return state.is(Blocks.JUKEBOX);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new JukeboxPoint(this, level, pos, state);
}
}
public static class RespawnAnchorType extends ArmInteractionPointType {
public RespawnAnchorType(ResourceLocation id) {
super(id);
}
@Override
public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) {
return state.is(Blocks.RESPAWN_ANCHOR);
}
@Override
public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) {
return new RespawnAnchorPoint(this, level, pos, state);
}
}
//
public static class DepositOnlyArmInteractionPoint extends ArmInteractionPoint {
public DepositOnlyArmInteractionPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
public void cycleMode() {
}
@Override
public ItemStack extract(int slot, int amount, boolean simulate) {
return ItemStack.EMPTY;
}
@Override
public int getSlotCount() {
return 0;
}
}
public static class TopFaceArmInteractionPoint extends ArmInteractionPoint {
public TopFaceArmInteractionPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
protected Vec3 getInteractionPositionVector() {
return Vec3.atLowerCornerOf(pos).add(.5f, 1, .5f);
}
}
public static class BeltPoint extends DepotPoint {
public BeltPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
public void keepAlive() {
super.keepAlive();
BeltTileEntity beltTE = BeltHelper.getSegmentTE(level, pos);
if (beltTE == null)
return;
TransportedItemStackHandlerBehaviour transport =
beltTE.getBehaviour(TransportedItemStackHandlerBehaviour.TYPE);
if (transport == null)
return;
MutableBoolean found = new MutableBoolean(false);
transport.handleProcessingOnAllItems(tis -> {
if (found.isTrue())
return TransportedResult.doNothing();
tis.lockedExternally = true;
found.setTrue();
return TransportedResult.doNothing();
});
}
}
public static class BlazeBurnerPoint extends DepositOnlyArmInteractionPoint {
public BlazeBurnerPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
public ItemStack insert(ItemStack stack, boolean simulate) {
ItemStack input = stack.copy();
InteractionResultHolder<ItemStack> res = BlazeBurnerBlock.tryInsert(cachedState, level, pos, input, false, false, simulate);
ItemStack remainder = res.getObject();
if (input.isEmpty()) {
return remainder;
} else {
if (!simulate)
Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), remainder);
return input;
}
}
}
public static class CrafterPoint extends ArmInteractionPoint {
public CrafterPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
protected Direction getInteractionDirection() {
return cachedState.getValue(MechanicalCrafterBlock.HORIZONTAL_FACING)
.getOpposite();
}
@Override
protected Vec3 getInteractionPositionVector() {
return super.getInteractionPositionVector()
.add(Vec3.atLowerCornerOf(getInteractionDirection().getNormal()).scale(.5f));
}
@Override
public void updateCachedState() {
BlockState oldState = cachedState;
super.updateCachedState();
if (oldState != cachedState)
cachedAngles = null;
}
@Override
public ItemStack extract(int slot, int amount, boolean simulate) {
BlockEntity te = level.getBlockEntity(pos);
if (!(te instanceof MechanicalCrafterTileEntity))
return ItemStack.EMPTY;
MechanicalCrafterTileEntity crafter = (MechanicalCrafterTileEntity) te;
SmartInventory inventory = crafter.getInventory();
inventory.allowExtraction();
ItemStack extract = super.extract(slot, amount, simulate);
inventory.forbidExtraction();
return extract;
}
}
public static class DeployerPoint extends ArmInteractionPoint {
public DeployerPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
protected Direction getInteractionDirection() {
return cachedState.getValue(DeployerBlock.FACING)
.getOpposite();
}
@Override
protected Vec3 getInteractionPositionVector() {
return super.getInteractionPositionVector()
.add(Vec3.atLowerCornerOf(getInteractionDirection().getNormal()).scale(.65f));
}
@Override
public void updateCachedState() {
BlockState oldState = cachedState;
super.updateCachedState();
if (oldState != cachedState)
cachedAngles = null;
}
}
public static class DepotPoint extends ArmInteractionPoint {
public DepotPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
protected Vec3 getInteractionPositionVector() {
return Vec3.atLowerCornerOf(pos).add(.5f, 14 / 16f, .5f);
}
}
public static class FunnelPoint extends DepositOnlyArmInteractionPoint {
public FunnelPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
protected Vec3 getInteractionPositionVector() {
return VecHelper.getCenterOf(pos)
.add(Vec3.atLowerCornerOf(FunnelBlock.getFunnelFacing(cachedState)
.getNormal()).scale(-.15f));
}
@Override
protected Direction getInteractionDirection() {
return FunnelBlock.getFunnelFacing(cachedState)
.getOpposite();
}
@Override
public void updateCachedState() {
BlockState oldState = cachedState;
super.updateCachedState();
if (oldState != cachedState)
cachedAngles = null;
}
@Override
public ItemStack insert(ItemStack stack, boolean simulate) {
FilteringBehaviour filtering = TileEntityBehaviour.get(level, pos, FilteringBehaviour.TYPE);
InvManipulationBehaviour inserter = TileEntityBehaviour.get(level, pos, InvManipulationBehaviour.TYPE);
if (cachedState.getOptionalValue(BlockStateProperties.POWERED).orElse(false))
return stack;
if (inserter == null)
return stack;
if (filtering != null && !filtering.test(stack))
return stack;
if (simulate)
inserter.simulate();
ItemStack insert = inserter.insert(stack);
if (!simulate && insert.getCount() != stack.getCount()) {
BlockEntity tileEntity = level.getBlockEntity(pos);
if (tileEntity instanceof FunnelTileEntity) {
FunnelTileEntity funnelTileEntity = (FunnelTileEntity) tileEntity;
funnelTileEntity.onTransfer(stack);
if (funnelTileEntity.hasFlap())
funnelTileEntity.flap(true);
}
}
return insert;
}
}
public static class CampfirePoint extends DepositOnlyArmInteractionPoint {
public CampfirePoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
public ItemStack insert(ItemStack stack, boolean simulate) {
BlockEntity blockEntity = level.getBlockEntity(pos);
if (!(blockEntity instanceof CampfireBlockEntity campfireBE))
return stack;
Optional<CampfireCookingRecipe> recipe = campfireBE.getCookableRecipe(stack);
if (recipe.isEmpty())
return stack;
if (simulate) {
boolean hasSpace = false;
for (ItemStack campfireStack : campfireBE.getItems()) {
if (campfireStack.isEmpty()) {
hasSpace = true;
break;
}
}
if (!hasSpace)
return stack;
ItemStack remainder = stack.copy();
remainder.shrink(1);
return remainder;
}
ItemStack remainder = stack.copy();
campfireBE.placeFood(remainder, recipe.get().getCookingTime());
return remainder;
}
}
public static class ComposterPoint extends ArmInteractionPoint {
public ComposterPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
protected Vec3 getInteractionPositionVector() {
return Vec3.atLowerCornerOf(pos).add(.5f, 13 / 16f, .5f);
}
@Override
public void updateCachedState() {
BlockState oldState = cachedState;
super.updateCachedState();
if (oldState != cachedState)
cachedHandler.invalidate();
}
@Nullable
@Override
protected IItemHandler getHandler() {
if (!cachedHandler.isPresent()) {
cachedHandler = LazyOptional.of(() -> {
ComposterBlock composterBlock = (ComposterBlock) Blocks.COMPOSTER;
WorldlyContainer container = composterBlock.getContainer(cachedState, level, pos);
SidedInvWrapper insertionHandler = new SidedInvWrapper(container, Direction.UP);
SidedInvWrapper extractionHandler = new SidedInvWrapper(container, Direction.DOWN);
return new CombinedInvWrapper(insertionHandler, extractionHandler);
});
}
return cachedHandler.orElse(null);
}
}
public static class JukeboxPoint extends TopFaceArmInteractionPoint {
public JukeboxPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
public int getSlotCount() {
return 1;
}
@Override
public ItemStack insert(ItemStack stack, boolean simulate) {
Item item = stack.getItem();
if (!(item instanceof RecordItem))
return stack;
if (cachedState.getValue(JukeboxBlock.HAS_RECORD))
return stack;
BlockEntity blockEntity = level.getBlockEntity(pos);
if (!(blockEntity instanceof JukeboxBlockEntity jukeboxBE))
return stack;
if (!jukeboxBE.getRecord()
.isEmpty())
return stack;
ItemStack remainder = stack.copy();
ItemStack toInsert = remainder.split(1);
if (!simulate) {
jukeboxBE.setRecord(toInsert);
level.setBlock(pos, cachedState.setValue(JukeboxBlock.HAS_RECORD, true), 2);
level.levelEvent(null, 1010, pos, Item.getId(item));
AllTriggers.triggerForNearbyPlayers(AllTriggers.MUSICAL_ARM, level, pos, 10);
}
return remainder;
}
@Override
public ItemStack extract(int slot, int amount, boolean simulate) {
if (!cachedState.getValue(JukeboxBlock.HAS_RECORD))
return ItemStack.EMPTY;
BlockEntity blockEntity = level.getBlockEntity(pos);
if (!(blockEntity instanceof JukeboxBlockEntity jukeboxBE))
return ItemStack.EMPTY;
ItemStack record = jukeboxBE.getRecord();
if (record.isEmpty())
return ItemStack.EMPTY;
if (!simulate) {
level.levelEvent(1010, pos, 0);
jukeboxBE.clearContent();
level.setBlock(pos, cachedState.setValue(JukeboxBlock.HAS_RECORD, false), 2);
}
return record;
}
}
public static class RespawnAnchorPoint extends DepositOnlyArmInteractionPoint {
public RespawnAnchorPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
super(type, level, pos, state);
}
@Override
protected Vec3 getInteractionPositionVector() {
return Vec3.atLowerCornerOf(pos).add(.5f, 1, .5f);
}
@Override
public ItemStack insert(ItemStack stack, boolean simulate) {
if (!stack.is(Items.GLOWSTONE))
return stack;
if (cachedState.getValue(RespawnAnchorBlock.CHARGE) == 4)
return stack;
if (!simulate)
RespawnAnchorBlock.charge(level, pos, cachedState);
ItemStack remainder = stack.copy();
remainder.shrink(1);
return remainder;
}
}
}

View file

@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3;
public class ArmAngleTarget {
static ArmAngleTarget NO_TARGET = new ArmAngleTarget();
static final ArmAngleTarget NO_TARGET = new ArmAngleTarget();
float baseAngle;
float lowerArmAngle;

View file

@ -49,13 +49,13 @@ public class ArmInstance extends SingleRotatingInstance implements DynamicInstan
Material<ModelData> mat = getTransformMaterial();
base = mat.getModel(AllBlockPartials.ARM_BASE, blockState).createInstance();
lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, blockState).createInstance();
upperBody = mat.getModel(AllBlockPartials.ARM_UPPER_BODY, blockState).createInstance();
head = mat.getModel(AllBlockPartials.ARM_HEAD, blockState).createInstance();
claw = mat.getModel(AllBlockPartials.ARM_CLAW_BASE, blockState).createInstance();
base = mat.getModel(AllBlockPartials.ARM_BASE).createInstance();
lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY).createInstance();
upperBody = mat.getModel(AllBlockPartials.ARM_UPPER_BODY).createInstance();
head = mat.getModel(AllBlockPartials.ARM_HEAD).createInstance();
claw = mat.getModel(AllBlockPartials.ARM_CLAW_BASE).createInstance();
Instancer<ModelData> clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP, blockState);
Instancer<ModelData> clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP);
ModelData clawGrip1 = clawHalfModel.createInstance();
ModelData clawGrip2 = clawHalfModel.createInstance();
@ -172,7 +172,7 @@ public class ArmInstance extends SingleRotatingInstance implements DynamicInstan
@Override
protected Instancer<RotatingData> getModel() {
return getRotatingMaterial().getModel(AllBlockPartials.ARM_COG, blockEntity.getBlockState());
return getRotatingMaterial().getModel(AllBlockPartials.ARM_COG);
}
@Override

View file

@ -1,114 +1,66 @@
package com.simibubi.create.content.logistics.block.mechanicalArm;
import java.util.HashMap;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlock;
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity;
import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock;
import com.simibubi.create.content.contraptions.components.saw.SawBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
import com.simibubi.create.content.logistics.block.funnel.AbstractFunnelBlock;
import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock;
import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape;
import com.simibubi.create.content.logistics.block.funnel.FunnelBlock;
import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.world.Containers;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.item.Item;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.RecordItem;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.ComposterBlock;
import net.minecraft.world.level.block.JukeboxBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.JukeboxBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.InvWrapper;
public abstract class ArmInteractionPoint {
public enum Mode {
DEPOSIT, TAKE
}
public class ArmInteractionPoint {
protected BlockPos pos;
protected BlockState state;
protected Mode mode;
protected final ArmInteractionPointType type;
protected Level level;
protected final BlockPos pos;
protected Mode mode = Mode.DEPOSIT;
protected LazyOptional<IItemHandler> cachedHandler;
protected BlockState cachedState;
protected LazyOptional<IItemHandler> cachedHandler = LazyOptional.empty();
protected ArmAngleTarget cachedAngles;
protected static final HashMap<ArmInteractionPoint, Supplier<ArmInteractionPoint>> POINTS = new HashMap<>();
static {
addPoint(new Saw(), Saw::new);
addPoint(new Belt(), Belt::new);
addPoint(new Depot(), Depot::new);
addPoint(new Chute(), Chute::new);
addPoint(new Basin(), Basin::new);
addPoint(new Funnel(), Funnel::new);
addPoint(new Jukebox(), Jukebox::new);
addPoint(new Crafter(), Crafter::new);
addPoint(new Deployer(), Deployer::new);
addPoint(new Composter(), Composter::new);
addPoint(new Millstone(), Millstone::new);
addPoint(new BlazeBurner(), BlazeBurner::new);
addPoint(new CrushingWheels(), CrushingWheels::new);
public ArmInteractionPoint(ArmInteractionPointType type, Level level, BlockPos pos, BlockState state) {
this.type = type;
this.level = level;
this.pos = pos;
this.cachedState = state;
}
public static void addPoint(ArmInteractionPoint instance, Supplier<ArmInteractionPoint> factory) {
if (POINTS.containsKey(instance))
Create.LOGGER.warn("Point for " + instance.getClass()
.getSimpleName() + " was overridden");
POINTS.put(instance, factory);
public ArmInteractionPointType getType() {
return type;
}
public ArmInteractionPoint() {
cachedHandler = LazyOptional.empty();
public Level getLevel() {
return level;
}
@OnlyIn(Dist.CLIENT)
protected void transformFlag(PoseStack stack) {}
public void setLevel(Level level) {
this.level = level;
}
protected void cycleMode() {
public BlockPos getPos() {
return pos;
}
public Mode getMode() {
return mode;
}
public void cycleMode() {
mode = mode == Mode.DEPOSIT ? Mode.TAKE : Mode.DEPOSIT;
}
@ -120,22 +72,7 @@ public abstract class ArmInteractionPoint {
return Direction.DOWN;
}
protected boolean isStillValid(BlockGetter reader) {
return isValid(reader, pos, reader.getBlockState(pos));
}
protected void keepAlive(LevelAccessor world) {}
protected abstract boolean isValid(BlockGetter reader, BlockPos pos, BlockState state);
protected static boolean isInteractable(BlockGetter reader, BlockPos pos, BlockState state) {
for (ArmInteractionPoint armInteractionPoint : POINTS.keySet())
if (armInteractionPoint.isValid(reader, pos, state))
return true;
return false;
}
protected ArmAngleTarget getTargetAngles(BlockPos armPos, boolean ceiling) {
public ArmAngleTarget getTargetAngles(BlockPos armPos, boolean ceiling) {
if (cachedAngles == null)
cachedAngles =
new ArmAngleTarget(armPos, getInteractionPositionVector(), getInteractionDirection(), ceiling);
@ -143,10 +80,21 @@ public abstract class ArmInteractionPoint {
return cachedAngles;
}
public void updateCachedState() {
cachedState = level.getBlockState(pos);
}
public boolean isValid() {
updateCachedState();
return type.canCreatePoint(level, pos, cachedState);
}
public void keepAlive() {}
@Nullable
protected IItemHandler getHandler(Level world) {
protected IItemHandler getHandler() {
if (!cachedHandler.isPresent()) {
BlockEntity te = world.getBlockEntity(pos);
BlockEntity te = level.getBlockEntity(pos);
if (te == null)
return null;
cachedHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP);
@ -154,401 +102,106 @@ public abstract class ArmInteractionPoint {
return cachedHandler.orElse(null);
}
protected ItemStack insert(Level world, ItemStack stack, boolean simulate) {
IItemHandler handler = getHandler(world);
public ItemStack insert(ItemStack stack, boolean simulate) {
IItemHandler handler = getHandler();
if (handler == null)
return stack;
return ItemHandlerHelper.insertItem(handler, stack, simulate);
}
protected ItemStack extract(Level world, int slot, int amount, boolean simulate) {
IItemHandler handler = getHandler(world);
public ItemStack extract(int slot, int amount, boolean simulate) {
IItemHandler handler = getHandler();
if (handler == null)
return ItemStack.EMPTY;
return handler.extractItem(slot, amount, simulate);
}
protected ItemStack extract(Level world, int slot, boolean simulate) {
return extract(world, slot, 64, simulate);
public ItemStack extract(int slot, boolean simulate) {
return extract(slot, 64, simulate);
}
protected int getSlotCount(Level world) {
IItemHandler handler = getHandler(world);
public int getSlotCount() {
IItemHandler handler = getHandler();
if (handler == null)
return 0;
return handler.getSlots();
}
@Nullable
protected static ArmInteractionPoint createAt(BlockGetter world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
ArmInteractionPoint point = null;
for (ArmInteractionPoint armInteractionPoint : POINTS.keySet())
if (armInteractionPoint.isValid(world, pos, state))
point = POINTS.get(armInteractionPoint)
.get();
if (point != null) {
point.state = state;
point.pos = pos;
point.mode = Mode.DEPOSIT;
}
return point;
protected void serialize(CompoundTag nbt, BlockPos anchor) {
NBTHelper.writeEnum(nbt, "Mode", mode);
}
protected CompoundTag serialize(BlockPos anchor) {
protected void deserialize(CompoundTag nbt, BlockPos anchor) {
mode = NBTHelper.readEnum(nbt, "Mode", Mode.class);
}
public final CompoundTag serialize(BlockPos anchor) {
CompoundTag nbt = new CompoundTag();
nbt.putString("Type", type.getId().toString());
nbt.put("Pos", NbtUtils.writeBlockPos(pos.subtract(anchor)));
NBTHelper.writeEnum(nbt, "Mode", mode);
serialize(nbt, anchor);
return nbt;
}
protected static ArmInteractionPoint deserialize(BlockGetter world, BlockPos anchor, CompoundTag nbt) {
BlockPos pos = NbtUtils.readBlockPos(nbt.getCompound("Pos"));
ArmInteractionPoint interactionPoint = createAt(world, pos.offset(anchor));
if (interactionPoint == null)
@Nullable
public static ArmInteractionPoint deserialize(CompoundTag nbt, Level level, BlockPos anchor) {
ResourceLocation id = ResourceLocation.tryParse(nbt.getString("Type"));
if (id == null)
return null;
interactionPoint.mode = NBTHelper.readEnum(nbt, "Mode", Mode.class);
return interactionPoint;
ArmInteractionPointType type = ArmInteractionPointType.get(id);
if (type == null)
return null;
BlockPos pos = NbtUtils.readBlockPos(nbt.getCompound("Pos")).offset(anchor);
ArmInteractionPoint point = type.createPoint(level, pos, level.getBlockState(pos));
if (point == null)
return null;
point.deserialize(nbt, anchor);
return point;
}
protected static void transformPos(StructureTransform transform, CompoundTag nbt) {
public static void transformPos(CompoundTag nbt, StructureTransform transform) {
BlockPos pos = NbtUtils.readBlockPos(nbt.getCompound("Pos"));
pos = transform.applyWithoutOffset(pos);
nbt.put("Pos", NbtUtils.writeBlockPos(pos));
}
public static abstract class TopFaceArmInteractionPoint extends ArmInteractionPoint {
@Override
protected Vec3 getInteractionPositionVector() {
return Vec3.atLowerCornerOf(pos)
.add(.5f, 1, .5f);
}
public static boolean isInteractable(Level level, BlockPos pos, BlockState state) {
return ArmInteractionPointType.getPrimaryType(level, pos, state) != null;
}
public static class Depot extends ArmInteractionPoint {
@Override
protected Vec3 getInteractionPositionVector() {
return Vec3.atLowerCornerOf(pos)
.add(.5f, 14 / 16f, .5f);
}
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.DEPOT.has(state) || AllBlocks.WEIGHTED_EJECTOR.has(state)
|| AllBlocks.TRACK_STATION.has(state);
}
@Nullable
public static ArmInteractionPoint create(Level level, BlockPos pos, BlockState state) {
ArmInteractionPointType type = ArmInteractionPointType.getPrimaryType(level, pos, state);
if (type == null)
return null;
return type.createPoint(level, pos, state);
}
public static class Saw extends Depot {
public enum Mode {
DEPOSIT("mechanical_arm.deposit_to", ChatFormatting.GOLD, 0xFFCB74),
TAKE("mechanical_arm.extract_from", ChatFormatting.AQUA, 0x4F8A8B);
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.MECHANICAL_SAW.has(state) && state.getValue(SawBlock.FACING) == Direction.UP
&& ((KineticTileEntity) reader.getBlockEntity(pos)).getSpeed() != 0;
private final String translationKey;
private final ChatFormatting chatColor;
private final int color;
Mode(String translationKey, ChatFormatting chatColor, int color) {
this.translationKey = translationKey;
this.chatColor = chatColor;
this.color = color;
}
}
public static class Millstone extends ArmInteractionPoint {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.MILLSTONE.has(state);
public String getTranslationKey() {
return translationKey;
}
}
public static class CrushingWheels extends TopFaceArmInteractionPoint {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(state);
public ChatFormatting getChatColor() {
return chatColor;
}
}
public static class Composter extends TopFaceArmInteractionPoint {
@Override
protected Vec3 getInteractionPositionVector() {
return Vec3.atLowerCornerOf(pos)
.add(.5f, 13 / 16f, .5f);
}
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return Blocks.COMPOSTER.equals(state.getBlock());
}
@Nullable
@Override
protected IItemHandler getHandler(Level world) {
return new InvWrapper(
((ComposterBlock) Blocks.COMPOSTER).getContainer(world.getBlockState(pos), world, pos));
public int getColor() {
return color;
}
}
public static class Deployer extends ArmInteractionPoint {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.DEPLOYER.has(state);
}
@Override
protected Direction getInteractionDirection() {
return state.getValue(DeployerBlock.FACING)
.getOpposite();
}
@Override
protected Vec3 getInteractionPositionVector() {
return super.getInteractionPositionVector().add(Vec3.atLowerCornerOf(getInteractionDirection().getNormal())
.scale(.65f));
}
}
public static class BlazeBurner extends ArmInteractionPoint {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.BLAZE_BURNER.has(state);
}
@Override
protected ItemStack extract(Level world, int slot, int amount, boolean simulate) {
return ItemStack.EMPTY;
}
@Override
protected ItemStack insert(Level world, ItemStack stack, boolean simulate) {
ItemStack input = stack.copy();
InteractionResultHolder<ItemStack> res =
BlazeBurnerBlock.tryInsert(state, world, pos, input, false, false, simulate);
ItemStack remainder = res.getObject();
if (input.isEmpty()) {
return remainder;
} else {
if (!simulate)
Containers.dropItemStack(world, pos.getX(), pos.getY(), pos.getZ(), remainder);
return input;
}
}
@Override
protected void cycleMode() {}
}
public static class Crafter extends ArmInteractionPoint {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.MECHANICAL_CRAFTER.has(state);
}
@Override
protected Direction getInteractionDirection() {
return state.getValue(MechanicalCrafterBlock.HORIZONTAL_FACING)
.getOpposite();
}
@Override
protected ItemStack extract(Level world, int slot, int amount, boolean simulate) {
BlockEntity te = world.getBlockEntity(pos);
if (!(te instanceof MechanicalCrafterTileEntity))
return ItemStack.EMPTY;
MechanicalCrafterTileEntity crafter = (MechanicalCrafterTileEntity) te;
SmartInventory inventory = crafter.getInventory();
inventory.allowExtraction();
ItemStack extract = super.extract(world, slot, amount, simulate);
inventory.forbidExtraction();
return extract;
}
@Override
protected Vec3 getInteractionPositionVector() {
return super.getInteractionPositionVector().add(Vec3.atLowerCornerOf(getInteractionDirection().getNormal())
.scale(.5f));
}
}
public static class Basin extends ArmInteractionPoint {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.BASIN.has(state);
}
}
public static class Jukebox extends TopFaceArmInteractionPoint {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return state.getBlock() instanceof JukeboxBlock;
}
@Override
protected int getSlotCount(Level world) {
return 1;
}
@Override
protected ItemStack insert(Level world, ItemStack stack, boolean simulate) {
BlockEntity tileEntity = world.getBlockEntity(pos);
if (!(tileEntity instanceof JukeboxBlockEntity))
return stack;
if (!(state.getBlock() instanceof JukeboxBlock))
return stack;
JukeboxBlock jukeboxBlock = (JukeboxBlock) state.getBlock();
JukeboxBlockEntity jukeboxTE = (JukeboxBlockEntity) tileEntity;
if (!jukeboxTE.getRecord()
.isEmpty())
return stack;
if (!(stack.getItem() instanceof RecordItem))
return stack;
ItemStack remainder = stack.copy();
ItemStack toInsert = remainder.split(1);
if (!simulate && !world.isClientSide) {
jukeboxBlock.setRecord(world, pos, state, toInsert);
world.levelEvent(null, 1010, pos, Item.getId(toInsert.getItem()));
AllTriggers.triggerForNearbyPlayers(AllTriggers.MUSICAL_ARM, world, pos, 10);
}
return remainder;
}
@Override
protected ItemStack extract(Level world, int slot, int amount, boolean simulate) {
BlockEntity tileEntity = world.getBlockEntity(pos);
if (!(tileEntity instanceof JukeboxBlockEntity))
return ItemStack.EMPTY;
if (!(state.getBlock() instanceof JukeboxBlock))
return ItemStack.EMPTY;
JukeboxBlockEntity jukeboxTE = (JukeboxBlockEntity) tileEntity;
ItemStack itemstack = jukeboxTE.getRecord();
if (itemstack.isEmpty())
return ItemStack.EMPTY;
if (!simulate && !world.isClientSide) {
world.levelEvent(1010, pos, 0);
jukeboxTE.clearContent();
world.setBlock(pos, state.setValue(JukeboxBlock.HAS_RECORD, false), 2);
}
return itemstack;
}
}
public static class Belt extends Depot {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AllBlocks.BELT.has(state) && !(reader.getBlockState(pos.above())
.getBlock() instanceof BeltTunnelBlock);
}
@Override
protected void keepAlive(LevelAccessor world) {
super.keepAlive(world);
BeltTileEntity beltTE = BeltHelper.getSegmentTE(world, pos);
if (beltTE == null)
return;
TransportedItemStackHandlerBehaviour transport =
beltTE.getBehaviour(TransportedItemStackHandlerBehaviour.TYPE);
if (transport == null)
return;
MutableBoolean found = new MutableBoolean(false);
transport.handleProcessingOnAllItems(tis -> {
if (found.isTrue())
return TransportedResult.doNothing();
tis.lockedExternally = true;
found.setTrue();
return TransportedResult.doNothing();
});
}
}
public static class Chute extends TopFaceArmInteractionPoint {
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return AbstractChuteBlock.isChute(state);
}
}
public static class Funnel extends ArmInteractionPoint {
@Override
protected Vec3 getInteractionPositionVector() {
return VecHelper.getCenterOf(pos)
.add(Vec3.atLowerCornerOf(FunnelBlock.getFunnelFacing(state)
.getNormal())
.scale(-.15f));
}
@Override
protected int getSlotCount(Level world) {
return 0;
}
@Override
protected ItemStack extract(Level world, int slot, int amount, boolean simulate) {
return ItemStack.EMPTY;
}
@Override
protected Direction getInteractionDirection() {
return FunnelBlock.getFunnelFacing(state)
.getOpposite();
}
@Override
protected ItemStack insert(Level world, ItemStack stack, boolean simulate) {
FilteringBehaviour filtering = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
InvManipulationBehaviour inserter = TileEntityBehaviour.get(world, pos, InvManipulationBehaviour.TYPE);
BlockState state = world.getBlockState(pos);
if (state.getOptionalValue(BlockStateProperties.POWERED)
.orElse(false))
return stack;
if (inserter == null)
return stack;
if (filtering != null && !filtering.test(stack))
return stack;
if (simulate)
inserter.simulate();
ItemStack insert = inserter.insert(stack);
if (!simulate && insert.getCount() != stack.getCount()) {
BlockEntity tileEntity = world.getBlockEntity(pos);
if (tileEntity instanceof FunnelTileEntity) {
FunnelTileEntity funnelTileEntity = (FunnelTileEntity) tileEntity;
funnelTileEntity.onTransfer(stack);
if (funnelTileEntity.hasFlap())
funnelTileEntity.flap(true);
}
}
return insert;
}
@Override
protected boolean isValid(BlockGetter reader, BlockPos pos, BlockState state) {
return state.getBlock() instanceof AbstractFunnelBlock
&& !(state.hasProperty(FunnelBlock.EXTRACTING) && state.getValue(FunnelBlock.EXTRACTING))
&& !(state.hasProperty(BeltFunnelBlock.SHAPE)
&& state.getValue(BeltFunnelBlock.SHAPE) == Shape.PUSHING);
}
@Override
protected void cycleMode() {}
}
}

View file

@ -16,7 +16,7 @@ import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
@ -52,9 +52,10 @@ public class ArmInteractionPointHandler {
return;
ArmInteractionPoint selected = getSelected(pos);
BlockState state = world.getBlockState(pos);
if (selected == null) {
ArmInteractionPoint point = ArmInteractionPoint.createAt(world, pos);
ArmInteractionPoint point = ArmInteractionPoint.create(world, pos, state);
if (point == null)
return;
selected = point;
@ -63,10 +64,9 @@ public class ArmInteractionPointHandler {
selected.cycleMode();
if (player != null) {
String key = selected.mode == Mode.DEPOSIT ? "mechanical_arm.deposit_to" : "mechanical_arm.extract_from";
ChatFormatting colour = selected.mode == Mode.DEPOSIT ? ChatFormatting.GOLD : ChatFormatting.AQUA;
TranslatableComponent translatedBlock = new TranslatableComponent(selected.state.getBlock()
.getDescriptionId());
String key = selected.getMode().getTranslationKey();
ChatFormatting colour = selected.getMode().getChatColor();
MutableComponent translatedBlock = state.getBlock().getName();
player.displayClientMessage((Lang.translate(key, translatedBlock.withStyle(ChatFormatting.WHITE, colour)).withStyle(colour)),
true);
}
@ -95,7 +95,7 @@ public class ArmInteractionPointHandler {
int removed = 0;
for (Iterator<ArmInteractionPoint> iterator = currentSelection.iterator(); iterator.hasNext();) {
ArmInteractionPoint point = iterator.next();
if (point.pos.closerThan(pos, ArmTileEntity.getRange()))
if (point.getPos().closerThan(pos, ArmTileEntity.getRange()))
continue;
iterator.remove();
removed++;
@ -109,7 +109,7 @@ public class ArmInteractionPointHandler {
int inputs = 0;
int outputs = 0;
for (ArmInteractionPoint armInteractionPoint : currentSelection) {
if (armInteractionPoint.mode == Mode.DEPOSIT)
if (armInteractionPoint.getMode() == Mode.DEPOSIT)
outputs++;
else
inputs++;
@ -179,22 +179,22 @@ public class ArmInteractionPointHandler {
}
private static void drawOutlines(Collection<ArmInteractionPoint> selection) {
Level world = Minecraft.getInstance().level;
for (Iterator<ArmInteractionPoint> iterator = selection.iterator(); iterator.hasNext();) {
ArmInteractionPoint point = iterator.next();
BlockPos pos = point.pos;
BlockState state = world.getBlockState(pos);
if (!point.isValid(world, pos, state)) {
if (!point.isValid()) {
iterator.remove();
continue;
}
VoxelShape shape = state.getShape(world, pos);
Level level = point.getLevel();
BlockPos pos = point.getPos();
BlockState state = level.getBlockState(pos);
VoxelShape shape = state.getShape(level, pos);
if (shape.isEmpty())
continue;
int color = point.mode == Mode.DEPOSIT ? 0xffcb74 : 0x4f8a8b;
int color = point.getMode().getColor();
CreateClient.OUTLINER.showAABB(point, shape.bounds()
.move(pos))
.colored(color)
@ -214,10 +214,9 @@ public class ArmInteractionPointHandler {
}
private static ArmInteractionPoint getSelected(BlockPos pos) {
for (ArmInteractionPoint point : currentSelection) {
if (point.pos.equals(pos))
for (ArmInteractionPoint point : currentSelection)
if (point.getPos().equals(pos))
return point;
}
return null;
}

View file

@ -0,0 +1,66 @@
package com.simibubi.create.content.logistics.block.mechanicalArm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
public abstract class ArmInteractionPointType {
private static final Map<ResourceLocation, ArmInteractionPointType> TYPES = new HashMap<>();
private static final List<ArmInteractionPointType> SORTED_TYPES = new ArrayList<>();
protected final ResourceLocation id;
public ArmInteractionPointType(ResourceLocation id) {
this.id = id;
}
public static void register(ArmInteractionPointType type) {
ResourceLocation id = type.getId();
if (TYPES.containsKey(id))
throw new IllegalArgumentException("Tried to override ArmInteractionPointType registration for id '" + id + "'. This is not supported!");
TYPES.put(id, type);
SORTED_TYPES.add(type);
SORTED_TYPES.sort((t1, t2) -> t2.getPriority() - t1.getPriority());
}
@Nullable
public static ArmInteractionPointType get(ResourceLocation id) {
return TYPES.get(id);
}
public static void forEach(Consumer<ArmInteractionPointType> action) {
SORTED_TYPES.forEach(action);
}
@Nullable
public static ArmInteractionPointType getPrimaryType(Level level, BlockPos pos, BlockState state) {
for (ArmInteractionPointType type : SORTED_TYPES)
if (type.canCreatePoint(level, pos, state))
return type;
return null;
}
public final ResourceLocation getId() {
return id;
}
public abstract boolean canCreatePoint(Level level, BlockPos pos, BlockState state);
@Nullable
public abstract ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state);
public int getPriority() {
return 0;
}
}

View file

@ -9,7 +9,6 @@ import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
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.mechanicalArm.ArmInteractionPoint.Jukebox;
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPoint.Mode;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.config.AllConfigs;
@ -35,6 +34,7 @@ import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.JukeboxBlock;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
@ -116,7 +116,7 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
if (phase == Phase.MOVE_TO_INPUT) {
ArmInteractionPoint point = getTargetedInteractionPoint();
if (point != null)
point.keepAlive(level);
point.keepAlive();
}
return;
}
@ -164,9 +164,9 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
private boolean checkForMusicAmong(List<ArmInteractionPoint> list) {
for (ArmInteractionPoint armInteractionPoint : list) {
if (!(armInteractionPoint instanceof Jukebox))
if (!(armInteractionPoint instanceof AllArmInteractionPointTypes.JukeboxPoint))
continue;
BlockState state = level.getBlockState(armInteractionPoint.pos);
BlockState state = level.getBlockState(armInteractionPoint.getPos());
if (state.getOptionalValue(JukeboxBlock.HAS_RECORD).orElse(false))
return true;
}
@ -236,9 +236,9 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
InteractionPoints: for (int i = startIndex; i < scanRange; i++) {
ArmInteractionPoint armInteractionPoint = inputs.get(i);
if (!armInteractionPoint.isStillValid(level))
if (!armInteractionPoint.isValid())
continue;
for (int j = 0; j < armInteractionPoint.getSlotCount(level); j++) {
for (int j = 0; j < armInteractionPoint.getSlotCount(); j++) {
if (getDistributableAmount(armInteractionPoint, j) == 0)
continue;
@ -274,10 +274,10 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
for (int i = startIndex; i < scanRange; i++) {
ArmInteractionPoint armInteractionPoint = outputs.get(i);
if (!armInteractionPoint.isStillValid(level))
if (!armInteractionPoint.isValid())
continue;
ItemStack remainder = armInteractionPoint.insert(level, held, true);
ItemStack remainder = armInteractionPoint.insert(held, true);
if (remainder.equals(heldItem, false))
continue;
@ -311,7 +311,7 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
}
protected int getDistributableAmount(ArmInteractionPoint armInteractionPoint, int i) {
ItemStack stack = armInteractionPoint.extract(level, i, true);
ItemStack stack = armInteractionPoint.extract(i, true);
ItemStack remainder = simulateInsertion(stack);
if (stack.sameItem(remainder)) {
return stack.getCount() - remainder.getCount();
@ -320,11 +320,21 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
}
}
private ItemStack simulateInsertion(ItemStack stack) {
for (ArmInteractionPoint armInteractionPoint : outputs) {
if (armInteractionPoint.isValid())
stack = armInteractionPoint.insert(stack, true);
if (stack.isEmpty())
break;
}
return stack;
}
protected void depositItem() {
ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint();
if (armInteractionPoint != null) {
if (armInteractionPoint != null && armInteractionPoint.isValid()) {
ItemStack toInsert = heldItem.copy();
ItemStack remainder = armInteractionPoint.insert(level, toInsert, false);
ItemStack remainder = armInteractionPoint.insert(toInsert, false);
heldItem = remainder;
}
phase = heldItem.isEmpty() ? Phase.SEARCH_INPUTS : Phase.SEARCH_OUTPUTS;
@ -339,14 +349,14 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
protected void collectItem() {
ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint();
if (armInteractionPoint != null)
for (int i = 0; i < armInteractionPoint.getSlotCount(level); i++) {
if (armInteractionPoint != null && armInteractionPoint.isValid())
for (int i = 0; i < armInteractionPoint.getSlotCount(); i++) {
int amountExtracted = getDistributableAmount(armInteractionPoint, i);
if (amountExtracted == 0)
continue;
ItemStack prevHeld = heldItem;
heldItem = armInteractionPoint.extract(level, i, amountExtracted, false);
heldItem = armInteractionPoint.extract(i, amountExtracted, false);
phase = Phase.SEARCH_OUTPUTS;
chasedPointProgress = 0;
chasedPointIndex = -1;
@ -366,15 +376,6 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
setChanged();
}
private ItemStack simulateInsertion(ItemStack stack) {
for (ArmInteractionPoint armInteractionPoint : outputs) {
stack = armInteractionPoint.insert(level, stack, true);
if (stack.isEmpty())
break;
}
return stack;
}
public void redstoneUpdate() {
if (level.isClientSide)
return;
@ -392,8 +393,8 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
if (interactionPointTag == null)
return;
for (Tag inbt : interactionPointTag) {
ArmInteractionPoint.transformPos(transform, (CompoundTag) inbt);
for (Tag tag : interactionPointTag) {
ArmInteractionPoint.transformPos((CompoundTag) tag, transform);
}
notifyUpdate();
@ -408,15 +409,15 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
outputs.clear();
boolean hasBlazeBurner = false;
for (Tag inbt : interactionPointTag) {
ArmInteractionPoint point = ArmInteractionPoint.deserialize(level, worldPosition, (CompoundTag) inbt);
for (Tag tag : interactionPointTag) {
ArmInteractionPoint point = ArmInteractionPoint.deserialize((CompoundTag) tag, level, worldPosition);
if (point == null)
continue;
if (point.mode == Mode.DEPOSIT)
if (point.getMode() == Mode.DEPOSIT)
outputs.add(point);
if (point.mode == Mode.TAKE)
else if (point.getMode() == Mode.TAKE)
inputs.add(point);
hasBlazeBurner |= point instanceof ArmInteractionPoint.BlazeBurner;
hasBlazeBurner |= point instanceof AllArmInteractionPointTypes.BlazeBurnerPoint;
}
if (!level.isClientSide) {
@ -496,6 +497,10 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
previousPoint == null ? ArmAngleTarget.NO_TARGET : previousPoint.getTargetAngles(worldPosition, ceiling);
if (previousPoint != null)
previousBaseAngle = previousPoint.getTargetAngles(worldPosition, ceiling).baseAngle;
ArmInteractionPoint targetedPoint = getTargetedInteractionPoint();
if (targetedPoint != null)
targetedPoint.updateCachedState();
}
}
@ -518,6 +523,16 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
return true;
}
public void setLevel(Level level) {
super.setLevel(level);
for (ArmInteractionPoint input : inputs) {
input.setLevel(level);
}
for (ArmInteractionPoint output : outputs) {
output.setLevel(level);
}
}
private class SelectionModeValueBox extends CenteredSideValueBoxTransform {
public SelectionModeValueBox() {

View file

@ -28,8 +28,8 @@ public class AnalogLeverInstance extends BlockEntityInstance<AnalogLeverTileEnti
Material<ModelData> mat = getTransformMaterial();
handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE, blockState).createInstance();
indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR, blockState).createInstance();
handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE).createInstance();
indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR).createInstance();
transform(indicator);

View file

@ -4,6 +4,7 @@ import javax.annotation.Nullable;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.item.ItemHelper;
@ -85,7 +86,7 @@ public class ItemVaultBlock extends Block implements IWrenchable, ITE<ItemVaultT
.getBlockEntity(context.getClickedPos());
if (te instanceof ItemVaultTileEntity) {
ItemVaultTileEntity vault = (ItemVaultTileEntity) te;
ItemVaultConnectivityHandler.splitVault(vault);
ConnectivityHandler.splitMulti(vault);
vault.removeController(true);
}
state = state.setValue(LARGE, false);
@ -100,10 +101,10 @@ public class ItemVaultBlock extends Block implements IWrenchable, ITE<ItemVaultT
BlockEntity te = world.getBlockEntity(pos);
if (!(te instanceof ItemVaultTileEntity))
return;
ItemVaultTileEntity tankTE = (ItemVaultTileEntity) te;
ItemHelper.dropContents(world, pos, tankTE.inventory);
ItemVaultTileEntity vaultTE = (ItemVaultTileEntity) te;
ItemHelper.dropContents(world, pos, vaultTE.inventory);
world.removeBlockEntity(pos);
ItemVaultConnectivityHandler.splitVault(tankTE);
ConnectivityHandler.splitMulti(vaultTE);
}
}

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.logistics.block.vault;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
@ -62,7 +63,7 @@ public class ItemVaultCTBehaviour extends ConnectedTextureBehaviour {
@Override
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos,
BlockPos otherPos, Direction face) {
return state == other && ItemVaultConnectivityHandler.isConnected(reader, pos, otherPos);
return state == other && ConnectivityHandler.isConnected(reader, pos, otherPos); //ItemVaultConnectivityHandler.isConnected(reader, pos, otherPos);
}
}

View file

@ -1,329 +0,0 @@
package com.simibubi.create.content.logistics.block.vault;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.PriorityQueue;
import java.util.Set;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
public class ItemVaultConnectivityHandler {
public static void formVaults(ItemVaultTileEntity te) {
VaultSearchCache cache = new VaultSearchCache();
List<ItemVaultTileEntity> frontier = new ArrayList<>();
frontier.add(te);
formVaults(te.getType(), te.getLevel(), cache, frontier);
}
private static void formVaults(BlockEntityType<?> type, BlockGetter world, VaultSearchCache cache,
List<ItemVaultTileEntity> frontier) {
PriorityQueue<Pair<Integer, ItemVaultTileEntity>> creationQueue = makeCreationQueue();
Set<BlockPos> visited = new HashSet<>();
int minY = Integer.MAX_VALUE;
for (ItemVaultTileEntity fluidTankTileEntity : frontier) {
BlockPos pos = fluidTankTileEntity.getBlockPos();
minY = Math.min(pos.getY(), minY);
}
minY -= 3;
while (!frontier.isEmpty()) {
ItemVaultTileEntity tank = frontier.remove(0);
BlockPos tankPos = tank.getBlockPos();
if (visited.contains(tankPos))
continue;
visited.add(tankPos);
int amount = tryToFormNewVault(tank, cache, true);
if (amount > 1)
creationQueue.add(Pair.of(amount, tank));
for (Axis axis : Iterate.axes) {
Direction d = Direction.fromAxisAndDirection(axis, AxisDirection.NEGATIVE);
BlockPos next = tankPos.relative(d);
if (next.getY() <= minY)
continue;
if (visited.contains(next))
continue;
ItemVaultTileEntity nextTank = vaultAt(type, world, next);
if (nextTank == null)
continue;
if (nextTank.isRemoved())
continue;
frontier.add(nextTank);
}
}
visited.clear();
while (!creationQueue.isEmpty()) {
Pair<Integer, ItemVaultTileEntity> next = creationQueue.poll();
ItemVaultTileEntity toCreate = next.getValue();
if (visited.contains(toCreate.getBlockPos()))
continue;
visited.add(toCreate.getBlockPos());
tryToFormNewVault(toCreate, cache, false);
}
}
public static void splitVault(ItemVaultTileEntity te) {
splitVaultAndInvalidate(te, null, false);
}
private static int tryToFormNewVault(ItemVaultTileEntity te, VaultSearchCache cache, boolean simulate) {
int bestWidth = 1;
int bestAmount = -1;
if (!te.isController())
return 0;
for (int w = 1; w <= 3; w++) {
int amount = tryToFormNewVaultOfRadius(te, w, cache, true);
if (amount < bestAmount)
continue;
bestWidth = w;
bestAmount = amount;
}
if (!simulate) {
if (te.radius == bestWidth && te.radius * te.radius * te.length == bestAmount)
return bestAmount;
splitVaultAndInvalidate(te, cache, false);
tryToFormNewVaultOfRadius(te, bestWidth, cache, simulate);
te.updateConnectivity = false;
te.radius = bestWidth;
te.length = bestAmount / bestWidth / bestWidth;
BlockState state = te.getBlockState();
if (ItemVaultBlock.isVault(state))
te.getLevel()
.setBlock(te.getBlockPos(), state.setValue(ItemVaultBlock.LARGE, te.radius > 2), 22);
te.itemCapability.invalidate();
te.setChanged();
}
return bestAmount;
}
private static int tryToFormNewVaultOfRadius(ItemVaultTileEntity te, int width, VaultSearchCache cache,
boolean simulate) {
int amount = 0;
int height = 0;
BlockEntityType<?> type = te.getType();
Level world = te.getLevel();
BlockPos origin = te.getBlockPos();
boolean alongZ = ItemVaultBlock.getVaultBlockAxis(te.getBlockState()) == Axis.Z;
Search:
for (int yOffset = 0; yOffset < ItemVaultTileEntity.getMaxLength(width); yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos =
alongZ ? origin.offset(xOffset, zOffset, yOffset) : origin.offset(yOffset, xOffset, zOffset);
Optional<ItemVaultTileEntity> tank = cache.getOrCache(type, world, pos);
if (!tank.isPresent())
break Search;
ItemVaultTileEntity controller = tank.get();
int otherWidth = controller.radius;
if (otherWidth > width)
break Search;
if (otherWidth == width && controller.length == ItemVaultTileEntity.getMaxLength(width))
break Search;
if ((ItemVaultBlock.getVaultBlockAxis(controller.getBlockState()) == Axis.Z) != alongZ)
break Search;
BlockPos controllerPos = controller.getBlockPos();
if (!controllerPos.equals(origin)) {
if (alongZ && controllerPos.getX() < origin.getX())
break Search;
if (controllerPos.getY() < origin.getY())
break Search;
if (!alongZ && controllerPos.getZ() < origin.getZ())
break Search;
if (alongZ && controllerPos.getX() + otherWidth > origin.getX() + width)
break Search;
if (controllerPos.getY() + otherWidth > origin.getY() + width)
break Search;
if (!alongZ && controllerPos.getZ() + otherWidth > origin.getZ() + width)
break Search;
}
}
}
amount += width * width;
height++;
}
if (simulate)
return amount;
for (int yOffset = 0; yOffset < height; yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos =
alongZ ? origin.offset(xOffset, zOffset, yOffset) : origin.offset(yOffset, xOffset, zOffset);
ItemVaultTileEntity tank = vaultAt(type, world, pos);
if (tank == te)
continue;
splitVaultAndInvalidate(tank, cache, false);
tank.setController(origin);
tank.updateConnectivity = false;
cache.put(pos, te);
BlockState state = world.getBlockState(pos);
if (!ItemVaultBlock.isVault(state))
continue;
state = state.setValue(ItemVaultBlock.LARGE, width > 2);
world.setBlock(pos, state, 22);
}
}
}
return amount;
}
private static void splitVaultAndInvalidate(ItemVaultTileEntity te, @Nullable VaultSearchCache cache,
boolean tryReconnect) {
// tryReconnect helps whenever only few tanks have been removed
te = te.getControllerTE();
if (te == null)
return;
int height = te.length;
int width = te.radius;
BlockState state = te.getBlockState();
boolean alongZ = ItemVaultBlock.getVaultBlockAxis(state) == Axis.Z;
if (width == 1 && height == 1)
return;
Level world = te.getLevel();
BlockPos origin = te.getBlockPos();
List<ItemVaultTileEntity> frontier = new ArrayList<>();
for (int yOffset = 0; yOffset < height; yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) {
for (int zOffset = 0; zOffset < width; zOffset++) {
BlockPos pos =
alongZ ? origin.offset(xOffset, zOffset, yOffset) : origin.offset(yOffset, xOffset, zOffset);
ItemVaultTileEntity tankAt = vaultAt(te.getType(), world, pos);
if (tankAt == null)
continue;
if (!tankAt.getController()
.equals(origin))
continue;
tankAt.removeController(true);
if (tryReconnect) {
frontier.add(tankAt);
tankAt.updateConnectivity = false;
}
if (cache != null)
cache.put(pos, tankAt);
}
}
}
te.itemCapability.invalidate();
if (tryReconnect)
formVaults(te.getType(), world, cache == null ? new VaultSearchCache() : cache, frontier);
}
private static PriorityQueue<Pair<Integer, ItemVaultTileEntity>> makeCreationQueue() {
return new PriorityQueue<>(new Comparator<Pair<Integer, ItemVaultTileEntity>>() {
@Override
public int compare(Pair<Integer, ItemVaultTileEntity> o1, Pair<Integer, ItemVaultTileEntity> o2) {
return o2.getKey() - o1.getKey();
}
});
}
@Nullable
public static ItemVaultTileEntity vaultAt(BlockEntityType<?> type, BlockGetter world, BlockPos pos) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof ItemVaultTileEntity && te.getType() == type)
return (ItemVaultTileEntity) te;
return null;
}
private static class VaultSearchCache {
Map<BlockPos, Optional<ItemVaultTileEntity>> controllerMap;
public VaultSearchCache() {
controllerMap = new HashMap<>();
}
void put(BlockPos pos, ItemVaultTileEntity target) {
controllerMap.put(pos, Optional.of(target));
}
void putEmpty(BlockPos pos) {
controllerMap.put(pos, Optional.empty());
}
boolean hasVisited(BlockPos pos) {
return controllerMap.containsKey(pos);
}
Optional<ItemVaultTileEntity> getOrCache(BlockEntityType<?> type, BlockGetter world, BlockPos pos) {
if (hasVisited(pos))
return controllerMap.get(pos);
ItemVaultTileEntity tankAt = vaultAt(type, world, pos);
if (tankAt == null) {
putEmpty(pos);
return Optional.empty();
}
ItemVaultTileEntity controller = tankAt.getControllerTE();
if (controller == null) {
putEmpty(pos);
return Optional.empty();
}
put(pos, controller);
return Optional.of(controller);
}
}
public static boolean isConnected(BlockGetter world, BlockPos tankPos, BlockPos otherTankPos) {
BlockEntity te1 = world.getBlockEntity(tankPos);
BlockEntity te2 = world.getBlockEntity(otherTankPos);
if (!(te1 instanceof ItemVaultTileEntity) || !(te2 instanceof ItemVaultTileEntity))
return false;
return ((ItemVaultTileEntity) te1).getController()
.equals(((ItemVaultTileEntity) te2).getController());
}
}

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.logistics.block.vault;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos;
@ -64,7 +65,7 @@ public class ItemVaultItem extends BlockItem {
if (!ItemVaultBlock.isVault(placedOnState))
return;
ItemVaultTileEntity tankAt = ItemVaultConnectivityHandler.vaultAt(AllTileEntities.ITEM_VAULT.get(), world, placedOnPos);
ItemVaultTileEntity tankAt = ConnectivityHandler.partAt(AllTileEntities.ITEM_VAULT.get(), world, placedOnPos);
if (tankAt == null)
return;
ItemVaultTileEntity controllerTE = tankAt.getControllerTE();

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.logistics.block.vault;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.tileEntity.IMultiTileContainer;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
@ -25,7 +26,7 @@ import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileContainer {
public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileContainer.Inventory {
protected LazyOptional<IItemHandler> itemCapability;
@ -62,7 +63,7 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo
return;
if (!isController())
return;
ItemVaultConnectivityHandler.formVaults(this);
ConnectivityHandler.formMulti(this);
}
protected void updateComparators() {
@ -94,7 +95,7 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo
if (updateConnectivity)
updateConnectivity();
}
@Override
public BlockPos getLastKnownPos() {
return lastKnownPos;
@ -105,7 +106,7 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo
return controller == null || worldPosition.getX() == controller.getX()
&& worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ();
}
private void onPositionChanged() {
removeController(true);
lastKnownPos = worldPosition;
@ -155,7 +156,7 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo
public BlockPos getController() {
return isController() ? worldPosition : controller;
}
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
super.read(compound, clientPacket);
@ -209,11 +210,11 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo
compound.put("Inventory", inventory.serializeNBT());
}
}
public ItemStackHandler getInventoryOfBlock() {
return inventory;
}
public void applyInventoryToBlock(ItemStackHandler handler) {
for (int i = 0; i < inventory.getSlots(); i++)
inventory.setStackInSlot(i, i < handler.getSlots() ? handler.getStackInSlot(i) : ItemStack.EMPTY);
@ -248,7 +249,7 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo
BlockPos vaultPos = alongZ ? worldPosition.offset(xOffset, zOffset, yOffset)
: worldPosition.offset(yOffset, xOffset, zOffset);
ItemVaultTileEntity vaultAt =
ItemVaultConnectivityHandler.vaultAt(AllTileEntities.ITEM_VAULT.get(), level, vaultPos);
ConnectivityHandler.partAt(AllTileEntities.ITEM_VAULT.get(), level, vaultPos);
invs[yOffset * radius * radius + xOffset * radius + zOffset] =
vaultAt != null ? vaultAt.inventory : new ItemStackHandler();
}
@ -263,4 +264,45 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo
return radius * 3;
}
@Override
public void preventConnectivityUpdate() { updateConnectivity = false; }
@Override
public void notifyMultiUpdated() {
BlockState state = this.getBlockState();
if (ItemVaultBlock.isVault(state)) { // safety
level.setBlock(getBlockPos(), state.setValue(ItemVaultBlock.LARGE, radius > 2), 22);
}
itemCapability.invalidate();
setChanged();
}
@Override
public Direction.Axis getMainConnectionAxis() { return getMainAxisOf(this); }
@Override
public int getMaxLength(Direction.Axis longAxis, int width) {
if (longAxis == Direction.Axis.Y) return getMaxWidth();
return getMaxLength(width);
}
@Override
public int getMaxWidth() {
return 3;
}
@Override
public int getHeight() { return length; }
@Override
public int getWidth() { return radius; }
@Override
public void setHeight(int height) { this.length = height; }
@Override
public void setWidth(int width) { this.radius = width; }
@Override
public boolean hasInventory() { return true; }
}

View file

@ -77,6 +77,13 @@ public interface ItemAttribute {
return attributeType;
}
static ItemAttribute fromNBT(CompoundTag nbt) {
for (ItemAttribute itemAttribute : types)
if (itemAttribute.canRead(nbt))
return itemAttribute.readNBT(nbt.getCompound(itemAttribute.getNBTKey()));
return null;
}
default boolean appliesTo(ItemStack stack, Level world) {
return appliesTo(stack);
}
@ -87,29 +94,20 @@ public interface ItemAttribute {
return listAttributesOf(stack);
}
public List<ItemAttribute> listAttributesOf(ItemStack stack);
List<ItemAttribute> listAttributesOf(ItemStack stack);
public String getTranslationKey();
String getTranslationKey();
void writeNBT(CompoundTag nbt);
ItemAttribute readNBT(CompoundTag nbt);
public default void serializeNBT(CompoundTag nbt) {
default void serializeNBT(CompoundTag nbt) {
CompoundTag compound = new CompoundTag();
writeNBT(compound);
nbt.put(getNBTKey(), compound);
}
public static ItemAttribute fromNBT(CompoundTag nbt) {
for (ItemAttribute itemAttribute : types) {
if (!itemAttribute.canRead(nbt))
continue;
return itemAttribute.readNBT(nbt.getCompound(itemAttribute.getNBTKey()));
}
return null;
}
default Object[] getTranslationParameters() {
return new String[0];
}

View file

@ -22,8 +22,8 @@ public class SchematicannonInstance extends BlockEntityInstance<SchematicannonTi
Material<ModelData> mat = getTransformMaterial();
connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance();
pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance();
connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR).createInstance();
pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE).createInstance();
}
@Override

View file

@ -1,6 +1,6 @@
package com.simibubi.create.content.schematics.client;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
@ -33,7 +33,7 @@ public class SchematicRenderer {
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
private final Map<RenderType, SuperByteBuffer> bufferCache = new HashMap<>(getLayerCount());
private final Map<RenderType, SuperByteBuffer> bufferCache = new LinkedHashMap<>(getLayerCount());
private boolean active;
private boolean changed;
protected SchematicWorld schematic;

View file

@ -30,6 +30,7 @@ import com.tterrag.registrate.util.nullness.NonNullFunction;
import com.tterrag.registrate.util.nullness.NonNullSupplier;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
@ -168,12 +169,26 @@ public class CreateRegistrate extends AbstractRegistrate<CreateRegistrate> {
Create.asResource("fluid/" + name + "_flow"), attributesFactory, factory));
}
public <T extends ForgeFlowingFluid> FluidBuilder<T, CreateRegistrate> virtualFluid(String name, ResourceLocation still, ResourceLocation flow,
BiFunction<FluidAttributes.Builder, Fluid, FluidAttributes> attributesFactory,
NonNullFunction<ForgeFlowingFluid.Properties, T> factory) {
return entry(name,
c -> new VirtualFluidBuilder<>(self(), self(), name, c, still,
flow, attributesFactory, factory));
}
public FluidBuilder<VirtualFluid, CreateRegistrate> virtualFluid(String name) {
return entry(name,
c -> new VirtualFluidBuilder<>(self(), self(), name, c, Create.asResource("fluid/" + name + "_still"),
Create.asResource("fluid/" + name + "_flow"), null, VirtualFluid::new));
}
public FluidBuilder<VirtualFluid, CreateRegistrate> virtualFluid(String name, ResourceLocation still, ResourceLocation flow) {
return entry(name,
c -> new VirtualFluidBuilder<>(self(), self(), name, c, still,
flow, null, VirtualFluid::new));
}
public FluidBuilder<ForgeFlowingFluid.Flowing, CreateRegistrate> standardFluid(String name) {
return fluid(name, Create.asResource("fluid/" + name + "_still"), Create.asResource("fluid/" + name + "_flow"));
}

View file

@ -95,7 +95,7 @@ public class CrushingRecipeGen extends ProcessingRecipeGen {
DEEP_REDSTONE_ORE = deepslateOre(() -> Items.DEEPSLATE_REDSTONE_ORE, () -> Items.REDSTONE, 7.5f, 350),
DEEP_LAPIS_ORE = deepslateOre(() -> Items.DEEPSLATE_LAPIS_ORE, () -> Items.LAPIS_LAZULI, 12.5f, 350),
NETHER_GOLD_ORE = netherOre(() -> Items.NETHER_GOLD_ORE, () -> Items.GOLD_NUGGET, 7.5f, 350),
NETHER_GOLD_ORE = netherOre(() -> Items.NETHER_GOLD_ORE, () -> Items.GOLD_NUGGET, 18, 350),
NETHER_QUARTZ_ORE = netherOre(() -> Items.NETHER_QUARTZ_ORE, () -> Items.QUARTZ, 2.25f, 350),
RAW_COPPER_ORE = rawOre(() -> Items.RAW_COPPER, AllItems.CRUSHED_COPPER::get, 1),

View file

@ -229,7 +229,7 @@ public class ItemHelper {
for (int slot = 0; slot < inv.getSlots(); slot++) {
if (extracting.isEmpty()) {
ItemStack stackInSlot = inv.getStackInSlot(slot);
if (stackInSlot.isEmpty())
if (stackInSlot.isEmpty() || !test.test(stackInSlot))
continue;
int maxExtractionCountForItem = amountFunction.apply(stackInSlot);
if (maxExtractionCountForItem == 0)

View file

@ -1,12 +1,75 @@
package com.simibubi.create.foundation.tileEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import javax.annotation.Nullable;
public interface IMultiTileContainer {
public BlockPos getController();
public boolean isController();
public void setController(BlockPos pos);
public BlockPos getLastKnownPos();
BlockPos getController();
<T extends BlockEntity & IMultiTileContainer> T getControllerTE ();
boolean isController();
void setController(BlockPos pos);
void removeController (boolean keepContents);
BlockPos getLastKnownPos();
void preventConnectivityUpdate ();
void notifyMultiUpdated ();
// only used for FluidTank windows at present. Might be useful for similar properties on other things?
default void setExtraData (@Nullable Object data) {}
@Nullable
default Object getExtraData () { return null; }
default Object modifyExtraData (Object data) { return data; }
// multiblock structural information
Direction.Axis getMainConnectionAxis();
default Direction.Axis getMainAxisOf (BlockEntity be) { // this feels redundant, but it gives us a default to use when defining ::getMainConnectionAxis
BlockState state = be.getBlockState();
Direction.Axis axis;
if (state.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) {
axis = state.getValue(BlockStateProperties.HORIZONTAL_AXIS);
}
else if (state.hasProperty(BlockStateProperties.FACING)) {
axis = state.getValue(BlockStateProperties.FACING).getAxis();
}
else if (state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) {
axis = state.getValue(BlockStateProperties.HORIZONTAL_FACING).getAxis();
}
else axis = Direction.Axis.Y;
return axis;
}
int getMaxLength (Direction.Axis longAxis, int width);
int getMaxWidth ();
int getHeight ();
void setHeight (int height);
int getWidth ();
void setWidth (int width);
public interface Inventory extends IMultiTileContainer {
default boolean hasInventory() { return false; }
}
public interface Fluid extends IMultiTileContainer {
// done here rather than through the Capability to allow greater flexibility
default boolean hasTank() { return false; }
default int getTankSize(int tank) { return 0; }
default void setTankSize(int tank, int blocks) {}
default IFluidTank getTank(int tank) { return null; }
default FluidStack getFluid(int tank) { return FluidStack.EMPTY; }
}
}

View file

@ -17,7 +17,8 @@ import net.minecraft.world.phys.Vec3;
public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour {
public static BehaviourType<TransportedItemStackHandlerBehaviour> TYPE = new BehaviourType<>();
public static final BehaviourType<TransportedItemStackHandlerBehaviour> TYPE = new BehaviourType<>();
private ProcessingCallback processingCallback;
private PositionGetter positionGetter;

View file

@ -25,7 +25,7 @@ import net.minecraftforge.items.ItemHandlerHelper;
public class FilteringBehaviour extends TileEntityBehaviour {
public static BehaviourType<FilteringBehaviour> TYPE = new BehaviourType<>();
public static final BehaviourType<FilteringBehaviour> TYPE = new BehaviourType<>();
ValueBoxTransform slotPositioning;
boolean showCount;

View file

@ -22,7 +22,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler;
public class SmartFluidTankBehaviour extends TileEntityBehaviour {
public static BehaviourType<SmartFluidTankBehaviour>
public static final BehaviourType<SmartFluidTankBehaviour>
TYPE = new BehaviourType<>(), INPUT = new BehaviourType<>("Input"), OUTPUT = new BehaviourType<>("Output");

View file

@ -15,7 +15,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
public class TankManipulationBehaviour extends CapManipulationBehaviourBase<IFluidHandler, TankManipulationBehaviour> {
public static BehaviourType<TankManipulationBehaviour> OBSERVE = new BehaviourType<>();
public static final BehaviourType<TankManipulationBehaviour> OBSERVE = new BehaviourType<>();
private BehaviourType<TankManipulationBehaviour> behaviourType;
public TankManipulationBehaviour(SmartTileEntity te, InterfaceProvider target) {

View file

@ -23,7 +23,7 @@ import net.minecraft.world.phys.Vec3;
public class LinkBehaviour extends TileEntityBehaviour implements IRedstoneLinkable {
public static BehaviourType<LinkBehaviour> TYPE = new BehaviourType<>();
public static final BehaviourType<LinkBehaviour> TYPE = new BehaviourType<>();
enum Mode {
TRANSMIT, RECEIVE

View file

@ -18,7 +18,7 @@ import net.minecraft.world.phys.Vec3;
public class ScrollValueBehaviour extends TileEntityBehaviour {
public static BehaviourType<ScrollValueBehaviour> TYPE = new BehaviourType<>();
public static final BehaviourType<ScrollValueBehaviour> TYPE = new BehaviourType<>();
ValueBoxTransform slotPositioning;
Vec3 textShift;

View file

@ -10,7 +10,7 @@ import net.minecraft.nbt.CompoundTag;
public class DeferralBehaviour extends TileEntityBehaviour {
public static BehaviourType<DeferralBehaviour> TYPE = new BehaviourType<>();
public static final BehaviourType<DeferralBehaviour> TYPE = new BehaviourType<>();
private boolean needsUpdate;
private Supplier<Boolean> callback;

View file

@ -18,7 +18,7 @@ Technology that empowers the player.'''
[[dependencies.create]]
modId="forge"
mandatory=true
versionRange="[40.0.0,)"
versionRange="[40.1.0,)"
ordering="NONE"
side="BOTH"
@ -32,6 +32,6 @@ Technology that empowers the player.'''
[[dependencies.create]]
modId="flywheel"
mandatory=true
versionRange="[1.18-0.6.2,1.18-0.6.3)"
versionRange="[1.18-0.7.0,1.18-0.7.1)"
ordering="AFTER"
side="CLIENT"

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,4 @@
{
"_": "Missing Localizations: 330",
"_": "->------------------------] Game Elements [------------------------<-",
@ -567,11 +566,12 @@
"item.create.chromatic_compound": "Compuesto cromático",
"item.create.cinder_flour": "Harina del Nether",
"item.create.copper_backtank": "Depósito trasero de cobre",
"item.create.copper_backtank_placeable": "Depósito de cobre colocable",
"item.create.copper_nugget": "Pepita de cobre",
"item.create.copper_sheet": "Lámina de cobre",
"item.create.crafter_slot_cover": "Tapa de ranura del ensamblador mecánico",
"item.create.crafting_blueprint": "Plano de elaboración",
"item.create.creative_blaze_cake": "´Pastel de blaze creativo",
"item.create.creative_blaze_cake": "Pastel de blaze creativo",
"item.create.crushed_aluminum_ore": "Mineral de aluminio molido",
"item.create.crushed_copper_ore": "Mineral de cobre molido",
"item.create.crushed_gold_ore": "Mineral de oro molido",
@ -636,7 +636,7 @@
"advancement.create.root": "Bienvenido a Create",
"advancement.create.root.desc": "¡Es hora de empezar a construir increíbles artefactos animados!",
"advancement.creatse.andesite_alloy": "Aleaciones en abundancia",
"advancement.create.andesite_alloy": "Aliteraciones a montones",
"advancement.create.andesite_alloy.desc": "Los materiales de Create tienen nombres extraños, la aleación de andesita es uno de ellos.",
"advancement.create.its_alive": "¡Está vivo!",
"advancement.create.its_alive.desc": "Mira cómo gira tu primer componente cinético.",
@ -821,6 +821,8 @@
"create.recipe.fan_washing.fan": "Ventilador detrás del agua fluyente",
"create.recipe.fan_smoking": "Ahumador a granel",
"create.recipe.fan_smoking.fan": "Ventilador detrás del fuego",
"create.recipe.fan_haunting": "Maldecidor a granel",
"create.recipe.fan_haunting.fan": "Ventilador detrás del fuego de alma",
"create.recipe.fan_blasting": "Voladuras a granel",
"create.recipe.fan_blasting.fan": "Ventilador detrás de la lava",
"create.recipe.pressing": "Prensando",
@ -1163,6 +1165,8 @@
"create.item_attributes.furnace_fuel.inverted": "no es combustible para hornos",
"create.item_attributes.washable": "se puede lavar",
"create.item_attributes.washable.inverted": "no se puede lavar",
"create.item_attributes.hauntable": "puede ser maldito",
"create.item_attributes.hauntable.inverted": "no puede ser maldito",
"create.item_attributes.crushable": "puede ser molido",
"create.item_attributes.crushable.inverted": "no puede ser molido",
"create.item_attributes.smeltable": "se puede fundir",
@ -1227,6 +1231,7 @@
"create.tooltip.keyCtrl": "Ctrl",
"create.tooltip.speedRequirement": "Requisitos de velocidad: %1$s",
"create.tooltip.speedRequirement.none": "Ninguno",
"create.tooltip.speedRequirement.slow": "Lento",
"create.tooltip.speedRequirement.medium": "Moderado",
"create.tooltip.speedRequirement.fast": "Rápido",
"create.tooltip.stressImpact": "Impacto de estrés: %1$s",
@ -2438,6 +2443,6 @@
"create.ponder.windmill_structure.header": "Artefactos estacionarios de molinos de viento",
"create.ponder.windmill_structure.text_1": "Cualquier estructura puede contar como un molino de viento válido, siempre que contenga al menos 8 velas.",
"_": "¡Gracias por traducir Create!"
"_": "Thank you for translating Create!"
}

View file

@ -803,6 +803,16 @@
"death.attack.create.cuckoo_clock_explosion": "%1$s foi explodido por relógio cuco adulterado",
"death.attack.create.cuckoo_clock_explosion.player": "%1$s foi explodido por relógio cuco adulterado",
"create.block.deployer.damage_source_name": "Implantador rebelde",
"create.block.cart_assembler.invalid": "Coloque o seu montador de carrinho de minas num trilho",
"create.menu.return": "Retornar ao menu",
"create.menu.configure": "Configurar...",
"create.menu.ponder_index": "Tabela do ponderamento",
"create.menu.only_ingame": "Disponível no menu de pausa",
"create.menu.project_page": "Página do projeto",
"create.menu.report_bugs": "Informar um erro",
"create.menu.support": "Suporte nós",
"create.recipe.crushing": "Triturando",
"create.recipe.milling": "Moendo",
@ -818,6 +828,7 @@
"create.recipe.mixing": "Misturando",
"create.recipe.deploying": "Implantando",
"create.recipe.automatic_shapeless": "Fabricação sem forma automático",
"create.recipe.automatic_brewing": "Produção de poções",
"create.recipe.packing": "Compactando",
"create.recipe.automatic_packing": "Compactamento automático",
"create.recipe.sawing": "Serrando",
@ -869,18 +880,22 @@
"create.action.discard": "Descartar",
"create.keyinfo.toolmenu": "Menu Focal da Ferramenta",
"create.keyinfo.toolbelt": "Acessa caixas de ferramenta próximas",
"create.keyinfo.scrollup": "Simular a roda do mouse (para cima) (no mundo)",
"create.keyinfo.scrolldown": "Simular a roda do mouse (para baixo) (no mundo)",
"create.gui.scrollInput.defaultTitle": "Escolha uma Opção:",
"create.gui.scrollInput.scrollToModify": "Role o mouse para Modificar",
"create.gui.scrollInput.scrollToAdjustAmount": "Role o mouse para ajustar a quantidade",
"create.gui.scrollInput.scrollToSelect": "Role o mouse para Selecionar",
"create.gui.scrollInput.shiftScrollsFaster": "Shift para rolar o mouse mais rapido",
"create.gui.toolmenu.focusKey": "Segure [%1$s] para Focar",
"create.gui.toolmenu.cycle": "[SCROLL] para Circular",
"create.toolbox.unequip": "Desequipar: %1$s",
"create.toolbox.outOfRange": "Caixa de ferramentas do item segurado fora de alcance",
"create.toolbox.detach": "Parar de rastrear e manter item",
"create.toolbox.depositAll": "Retornar itens para caixa de ferramenta próxima",
"create.toolbox.depositAll": "Retorna itens para caixa de ferramenta próxima",
"create.toolbox.depositBox": "Retornar itens para caixa de ferramenta",
"create.gui.symmetryWand.mirrorType": "Espelhar",
@ -895,17 +910,90 @@
"create.orientation.horizontal": "Horizontal",
"create.orientation.alongZ": "Através de Z",
"create.orientation.alongX": "Através de X",
"create.minecart_coupling.two_couplings_max": "Carrinhos de mina não podem ter mais de dois acoplamentos cada",
"create.minecart_coupling.unloaded": "Partes do seu trem aparentam estar em um chunk descarregado",
"create.minecart_coupling.no_loops": "Acoplamentos não podem formar um loop",
"create.minecart_coupling.removed": "Removeu todos os acoplamentos do carrinho de mina",
"create.minecart_coupling.too_far": "Carrinhos de mina estão muito distanciados",
"create.contraptions.movement_mode": "Modo de movimento",
"create.contraptions.movement_mode.move_place": "Sempre colocar quando parado",
"create.contraptions.movement_mode.move_place_returned": "Colocar apenas na posição inicial",
"create.contraptions.movement_mode.move_never_place": "Colocar apenas caso a âncora seja destruída",
"create.contraptions.movement_mode.rotate_place": "Sempre colocar quando parado",
"create.contraptions.movement_mode.rotate_place_returned": "Apenas colocar perto do angulo inicial",
"create.contraptions.movement_mode.rotate_never_place": "Colocar apenas caso a âncora seja destruída",
"create.contraptions.cart_movement_mode": "Modo de movimento do carrinho",
"create.contraptions.cart_movement_mode.rotate": "Sempre apontar para a direção do movimento",
"create.contraptions.cart_movement_mode.rotate_paused": "Pausar atores quando girando",
"create.contraptions.cart_movement_mode.rotation_locked": "Travar a rotação",
"create.contraptions.windmill.rotation_direction": "Direção da rotação",
"create.contraptions.clockwork.clock_hands": "Ponteiros do relogio",
"create.contraptions.clockwork.hour_first": "Ponteiro da hora primeiro",
"create.contraptions.clockwork.minute_first": "Ponteiro do minuto primeiro",
"create.contraptions.clockwork.hour_first_24": "Ponteiro das 24 horas primeiro",
"create.logistics.filter": "Filtro",
"create.logistics.recipe_filter": "Filtro de receitas",
"create.logistics.fluid_filter": "Filtro de fluido",
"create.logistics.firstFrequency": "Freq. #1",
"create.logistics.secondFrequency": "Freq. #2",
"create.logistics.filter.apply": "Aplicou filtro para %1$s.",
"create.logistics.filter.apply_click_again": "Aplicou filtro para %1$s, Clique denovo para copiar quantidade.",
"create.logistics.filter.apply_count": "Aplicou quantidade de extração para o filtro.",
"create.gui.goggles.generator_stats": "Estatísticas do gerador:",
"create.gui.goggles.kinetic_stats": "Estatísticas cinéticas:",
"create.gui.goggles.at_current_speed": "Na velocidade atual",
"create.gui.goggles.pole_length": "Comprimento da vara:",
"create.gui.goggles.fluid_container": "Informação do recipiente de fluido:",
"create.gui.goggles.fluid_container.capacity": "Capacidade: ",
"create.gui.assembly.exception": "Não foi possível montar essa engenhoca:",
"create.gui.assembly.exception.unmovableBlock": "Bloco imovel (%4$s) em [%1$s,%2$s,%3$s]",
"create.gui.assembly.exception.chunkNotLoaded": "O bloco em [%1$s,%2$s,%3$s] não estava em um chunk carregado",
"create.gui.assembly.exception.structureTooLarge": "Tem muitos blocos incluídos na engenhoca. O limite configurado é: %1$s",
"create.gui.assembly.exception.tooManyPistonPoles": "Tem muitas varetas de extensão colocadas nesse pistão. O limite configurado é: %1$s",
"create.gui.assembly.exception.noPistonPoles": "O pistão esta faltando algumas varetas de extensão",
"create.gui.assembly.exception.not_enough_sails": "A estrutura conectada não possui o número suficiente de blocos tipo vela: %1$s\nUm mínimo de %2$s são requeridos",
"create.gui.gauge.info_header": "Informação do medidor:",
"create.gui.speedometer.title": "Velocidade de rotação",
"create.gui.stressometer.title": "Estresse do sistema",
"create.gui.stressometer.capacity": "Capacidade restante",
"create.gui.stressometer.overstressed": "Sobre estressado",
"create.gui.stressometer.no_rotation": "Nenhuma rotação",
"create.gui.contraptions.not_fast_enough": "Aparenta que esse %1$s não _está_ girando com _a velocidade_ _necessária_.",
"create.gui.contraptions.network_overstressed": "Aparenta que essa engenhoca está _sobre estressada_. Adicione mais fontes ou _desacelere_ __ os componentes que tem um _impacto de_ _stress alto_.",
"create.gui.adjustable_crate.title": "UNLOCALIZED: Adjustable Crate",
"create.gui.adjustable_crate.storageSpace": "UNLOCALIZED: Storage Space",
"create.gui.stockpile_switch.title": "Dijuntor de armazenamento",
"create.gui.stockpile_switch.invert_signal": "Inverter sinal",
"create.gui.stockpile_switch.move_to_lower_at": "Mover para a faixa mais baixa %1$s%%",
"create.gui.stockpile_switch.move_to_upper_at": "Mover para a faixa mais alta %1$s%%",
"create.gui.sequenced_gearshift.title": "Câmbio sequenciado",
"create.gui.sequenced_gearshift.instruction": "Instruções",
"create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "Rotacionar por angulo",
"create.gui.sequenced_gearshift.instruction.turn_angle": "Giro",
"create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Angulo",
"create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "Rotacionar par mover Pistão/Polia/Portico",
"create.gui.sequenced_gearshift.instruction.turn_distance": "Pistão",
"create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distancia",
"create.gui.sequenced_gearshift.instruction.delay.descriptive": "Espera",
"create.gui.sequenced_gearshift.instruction.delay": "Esperar",
"create.gui.sequenced_gearshift.instruction.delay.duration": "Duração",
"create.gui.sequenced_gearshift.instruction.end.descriptive": "Terminar",
"create.gui.sequenced_gearshift.instruction.end": "Termino",
"create.gui.sequenced_gearshift.instruction.await.descriptive": "Esperar novo pulso de redstone",
"create.gui.sequenced_gearshift.instruction.await": "Espera",
"create.gui.sequenced_gearshift.speed": "Velocidade, Direção",
"create.gui.sequenced_gearshift.speed.forward": "Velocidade inicial, Para frente",
"create.gui.sequenced_gearshift.speed.forward_fast": "Dobro da velocidade, Para frente",
"create.gui.sequenced_gearshift.speed.back": "Velocidade inicial, Para trás",
"create.gui.sequenced_gearshift.speed.back_fast": "Dobro da velocidade, Para trás",
"create.schematicAndQuill.dimensions": "Tamanho Esquema: %1$sx%2$sx%3$s",
"create.schematicAndQuill.firstPos": "Primeira posição feita.",
"create.schematicAndQuill.secondPos": "Segunda posição feita.",
"create.schematicAndQuill.noTarget": "Seguro [Ctrl] para selecionar Blocos de Ar.",
"create.schematicAndQuill.noTarget": "Seguro [Ctrl] para seleccionar Blocos de Ar.",
"create.schematicAndQuill.abort": "Seleção removida.",
"create.schematicAndQuill.title": "Nome do esquema:",
"create.schematicAndQuill.convert": "Salvar e carregar arquivo imediatamente",
@ -945,7 +1033,7 @@
"create.schematic.tool.rotate.description.1": "[CTRL]-Rolar para rolar 90 Graus",
"create.schematic.tool.rotate.description.2": "",
"create.schematic.tool.rotate.description.3": "",
"create.schematic.tool.print.description.0": "Coloca estrutura no mundo instantaneamente",
"create.schematic.tool.print.description.0": "Colocá estrutura no mundo instantaneamente",
"create.schematic.tool.print.description.1": "[Botão-Direito] para confirmar a posição atual.",
"create.schematic.tool.print.description.2": "Esta ferramenta é para o Modo Criativo apenas.",
"create.schematic.tool.print.description.3": "",
@ -957,7 +1045,12 @@
"create.schematics.synchronizing": "Sincronizando...",
"create.schematics.uploadTooLarge": "Seu esquema é muito grande",
"create.schematics.maxAllowedSize": "O tamanho máximo permitido para o esquema é:",
"create.gui.schematicTable.refresh": "atualizar arquivos",
"create.gui.schematicTable.open_folder": "Abrir pasta",
"create.gui.schematicTable.title": "Mesa de Desenho",
"create.gui.schematicTable.availableSchematics": "Esquema disponíveis",
"create.gui.schematicTable.noSchematics": "Nenhum esquema salvo",
"create.gui.schematicTable.uploading": "Importando...",
"create.gui.schematicTable.finished": "Envio Concluído!",
"create.gui.schematicannon.title": "Canhão de esquema",
@ -967,14 +1060,18 @@
"create.gui.schematicannon.shotsRemainingWithBackup": "Com backup: %1$s",
"create.gui.schematicannon.optionEnabled": "Habilitado Atualmente",
"create.gui.schematicannon.optionDisabled": "Desabilitado Atualmente",
"create.gui.schematicannon.showOptions": "Mostrar as configurações da impressora",
"create.gui.schematicannon.option.dontReplaceSolid": "Não Substituir Blocos Sólidos",
"create.gui.schematicannon.option.replaceWithSolid": "Substituir Blocos Sólidos",
"create.gui.schematicannon.option.replaceWithAny": "Substituir Sólidos com Qualquer",
"create.gui.schematicannon.option.replaceWithEmpty": "Substituir Sólidos com Vazio",
"create.gui.schematicannon.option.skipMissing": "Pulando Blocos faltantes",
"create.gui.schematicannon.option.skipTileEntities": "Proteger Entidades Entalhadas",
"create.gui.schematicannon.option.skipMissing.description": "Se o Canhão de esquema não encontrar o Bloco para colocar, ele irá continuar para a próx. Posição.",
"create.gui.schematicannon.option.skipTileEntities.description": "O Canhão de esquema vai evitar substituir blocos que contêm dados como Baus.",
"create.gui.schematicannon.option.skipTileEntities": "Proteger tile entities",
"create.gui.schematicannon.slot.gunpowder": "Adicionar pólvora para carregar o canhão",
"create.gui.schematicannon.slot.listPrinter": "Coloque livros aqui para imprimir uma lista para o seu esquema",
"create.gui.schematicannon.slot.schematic": "Adicione o seu esquema aqui. Tenha certeza que ele está colocado em um lugar especifico.",
"create.gui.schematicannon.option.skipMissing.description": "Se o Canhão de esquema não encontrar o Bloco para colocar, ele irá continuar para a próxima. Posição.",
"create.gui.schematicannon.option.skipTileEntities.description": "O Canhão de esquema vai evitar substituir blocos que contêm dados como Baús.",
"create.gui.schematicannon.option.dontReplaceSolid.description": "O Canhão de esquema nunca irá substituir Blocos sólidos na área em trabalho, apenas não-Sólidos e Ar.",
"create.gui.schematicannon.option.replaceWithSolid.description": "O Canhão de esquema irá apenas substituir Blocos sólidos na área de trabalho, se o Esquema conter um bloco Sólido naquela posição.",
"create.gui.schematicannon.option.replaceWithAny.description": "O Canhão de esquema irá substituir Blocos sólidos na área de trabalho, se o Esquema conter qualquer Bloco naquela posição.",
@ -998,10 +1095,239 @@
"create.schematicannon.status.schematicNotPlaced": "Esquema não Colocado",
"create.schematicannon.status.schematicExpired": "Arquivo de Esquema Expirado",
"create.materialChecklist": "Lista de materiais",
"create.gui.filter.deny_list": "Lista de negação",
"create.gui.filter.deny_list.description": "Itens passam se eles não encaixam em nenhum dos acima. Uma lista de negação vazia aceita tudo.",
"create.gui.filter.allow_list": "Lista de permissão",
"create.gui.filter.allow_list.description": "Itens passam se eles se encaixam em algum dos acima. Uma lista de permissão vazia rejeita tudo.",
"create.gui.filter.respect_data": "Respeitar informação",
"create.gui.filter.respect_data.description": "Itens apenas se encaixam caso a durabilidade, encantamentos e outros atributos se encaixam também.",
"create.gui.filter.ignore_data": "Ignorar informação",
"create.gui.filter.ignore_data.description": "Itens se enquadram não importa os seus atributos.",
"create.item_attributes.placeable": "É colocavel",
"create.item_attributes.placeable.inverted": "Não é colocavel",
"create.item_attributes.consumable": "É comestivel",
"create.item_attributes.consumable.inverted": "Não é comestivel",
"create.item_attributes.fluid_container": "Pode armazenar fluidos",
"create.item_attributes.fluid_container.inverted": "Não pode armazenar fluidos",
"create.item_attributes.enchanted": "Está encantado",
"create.item_attributes.enchanted.inverted": "Não está encantado",
"create.item_attributes.max_enchanted": "Está encantado no nível máximo",
"create.item_attributes.max_enchanted.inverted": "Não está encantado no nível maximo",
"create.item_attributes.renamed": "Tem nome customizado",
"create.item_attributes.renamed.inverted": "Não tem nome customizado",
"create.item_attributes.damaged": "Está danificado",
"create.item_attributes.damaged.inverted": "Não está danificado",
"create.item_attributes.badly_damaged": "Está severamente danificado",
"create.item_attributes.badly_damaged.inverted": "Não esta severamente danificado",
"create.item_attributes.not_stackable": "Não pode ser empilhado",
"create.item_attributes.not_stackable.inverted": "Pode ser empilhado",
"create.item_attributes.equipable": "Pode ser equipado",
"create.item_attributes.equipable.inverted": "Não pode ser equipado",
"create.item_attributes.furnace_fuel": "è combustivel",
"create.item_attributes.furnace_fuel.inverted": "Não é combustivel",
"create.item_attributes.washable": "Pode ser lavado",
"create.item_attributes.washable.inverted": "Não pode ser lavado",
"create.item_attributes.hauntable": "Pode ser amaldiçoado",
"create.item_attributes.hauntable.inverted": "Não pode ser amaldiçoado",
"create.item_attributes.crushable": "Pode ser triturado",
"create.item_attributes.crushable.inverted": "Não pode ser triturado",
"create.item_attributes.smeltable": "Pode ser fundido",
"create.item_attributes.smeltable.inverted": "Não pode ser fundido",
"create.item_attributes.smokable": "Pode ser defumado",
"create.item_attributes.smokable.inverted": "Não pode ser defumado",
"create.item_attributes.blastable": "È fundível no alto-forno",
"create.item_attributes.blastable.inverted": "Não é fundível no alto-forno",
"create.item_attributes.shulker_level": "O shulker é %1$s",
"create.item_attributes.shulker_level.inverted": "O shulker não é %1$s",
"create.item_attributes.shulker_level.full": "Cheio",
"create.item_attributes.shulker_level.empty": "Vazio",
"create.item_attributes.shulker_level.partial": "Parcialmente cheio",
"create.item_attributes.in_tag": "è marcado %1$s",
"create.item_attributes.in_tag.inverted": "Não é marcado %1$s",
"create.item_attributes.in_item_group": "Está no grupo '%1$s'",
"create.item_attributes.in_item_group.inverted": "Não esta no grupo '%1$s'",
"create.item_attributes.added_by": "Foi adicionado por %1$s",
"create.item_attributes.added_by.inverted": "Não foi adicionado por %1$s",
"create.item_attributes.has_enchant": "Está encantado com %1$s",
"create.item_attributes.has_enchant.inverted": "Não esta encantado com %1$s",
"create.item_attributes.color": "Esta tingido de %1$s",
"create.item_attributes.color.inverted": "Não está tingido de %1$s",
"create.item_attributes.has_fluid": "Contem %1$s",
"create.item_attributes.has_fluid.inverted": "Não contem %1$s",
"create.item_attributes.has_name": "Tem o nome %1$s",
"create.item_attributes.has_name.inverted": "Não tem o nome %1$s",
"create.item_attributes.book_author": "Tem a autoria de %1$s",
"create.item_attributes.book_author.inverted": "Não tem a autoria de %1$s",
"create.item_attributes.book_copy_original": "É original",
"create.item_attributes.book_copy_original.inverted": "Não é original",
"create.item_attributes.book_copy_first": "É uma cópia da primeira geração",
"create.item_attributes.book_copy_first.inverted": "Não é uma copia de primeira geração",
"create.item_attributes.book_copy_second": "É uma cópia de segunda geração",
"create.item_attributes.book_copy_second.inverted": "Não é uma copia de segunda geração",
"create.item_attributes.book_copy_tattered": "É uma bagunça esfarrapada",
"create.item_attributes.book_copy_tattered.inverted": "Não é uma bagunça esfarrapada",
"create.item_attributes.astralsorcery_amulet": "Melhora %1$s",
"create.item_attributes.astralsorcery_amulet.inverted": "Não melhora %1$s",
"create.item_attributes.astralsorcery_constellation": "Esta sintonizado a %1$s",
"create.item_attributes.astralsorcery_constellation.inverted": "Não esta sintonizado a %1$s",
"create.item_attributes.astralsorcery_crystal": "Tem atributos de cristais %1$s",
"create.item_attributes.astralsorcery_crystal.inverted": "Não tem atributos de cristais %1$s",
"create.item_attributes.astralsorcery_perk_gem": " %1$s Tem um atributo de benefio",
"create.item_attributes.astralsorcery_perk_gem.inverted": "%1$s Não tem um atributo de benefio",
"create.gui.attribute_filter.no_selected_attributes": "Nenhum atributo selecionado",
"create.gui.attribute_filter.selected_attributes": "Atributos selecionados:",
"create.gui.attribute_filter.add_attribute": "Adicionar atributo a lista",
"create.gui.attribute_filter.add_inverted_attribute": "Adicionar atributo oposto a lista",
"create.gui.attribute_filter.allow_list_disjunctive": "Lista de permissão (Qualquer)",
"create.gui.attribute_filter.allow_list_disjunctive.description": "Itens passam se eles tiverem qualquer atributo selecionado.",
"create.gui.attribute_filter.allow_list_conjunctive": "Lista de permissão (Todos)",
"create.gui.attribute_filter.allow_list_conjunctive.description": "Itens passam se eles tiverem TODOS atributos selecionados.",
"create.gui.attribute_filter.deny_list": "lista de negação",
"create.gui.attribute_filter.deny_list.description": "Itens passam se eles NÃO tiverem qualquer atributo selecionado.",
"create.gui.attribute_filter.add_reference_item": "Adicionar item referência",
"create.tooltip.holdForDescription": "Segure [%1$s] para o sumário",
"create.tooltip.holdForControls": "Segure [%1$s] para os controles",
"create.tooltip.keyShift": "Shift",
"create.tooltip.keyCtrl": "Ctrl",
"create.tooltip.speedRequirement": "Requerimento de velocidade: %1$s",
"create.tooltip.speedRequirement.none": "Nenhum",
"create.tooltip.speedRequirement.slow": "Devagar",
"create.tooltip.speedRequirement.medium": "Modereado",
"create.tooltip.speedRequirement.fast": "Rapido",
"create.tooltip.stressImpact": "Impacto de stress: %1$s",
"create.tooltip.stressImpact.low": " Baixo",
"create.tooltip.stressImpact.medium": " Moderado",
"create.tooltip.stressImpact.high": " Alto",
"create.tooltip.stressImpact.overstressed": ": Sobre estresse",
"create.tooltip.capacityProvided": "Capacidade de stress cinético: %1$s",
"create.tooltip.capacityProvided.low": " Pequeno",
"create.tooltip.capacityProvided.medium": " Médio",
"create.tooltip.capacityProvided.high": " Grande",
"create.tooltip.generationSpeed": " Gera em %1$s %2$s",
"create.tooltip.analogStrength": " Força analogica: %1$s/15",
"create.mechanical_arm.extract_from": " Pegar itens de %1$s",
"create.mechanical_arm.deposit_to": " Depositar itens para %1$s",
"create.mechanical_arm.summary": "Braço mecânico tem %1$s entrada(s) e %2$s saida(s).",
"create.mechanical_arm.points_outside_range": "%1$s Ponto(s) de interação removidos pelas limitações de alcance.",
"create.weighted_ejector.target_set": "Alvo selecionado",
"create.weighted_ejector.target_not_valid": "Ejetando para o bloco adjacente (Alvo não foi valido)",
"create.weighted_ejector.no_target": "Ejetando para o bloco adjacente (Nenhum alvo foi selecionado)",
"create.weighted_ejector.targeting": "Ejetando para [%1$s,%2$s,%3$s]",
"create.weighted_ejector.stack_size": "Tamanho da pilha ejetada",
"create.logistics.when_multiple_outputs_available": "Quando multiplas saidas selecionadas",
"create.mechanical_arm.selection_mode.round_robin": "Rodízio",
"create.mechanical_arm.selection_mode.forced_round_robin": "Rodízio forçado",
"create.mechanical_arm.selection_mode.prefer_first": "Preferir primeiro alvo",
"create.tunnel.selection_mode.split": "Dividir",
"create.tunnel.selection_mode.forced_split": "Divisão forçada",
"create.tunnel.selection_mode.round_robin": "Rodízio",
"create.tunnel.selection_mode.forced_round_robin": "Rodízio forçado",
"create.tunnel.selection_mode.prefer_nearest": "Preferir o mais perto",
"create.tunnel.selection_mode.randomize": "Aleatorizar",
"create.tunnel.selection_mode.synchronize": "Sincronizar as entradas",
"create.tooltip.chute.header": "Informação da calha",
"create.tooltip.chute.items_move_down": "Itens movimentam para baixo",
"create.tooltip.chute.items_move_up": "Itens movem para cima",
"create.tooltip.chute.no_fans_attached": "Não conectado com um ventilador",
"create.tooltip.chute.fans_push_up": "Ventiladores sopram de baixo",
"create.tooltip.chute.fans_push_down": "Ventiladores sopram de cima",
"create.tooltip.chute.fans_pull_up": "Ventiladores sugam de cima",
"create.tooltip.chute.fans_pull_down": "Ventiladores sugam de baixo",
"create.tooltip.chute.contains": "Contem: %1$s x%2$s",
"create.tooltip.brass_tunnel.contains": "Distribuindo:",
"create.tooltip.brass_tunnel.contains_entry": " > %1$s x%2$s",
"create.tooltip.brass_tunnel.retrieve": "Clique direito para recuperar item",
"create.linked_controller.bind_mode": "Modo de vinculação",
"create.linked_controller.press_keybind": "Aperte %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, para vincular essa frequencia para tecla respectiva",
"create.linked_controller.key_bound": "Frequência vinculada com %1$s",
"create.linked_controller.frequency_slot_1": "Tecla: %1$s, Freq. #1",
"create.linked_controller.frequency_slot_2": "Tecla: %1$s, Freq. #2",
"create.crafting_blueprint.crafting_slot": "Slot de ingrediente",
"create.crafting_blueprint.filter_items_viable": "Filtros avançados são viaveis",
"create.crafting_blueprint.display_slot": "Slot de exibição",
"create.crafting_blueprint.inferred": "Deduzido pela receita",
"create.crafting_blueprint.manually_assigned": "Designado manualmente",
"create.crafting_blueprint.secondary_display_slot": "Slot de exibição secundario",
"create.crafting_blueprint.optional": "Opcional",
"create.potato_cannon.ammo.attack_damage": " %1$s Dano de ataque",
"create.potato_cannon.ammo.reload_ticks": " %1$s Velocidade de recarregamento",
"create.potato_cannon.ammo.knockback": " %1$s Repulsão do projetil",
"create.hint.hose_pulley.title": "Abastecimento sem fundo",
"create.hint.hose_pulley": "O corpo de fluido selecionado é considerado infinito.",
"create.hint.mechanical_arm_no_targets.title": "Sem alvos",
"create.hint.mechanical_arm_no_targets": "Aparentemente esse _Braço_ _Mecânico_ não foi designado nenhum _alvo._ Selecione esteiras, depósitos, funis e outros blocos com o _botão direito do mouse_ enquanto _segurando_ o _Braço_ _Mecanico_ na sua _mão_.",
"create.hint.empty_bearing.title": "Atualizar o rolamento",
"create.hint.empty_bearing": " _clique com o botão direito_ o rolamento com a _mão_ _vazia_ para _conectar_ a estrutura que você construiu não frente disso.",
"create.hint.full_deployer.title": "Implantador transbordando de itens",
"create.hint.full_deployer": "Aparenta que esse _inplantador_ contém _itens_ em _excesso_ que precisam ser _extraídos._ Use um _funil,_ _funil de andesito/latão_ ou outros meios para extrair os itens excedentes.",
"create.gui.config.overlay1": "Oi :)",
"create.command.killTPSCommand": " killtps",
"create.command.killTPSCommand.status.slowed_by.0": " [Create]: Server tick is currently slowed by %s ms :o",
"create.command.killTPSCommand.status.slowed_by.1": " [Create]: Server tick is slowed by %s ms now >:)",
"create.command.killTPSCommand.status.slowed_by.2": " [Create]: Server tick is back to regular speed :D",
"create.command.killTPSCommand.status.usage.0": " [Create]: use /killtps stop to bring back server tick to regular speed",
"create.command.killTPSCommand.status.usage.1": " [Create]: use /killtps start <tickTime> to artificially slow down the server tick",
"create.command.killTPSCommand.argument.tickTime": "tickTime",
"create.contraption.minecart_contraption_too_big": "Essa engenhoca de carrinho aparenta ser muita grande para pegar",
"create.contraption.minecart_contraption_illegal_pickup": "Uma força mistica esta segurando esta engenhoca de carrinho",
"_": "->------------------------] Subtitles [------------------------<-",
"create.subtitle.contraption_disassemble": "Engenhoca para",
"create.subtitle.peculiar_bell_use": "Sino peculiar toca",
"create.subtitle.mixing": "Sons de mistura",
"create.subtitle.mechanical_press_activation_belt": "Bonks da prensa mecanica",
"create.subtitle.fwoomp": "Fwoomps do canhão de batata",
"create.subtitle.worldshaper_place": "Zaps do terraformador",
"create.subtitle.sanding_long": "Sons de lixa",
"create.subtitle.crushing_1": "Sons de trituração",
"create.subtitle.depot_slide": "Item escorrega",
"create.subtitle.saw_activate_stone": "Serra mecânica ativa",
"create.subtitle.blaze_munch": "Queimador de blazer mastiga",
"create.subtitle.funnel_flap": "Abas do funil batendo",
"create.subtitle.schematicannon_finish": "Ding do canhão de esquema",
"create.subtitle.haunted_bell_use": "Sino assombrado toca",
"create.subtitle.scroll_value": "click do scroll",
"create.subtitle.crafter_craft": "Fabricador fábrica",
"create.subtitle.controller_put": "Thumps do controle",
"create.subtitle.cranking": "Manivela gira",
"create.subtitle.wrench_remove": "Componente quebra",
"create.subtitle.sanding_short": "Sons de lixa",
"create.subtitle.cogs": "tremer da rodas dentadas",
"create.subtitle.slime_added": "Slime sendo espremido",
"create.subtitle.wrench_rotate": "Chave inglesa usada",
"create.subtitle.potato_hit": "Impacto vegetal",
"create.subtitle.saw_activate_wood": "Serra mecânica ativa",
"create.subtitle.haunted_bell_convert": "Sino assombrado acorda",
"create.subtitle.deny": "Boop de negação",
"create.subtitle.controller_click": "Clicks do controle",
"create.subtitle.schematicannon_launch_block": "Canhão de esquema atira",
"create.subtitle.copper_armor_equip": "Tilintar dos equipamentos de mergulho",
"create.subtitle.controller_take": "Atril esvaziado",
"create.subtitle.mechanical_press_activation": "Clang da prensa mecânica",
"create.subtitle.contraption_assemble": "Engenhoca move",
"create.subtitle.crafter_click": "Clicks do fabricador",
"create.subtitle.depot_plop": "Item pousa",
"create.subtitle.confirm": "Ding afirmativo",
"_": "->------------------------] Item Descriptions [------------------------<-",

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more