Merge remote-tracking branch 'origin/mc1.15/dev' into mc1.15/dev

This commit is contained in:
grimmauld 2021-02-16 20:29:40 +01:00
commit c6f82bff5e
82 changed files with 1707 additions and 973 deletions

1
.gitignore vendored
View file

@ -40,4 +40,3 @@ local.properties
# PDT-specific # PDT-specific
.buildpath .buildpath
src/generated/resources/.cache/cache

View file

@ -404,7 +404,7 @@ e3f618c5b622d21880de858678d1802cbf65e615 assets/create/lang/en_ud.json
acc852d80378b426d7ee6cb59c169e06b6d63b25 assets/create/lang/en_us.json acc852d80378b426d7ee6cb59c169e06b6d63b25 assets/create/lang/en_us.json
30ce93c56557cea2f384a47b549fb893700523a5 assets/create/lang/unfinished/de_de.json 30ce93c56557cea2f384a47b549fb893700523a5 assets/create/lang/unfinished/de_de.json
77b8310f3cbed36fa0d2ee29e65ac6aee0c2adc2 assets/create/lang/unfinished/es_mx.json 77b8310f3cbed36fa0d2ee29e65ac6aee0c2adc2 assets/create/lang/unfinished/es_mx.json
b8e44c8c33b3c36b850f579e317103eb57f85f07 assets/create/lang/unfinished/fr_fr.json 8db9f9147dcef8c8182c548a524f96f578c116ec assets/create/lang/unfinished/fr_fr.json
89f7029d73733938ee9f900fc36d52ab7fc97563 assets/create/lang/unfinished/it_it.json 89f7029d73733938ee9f900fc36d52ab7fc97563 assets/create/lang/unfinished/it_it.json
b1935e7f8d79d1112e1685adb42daedb976ac6d7 assets/create/lang/unfinished/ja_jp.json b1935e7f8d79d1112e1685adb42daedb976ac6d7 assets/create/lang/unfinished/ja_jp.json
23aaf879d07a24775aeba3b98c355c992b24f28b assets/create/lang/unfinished/ko_kr.json 23aaf879d07a24775aeba3b98c355c992b24f28b assets/create/lang/unfinished/ko_kr.json
@ -3539,7 +3539,7 @@ d3fdb8ece6cb072a93ddb64a0baad5ac952117a4 data/create/recipes/weathered_limestone
eedf31af7134d03656c5fa57229982f9c5bed07c data/create/tags/blocks/brittle.json eedf31af7134d03656c5fa57229982f9c5bed07c data/create/tags/blocks/brittle.json
13b55d6e905a02403d2e95e9ba2357f99c5f2241 data/create/tags/blocks/fan_heaters.json 13b55d6e905a02403d2e95e9ba2357f99c5f2241 data/create/tags/blocks/fan_heaters.json
3bc64e3a1e7980237435b1770a9ba2102d57fcd4 data/create/tags/blocks/fan_transparent.json 3bc64e3a1e7980237435b1770a9ba2102d57fcd4 data/create/tags/blocks/fan_transparent.json
745a82505a68a6482407d87374e356781406ab46 data/create/tags/blocks/safe_nbt.json c81ea194e808985847159b201140d4aa4cbcca65 data/create/tags/blocks/safe_nbt.json
c9ac7e3e5ec18554e7184168d65e9b8e44ef5610 data/create/tags/blocks/sails.json c9ac7e3e5ec18554e7184168d65e9b8e44ef5610 data/create/tags/blocks/sails.json
6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json 6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json
50936b211d94167a35ec78c89954082a336b6269 data/create/tags/blocks/valve_handles.json 50936b211d94167a35ec78c89954082a336b6269 data/create/tags/blocks/valve_handles.json

View file

@ -823,6 +823,12 @@
"create.gui.goggles.kinetic_stats": "Kinetic Stats:", "create.gui.goggles.kinetic_stats": "Kinetic Stats:",
"create.gui.goggles.at_current_speed": "at current speed", "create.gui.goggles.at_current_speed": "at current speed",
"create.gui.goggles.pole_length": "Pole Length:", "create.gui.goggles.pole_length": "Pole Length:",
"create.gui.assembly.exception": "This Contraption was unable to assemble:",
"create.gui.assembly.exception.unmovableBlock": "Unmovable Block (%4$s) at [%1$s %2$s %3$s]",
"create.gui.assembly.exception.chunkNotLoaded": "The Block at [%1$s %2$s %3$s] was not in a loaded chunk",
"create.gui.assembly.exception.structureTooLarge": "There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.tooManyPistonPoles": "There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.noPistonPoles": "The Piston is missing some extension Poles",
"create.gui.gauge.info_header": "Gauge Information:", "create.gui.gauge.info_header": "Gauge Information:",
"create.gui.speedometer.title": "Rotation Speed", "create.gui.speedometer.title": "Rotation Speed",
"create.gui.stressometer.title": "Network Stress", "create.gui.stressometer.title": "Network Stress",

View file

@ -823,6 +823,12 @@
"create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:", "create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:",
"create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed", "create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed",
"create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:",
"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.gauge.info_header": "UNLOCALIZED: Gauge Information:", "create.gui.gauge.info_header": "UNLOCALIZED: Gauge Information:",
"create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed", "create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed",
"create.gui.stressometer.title": "UNLOCALIZED: Network Stress", "create.gui.stressometer.title": "UNLOCALIZED: Network Stress",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 730", "_": "Missing Localizations: 666",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -10,83 +10,83 @@
"block.create.adjustable_pulse_repeater": "Répéteur d'impulsions réglable", "block.create.adjustable_pulse_repeater": "Répéteur d'impulsions réglable",
"block.create.adjustable_repeater": "Répéteur réglable", "block.create.adjustable_repeater": "Répéteur réglable",
"block.create.analog_lever": "Levier analogique", "block.create.analog_lever": "Levier analogique",
"block.create.andesite_belt_funnel": "UNLOCALIZED: Andesite Belt Funnel", "block.create.andesite_belt_funnel": "Entonnoir en andésite pour tapis roulant",
"block.create.andesite_bricks": "Briques d'andésite", "block.create.andesite_bricks": "Briques d'andésite",
"block.create.andesite_bricks_slab": "Dalle en briques d'andésite", "block.create.andesite_bricks_slab": "Dalle en briques d'andésite",
"block.create.andesite_bricks_stairs": "Escalier en briques d'andésite", "block.create.andesite_bricks_stairs": "Escalier en briques d'andésite",
"block.create.andesite_bricks_wall": "Mur en briques d'andésite", "block.create.andesite_bricks_wall": "Mur en briques d'andésite",
"block.create.andesite_casing": "Boîtier en andésite", "block.create.andesite_casing": "Revêtement en andésite",
"block.create.andesite_cobblestone": "Pierres d'andésite", "block.create.andesite_cobblestone": "Pierres d'andésite",
"block.create.andesite_cobblestone_slab": "Dalles en pierres d'andésite", "block.create.andesite_cobblestone_slab": "Dalles en pierres d'andésite",
"block.create.andesite_cobblestone_stairs": "Escaliers en pierres d'andésite", "block.create.andesite_cobblestone_stairs": "Escaliers en pierres d'andésite",
"block.create.andesite_cobblestone_wall": "Mur en pierres d'andésite", "block.create.andesite_cobblestone_wall": "Mur en pierres d'andésite",
"block.create.andesite_encased_shaft": "Arbre mécanique dans un revêtement en andésite", "block.create.andesite_encased_shaft": "Rotor dans un revêtement en andésite",
"block.create.andesite_funnel": "Entonnoir en andésite", "block.create.andesite_funnel": "Entonnoir en andésite",
"block.create.andesite_pillar": "Pilier en andésite", "block.create.andesite_pillar": "Pilier en andésite",
"block.create.andesite_tunnel": "Tunnel en andésite", "block.create.andesite_tunnel": "Tunnel en andésite",
"block.create.basin": "Bassin", "block.create.basin": "Bassin",
"block.create.belt": "Tapis roulant", "block.create.belt": "Tapis roulant",
"block.create.birch_window": "Fenêtre en bouleau", "block.create.birch_window": "Fenêtre en bouleau",
"block.create.birch_window_pane": "UNLOCALIZED: Birch Window Pane", "block.create.birch_window_pane": "Vitre en bouleau",
"block.create.black_sail": "UNLOCALIZED: Black Sail", "block.create.black_sail": "Voile noire",
"block.create.black_seat": "UNLOCALIZED: Black Seat", "block.create.black_seat": "Siège noir",
"block.create.black_valve_handle": "UNLOCALIZED: Black Valve Handle", "block.create.black_valve_handle": "Vanne noire",
"block.create.blaze_burner": "UNLOCALIZED: Blaze Burner", "block.create.blaze_burner": "Brûleur à blaze",
"block.create.blue_sail": "UNLOCALIZED: Blue Sail", "block.create.blue_sail": "Voile bleue",
"block.create.blue_seat": "UNLOCALIZED: Blue Seat", "block.create.blue_seat": "Siège bleu",
"block.create.blue_valve_handle": "UNLOCALIZED: Blue Valve Handle", "block.create.blue_valve_handle": "Vanne bleue",
"block.create.brass_belt_funnel": "UNLOCALIZED: Brass Belt Funnel", "block.create.brass_belt_funnel": "Entonnoir en laiton pour tapis roulant",
"block.create.brass_block": "UNLOCALIZED: Brass Block", "block.create.brass_block": "Bloc de laiton",
"block.create.brass_casing": "Boîtier en laiton", "block.create.brass_casing": "Revêtement en laiton",
"block.create.brass_encased_shaft": "UNLOCALIZED: Brass Encased Shaft", "block.create.brass_encased_shaft": "Rotor dans un revêtement en laiton",
"block.create.brass_funnel": "UNLOCALIZED: Brass Funnel", "block.create.brass_funnel": "Entonnoir en laiton",
"block.create.brass_tunnel": "UNLOCALIZED: Brass Tunnel", "block.create.brass_tunnel": "Tunnel en laiton",
"block.create.brown_sail": "UNLOCALIZED: Brown Sail", "block.create.brown_sail": "Voile brune",
"block.create.brown_seat": "UNLOCALIZED: Brown Seat", "block.create.brown_seat": "Siège brun",
"block.create.brown_valve_handle": "UNLOCALIZED: Brown Valve Handle", "block.create.brown_valve_handle": "Vanne brune",
"block.create.cart_assembler": "Assembleur de wagon", "block.create.cart_assembler": "Assembleur de wagon",
"block.create.chiseled_dark_scoria": "UNLOCALIZED: Chiseled Dark Scoria", "block.create.chiseled_dark_scoria": "Scoria sombre taillé",
"block.create.chiseled_dolomite": "UNLOCALIZED: Chiseled Dolomite", "block.create.chiseled_dolomite": "Dolomite taillée",
"block.create.chiseled_gabbro": "UNLOCALIZED: Chiseled Gabbro", "block.create.chiseled_gabbro": "Gabbro taillé",
"block.create.chiseled_limestone": "UNLOCALIZED: Chiseled Limestone", "block.create.chiseled_limestone": "Calcaire taillé",
"block.create.chiseled_scoria": "UNLOCALIZED: Chiseled Scoria", "block.create.chiseled_scoria": "Scoria taillé",
"block.create.chiseled_weathered_limestone": "UNLOCALIZED: Chiseled Weathered Limestone", "block.create.chiseled_weathered_limestone": "Calcaire altéré taillé",
"block.create.chocolate": "UNLOCALIZED: Chocolate", "block.create.chocolate": "Chocolat",
"block.create.chute": "UNLOCALIZED: Chute", "block.create.chute": "Glissière",
"block.create.clockwork_bearing": "Roulement mécanique horloger", "block.create.clockwork_bearing": "Roulement mécanique horloger",
"block.create.clutch": "Embrayage", "block.create.clutch": "Embrayage",
"block.create.cogwheel": "Roue dentée", "block.create.cogwheel": "Roue dentée",
"block.create.content_observer": "UNLOCALIZED: Content Observer", "block.create.content_observer": "Observateur de contenu",
"block.create.controller_rail": "UNLOCALIZED: Controller Rail", "block.create.controller_rail": "Rails controlleurs",
"block.create.copper_block": "Bloc de cuivre", "block.create.copper_block": "Bloc de cuivre",
"block.create.copper_casing": "Boîtier en cuivre", "block.create.copper_casing": "Revêtement en cuivre",
"block.create.copper_ore": "Minerai de cuivre", "block.create.copper_ore": "Minerai de cuivre",
"block.create.copper_shingles": "Bardeaux de cuivre", "block.create.copper_shingles": "Bardeaux de cuivre",
"block.create.copper_tiles": "UNLOCALIZED: Copper Tiles", "block.create.copper_tiles": "Tuiles en cuivre",
"block.create.copper_valve_handle": "UNLOCALIZED: Copper Valve Handle", "block.create.copper_valve_handle": "Vanne en cuivre",
"block.create.creative_crate": "Créateur de schémacanon", "block.create.creative_crate": "Créateur de schémacanon",
"block.create.creative_fluid_tank": "UNLOCALIZED: Creative Fluid Tank", "block.create.creative_fluid_tank": "Réservoir créatif",
"block.create.creative_motor": "Moteur", "block.create.creative_motor": "Moteur",
"block.create.crushing_wheel": "Roue de concassage", "block.create.crushing_wheel": "Roue de concassage",
"block.create.crushing_wheel_controller": "UNLOCALIZED: Crushing Wheel Controller", "block.create.crushing_wheel_controller": "Contrôleur de roue de concassage",
"block.create.cuckoo_clock": "Horloge à coucou", "block.create.cuckoo_clock": "Horloge à coucou",
"block.create.cyan_sail": "UNLOCALIZED: Cyan Sail", "block.create.cyan_sail": "Voile cyan",
"block.create.cyan_seat": "UNLOCALIZED: Cyan Seat", "block.create.cyan_seat": "Siège cyan",
"block.create.cyan_valve_handle": "UNLOCALIZED: Cyan Valve Handle", "block.create.cyan_valve_handle": "Vanne cyan",
"block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window", "block.create.dark_oak_window": "fenêtre en chêne sombre",
"block.create.dark_oak_window_pane": "UNLOCALIZED: Dark Oak Window Pane", "block.create.dark_oak_window_pane": "Vitre en chêne sombre",
"block.create.dark_scoria": "Scorie sombre", "block.create.dark_scoria": "Scorie sombre",
"block.create.dark_scoria_bricks": "Briques de scorie sombre", "block.create.dark_scoria_bricks": "Briques de scorie sombre",
"block.create.dark_scoria_bricks_slab": "Dalles de briques de scorie sombre", "block.create.dark_scoria_bricks_slab": "Dalles de briques de scorie sombre",
"block.create.dark_scoria_bricks_stairs": "Escaliers de briques de scorie sombre", "block.create.dark_scoria_bricks_stairs": "Escaliers de briques de scorie sombre",
"block.create.dark_scoria_bricks_wall": "Muret de briques de scorie sombre", "block.create.dark_scoria_bricks_wall": "Muret de briques de scorie sombre",
"block.create.dark_scoria_cobblestone": "UNLOCALIZED: Dark Scoria Cobblestone", "block.create.dark_scoria_cobblestone": "Pierres de scorie sombre",
"block.create.dark_scoria_cobblestone_slab": "UNLOCALIZED: Dark Scoria Cobblestone Slab", "block.create.dark_scoria_cobblestone_slab": "UNLOCALIZED: Dark Scoria Cobblestone Slab",
"block.create.dark_scoria_cobblestone_stairs": "UNLOCALIZED: Dark Scoria Cobblestone Stairs", "block.create.dark_scoria_cobblestone_stairs": "UNLOCALIZED: Dark Scoria Cobblestone Stairs",
"block.create.dark_scoria_cobblestone_wall": "UNLOCALIZED: Dark Scoria Cobblestone Wall", "block.create.dark_scoria_cobblestone_wall": "UNLOCALIZED: Dark Scoria Cobblestone Wall",
"block.create.dark_scoria_pillar": "UNLOCALIZED: Dark Scoria Pillar", "block.create.dark_scoria_pillar": "UNLOCALIZED: Dark Scoria Pillar",
"block.create.deployer": "Déployeur", "block.create.deployer": "Déployeur",
"block.create.depot": "UNLOCALIZED: Depot", "block.create.depot": "pot",
"block.create.diorite_bricks": "Briques de diorite", "block.create.diorite_bricks": "Briques de diorite",
"block.create.diorite_bricks_slab": "UNLOCALIZED: Diorite Bricks Slab", "block.create.diorite_bricks_slab": "UNLOCALIZED: Diorite Bricks Slab",
"block.create.diorite_bricks_stairs": "UNLOCALIZED: Diorite Bricks Stairs", "block.create.diorite_bricks_stairs": "UNLOCALIZED: Diorite Bricks Stairs",
@ -96,18 +96,18 @@
"block.create.diorite_cobblestone_stairs": "UNLOCALIZED: Diorite Cobblestone Stairs", "block.create.diorite_cobblestone_stairs": "UNLOCALIZED: Diorite Cobblestone Stairs",
"block.create.diorite_cobblestone_wall": "UNLOCALIZED: Diorite Cobblestone Wall", "block.create.diorite_cobblestone_wall": "UNLOCALIZED: Diorite Cobblestone Wall",
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar", "block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
"block.create.dolomite": "Dolomie", "block.create.dolomite": "Dolomite",
"block.create.dolomite_bricks": "Briques de dolomie", "block.create.dolomite_bricks": "Briques de dolomite",
"block.create.dolomite_bricks_slab": "Dalle de briques de dolomie", "block.create.dolomite_bricks_slab": "Dalle de briques de dolomite",
"block.create.dolomite_bricks_stairs": "Escaliers de briques de dolomie", "block.create.dolomite_bricks_stairs": "Escaliers de briques de dolomite",
"block.create.dolomite_bricks_wall": "Muret de briques de dolomie", "block.create.dolomite_bricks_wall": "Muret de briques de dolomite",
"block.create.dolomite_cobblestone": "UNLOCALIZED: Dolomite Cobblestone", "block.create.dolomite_cobblestone": "UNLOCALIZED: Dolomite Cobblestone",
"block.create.dolomite_cobblestone_slab": "UNLOCALIZED: Dolomite Cobblestone Slab", "block.create.dolomite_cobblestone_slab": "UNLOCALIZED: Dolomite Cobblestone Slab",
"block.create.dolomite_cobblestone_stairs": "UNLOCALIZED: Dolomite Cobblestone Stairs", "block.create.dolomite_cobblestone_stairs": "UNLOCALIZED: Dolomite Cobblestone Stairs",
"block.create.dolomite_cobblestone_wall": "UNLOCALIZED: Dolomite Cobblestone Wall", "block.create.dolomite_cobblestone_wall": "UNLOCALIZED: Dolomite Cobblestone Wall",
"block.create.dolomite_pillar": "Pillier de dolomie", "block.create.dolomite_pillar": "Pillier de dolomite",
"block.create.encased_chain_drive": "UNLOCALIZED: Encased Chain Drive", "block.create.encased_chain_drive": "Chaine de transmission",
"block.create.encased_fan": "Ventilateur enfermé", "block.create.encased_fan": "Ventilateur enchâssé",
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe", "block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks", "block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
"block.create.fancy_andesite_bricks_slab": "UNLOCALIZED: Fancy Andesite Bricks Slab", "block.create.fancy_andesite_bricks_slab": "UNLOCALIZED: Fancy Andesite Bricks Slab",
@ -308,12 +308,12 @@
"block.create.pink_sail": "UNLOCALIZED: Pink Sail", "block.create.pink_sail": "UNLOCALIZED: Pink Sail",
"block.create.pink_seat": "UNLOCALIZED: Pink Seat", "block.create.pink_seat": "UNLOCALIZED: Pink Seat",
"block.create.pink_valve_handle": "UNLOCALIZED: Pink Valve Handle", "block.create.pink_valve_handle": "UNLOCALIZED: Pink Valve Handle",
"block.create.piston_extension_pole": "Pôle d'extension de piston", "block.create.piston_extension_pole": "Barre d'extension de piston",
"block.create.polished_dark_scoria": "Scorie sombre polie", "block.create.polished_dark_scoria": "Scorie sombre polie",
"block.create.polished_dark_scoria_slab": "UNLOCALIZED: Polished Dark Scoria Slab", "block.create.polished_dark_scoria_slab": "UNLOCALIZED: Polished Dark Scoria Slab",
"block.create.polished_dark_scoria_stairs": "UNLOCALIZED: Polished Dark Scoria Stairs", "block.create.polished_dark_scoria_stairs": "UNLOCALIZED: Polished Dark Scoria Stairs",
"block.create.polished_dark_scoria_wall": "UNLOCALIZED: Polished Dark Scoria Wall", "block.create.polished_dark_scoria_wall": "UNLOCALIZED: Polished Dark Scoria Wall",
"block.create.polished_dolomite": "Dolomie polie", "block.create.polished_dolomite": "Dolomite polie",
"block.create.polished_dolomite_slab": "UNLOCALIZED: Polished Dolomite Slab", "block.create.polished_dolomite_slab": "UNLOCALIZED: Polished Dolomite Slab",
"block.create.polished_dolomite_stairs": "UNLOCALIZED: Polished Dolomite Stairs", "block.create.polished_dolomite_stairs": "UNLOCALIZED: Polished Dolomite Stairs",
"block.create.polished_dolomite_wall": "UNLOCALIZED: Polished Dolomite Wall", "block.create.polished_dolomite_wall": "UNLOCALIZED: Polished Dolomite Wall",
@ -329,8 +329,8 @@
"block.create.polished_scoria_slab": "Dalle de scorie polie", "block.create.polished_scoria_slab": "Dalle de scorie polie",
"block.create.polished_scoria_stairs": "UNLOCALIZED: Polished Scoria Stairs", "block.create.polished_scoria_stairs": "UNLOCALIZED: Polished Scoria Stairs",
"block.create.polished_scoria_wall": "UNLOCALIZED: Polished Scoria Wall", "block.create.polished_scoria_wall": "UNLOCALIZED: Polished Scoria Wall",
"block.create.polished_weathered_limestone": "Calcaire patinées polies", "block.create.polished_weathered_limestone": "Calcaire altéré polies",
"block.create.polished_weathered_limestone_slab": "Dalle de calcaire patinées", "block.create.polished_weathered_limestone_slab": "Dalle de calcaire altéré",
"block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface", "block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
@ -346,7 +346,7 @@
"block.create.red_sail": "UNLOCALIZED: Red Sail", "block.create.red_sail": "UNLOCALIZED: Red Sail",
"block.create.red_seat": "UNLOCALIZED: Red Seat", "block.create.red_seat": "UNLOCALIZED: Red Seat",
"block.create.red_valve_handle": "UNLOCALIZED: Red Valve Handle", "block.create.red_valve_handle": "UNLOCALIZED: Red Valve Handle",
"block.create.redstone_contact": "redstone_contact Redstone", "block.create.redstone_contact": "Contact de redstone",
"block.create.redstone_link": "Liaison Redstone", "block.create.redstone_link": "Liaison Redstone",
"block.create.refined_radiance_casing": "UNLOCALIZED: Radiant Casing", "block.create.refined_radiance_casing": "UNLOCALIZED: Radiant Casing",
"block.create.reinforced_rail": "UNLOCALIZED: Reinforced Rail", "block.create.reinforced_rail": "UNLOCALIZED: Reinforced Rail",
@ -369,7 +369,7 @@
"block.create.secondary_linear_chassis": "UNLOCALIZED: Secondary Linear Chassis", "block.create.secondary_linear_chassis": "UNLOCALIZED: Secondary Linear Chassis",
"block.create.sequenced_gearshift": "Décaleur de rotation séquencé", "block.create.sequenced_gearshift": "Décaleur de rotation séquencé",
"block.create.shadow_steel_casing": "UNLOCALIZED: Shadow Casing", "block.create.shadow_steel_casing": "UNLOCALIZED: Shadow Casing",
"block.create.shaft": "Arbre mécanique", "block.create.shaft": "Rotor",
"block.create.smart_chute": "UNLOCALIZED: Smart Chute", "block.create.smart_chute": "UNLOCALIZED: Smart Chute",
"block.create.smart_fluid_pipe": "UNLOCALIZED: Smart Fluid Pipe", "block.create.smart_fluid_pipe": "UNLOCALIZED: Smart Fluid Pipe",
"block.create.speedometer": "Compteur de vitesse", "block.create.speedometer": "Compteur de vitesse",
@ -385,16 +385,16 @@
"block.create.vertical_framed_glass": "Fenêtre en verre verticale", "block.create.vertical_framed_glass": "Fenêtre en verre verticale",
"block.create.vertical_framed_glass_pane": "Vitre encadrée verticale", "block.create.vertical_framed_glass_pane": "Vitre encadrée verticale",
"block.create.water_wheel": "Roue à eau", "block.create.water_wheel": "Roue à eau",
"block.create.weathered_limestone": "Calcaire patinées", "block.create.weathered_limestone": "Calcaire altéré",
"block.create.weathered_limestone_bricks": "Briques de calcaire patinées", "block.create.weathered_limestone_bricks": "Briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_slab": "Dalle de briques de calcaire patinées", "block.create.weathered_limestone_bricks_slab": "Dalle de briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_stairs": "Escaliers de briques de calcaire patinées", "block.create.weathered_limestone_bricks_stairs": "Escaliers de briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_wall": "Muret de briques de calcaire patinées", "block.create.weathered_limestone_bricks_wall": "Muret de briques de Calcaire altéré",
"block.create.weathered_limestone_cobblestone": "UNLOCALIZED: Weathered Limestone Cobblestone", "block.create.weathered_limestone_cobblestone": "UNLOCALIZED: Weathered Limestone Cobblestone",
"block.create.weathered_limestone_cobblestone_slab": "UNLOCALIZED: Weathered Limestone Cobblestone Slab", "block.create.weathered_limestone_cobblestone_slab": "UNLOCALIZED: Weathered Limestone Cobblestone Slab",
"block.create.weathered_limestone_cobblestone_stairs": "UNLOCALIZED: Weathered Limestone Cobblestone Stairs", "block.create.weathered_limestone_cobblestone_stairs": "UNLOCALIZED: Weathered Limestone Cobblestone Stairs",
"block.create.weathered_limestone_cobblestone_wall": "UNLOCALIZED: Weathered Limestone Cobblestone Wall", "block.create.weathered_limestone_cobblestone_wall": "UNLOCALIZED: Weathered Limestone Cobblestone Wall",
"block.create.weathered_limestone_pillar": "Pillier de calcaire patinées", "block.create.weathered_limestone_pillar": "Pillier de Calcaire altéré",
"block.create.white_sail": "UNLOCALIZED: White Sail", "block.create.white_sail": "UNLOCALIZED: White Sail",
"block.create.white_seat": "UNLOCALIZED: White Seat", "block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle", "block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
@ -478,7 +478,7 @@
"item.create.schematic_and_quill": "Schéma et plume", "item.create.schematic_and_quill": "Schéma et plume",
"item.create.shadow_steel": "Acier sombre", "item.create.shadow_steel": "Acier sombre",
"item.create.super_glue": "Colle extra-forte", "item.create.super_glue": "Colle extra-forte",
"item.create.tree_fertilizer": "Engrais pour arbre", "item.create.tree_fertilizer": "Engrais pour arbres",
"item.create.vertical_gearbox": "Boîte de transfert verticale", "item.create.vertical_gearbox": "Boîte de transfert verticale",
"item.create.wand_of_symmetry": "Bâton de symétrie", "item.create.wand_of_symmetry": "Bâton de symétrie",
"item.create.wheat_flour": "Farine", "item.create.wheat_flour": "Farine",
@ -496,7 +496,7 @@
"advancement.create.andesite_alloy.desc": "Certains matériaux de Create ont des noms bizzares; l'alliage d'andésite est l'un d'entre eux.", "advancement.create.andesite_alloy.desc": "Certains matériaux de Create ont des noms bizzares; l'alliage d'andésite est l'un d'entre eux.",
"advancement.create.its_alive": "Ça bouge!", "advancement.create.its_alive": "Ça bouge!",
"advancement.create.its_alive.desc": "Regardez vos bremiers composants tourner.", "advancement.create.its_alive.desc": "Regardez vos bremiers composants tourner.",
"advancement.create.shifting_gears": "Arbre de transmission", "advancement.create.shifting_gears": "rotor de transmission",
"advancement.create.shifting_gears.desc": "Connectez une roue dentée à une grande roue dentée afin de changer la vitesse de votre engin", "advancement.create.shifting_gears.desc": "Connectez une roue dentée à une grande roue dentée afin de changer la vitesse de votre engin",
"advancement.create.overstressed": "Surtension", "advancement.create.overstressed": "Surtension",
"advancement.create.overstressed.desc": "Testez d'abord les limites de la force mécanique", "advancement.create.overstressed.desc": "Testez d'abord les limites de la force mécanique",
@ -657,7 +657,7 @@
"itemGroup.create.base": "Create", "itemGroup.create.base": "Create",
"itemGroup.create.palettes": "Create Palettes", "itemGroup.create.palettes": "Create Palettes",
"death.attack.create.crush": "%1$s nanana a été traitée par une roue de concassage", "death.attack.create.crush": "%1$s a été concassé.e",
"death.attack.create.fan_fire": "%1$s a été brûlé à mort par l'air chaud", "death.attack.create.fan_fire": "%1$s a été brûlé à mort par l'air chaud",
"death.attack.create.fan_lava": "%1$s a été brûlé à mort par un ventilateur de lave", "death.attack.create.fan_lava": "%1$s a été brûlé à mort par un ventilateur de lave",
"death.attack.create.mechanical_drill": "%1$s a été empalé par une perceuse mécanique", "death.attack.create.mechanical_drill": "%1$s a été empalé par une perceuse mécanique",
@ -796,10 +796,10 @@
"create.contraptions.movement_mode": "Mode de mouvement", "create.contraptions.movement_mode": "Mode de mouvement",
"create.contraptions.movement_mode.move_place": "Toujours placer à l'arrêt", "create.contraptions.movement_mode.move_place": "Toujours placer à l'arrêt",
"create.contraptions.movement_mode.move_place_returned": "Placer uniquement en position de départ", "create.contraptions.movement_mode.move_place_returned": "Placer uniquement en position de départ",
"create.contraptions.movement_mode.move_never_place": "Ne placer que lorsque l'ancre est détruite", "create.contraptions.movement_mode.move_never_place": "Ne placer que Quand l'ancre est détruite",
"create.contraptions.movement_mode.rotate_place": "Toujours placer à l'arrêt", "create.contraptions.movement_mode.rotate_place": "Toujours placer à l'arrêt",
"create.contraptions.movement_mode.rotate_place_returned": "Placer uniquement près de l'angle initial", "create.contraptions.movement_mode.rotate_place_returned": "Placer uniquement près de l'angle initial",
"create.contraptions.movement_mode.rotate_never_place": "Ne placer que lorsque l'ancre est détruite", "create.contraptions.movement_mode.rotate_never_place": "Ne placer que Quand l'ancre est détruite",
"create.contraptions.cart_movement_mode": "UNLOCALIZED: Cart Movement Mode", "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": "UNLOCALIZED: Always face toward motion",
"create.contraptions.cart_movement_mode.rotate_paused": "UNLOCALIZED: Pause actors while rotating", "create.contraptions.cart_movement_mode.rotate_paused": "UNLOCALIZED: Pause actors while rotating",
@ -1118,7 +1118,7 @@
"create.command.killTPSCommand.status.usage.1": "[Create]: use /killtps start <tickTime> to artificially slow down the server tick", "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.command.killTPSCommand.argument.tickTime": "tickTime",
"create.subtitle.schematicannon_launch_block": "Tire de schémacanon", "create.subtitle.schematicannon_launch_block": "Tir de schémacanon",
"create.subtitle.schematicannon_finish": "Fin de schémacanon", "create.subtitle.schematicannon_finish": "Fin de schémacanon",
"create.subtitle.slime_added": "Bruit de slime", "create.subtitle.slime_added": "Bruit de slime",
"create.subtitle.mechanical_press_activation": "Activation de la presse mechanique", "create.subtitle.mechanical_press_activation": "Activation de la presse mechanique",
@ -1138,7 +1138,7 @@
"item.create.example_item.tooltip.behaviour1": "Donc cet objet fait ceci. (les comportements sont affichés avec shift)", "item.create.example_item.tooltip.behaviour1": "Donc cet objet fait ceci. (les comportements sont affichés avec shift)",
"item.create.example_item.tooltip.condition2": "Et quand cela", "item.create.example_item.tooltip.condition2": "Et quand cela",
"item.create.example_item.tooltip.behaviour2": "Vous pouvez ajouter autant de comportements que vous le souhaitez", "item.create.example_item.tooltip.behaviour2": "Vous pouvez ajouter autant de comportements que vous le souhaitez",
"item.create.example_item.tooltip.control1": "Lorsque Ctrl enfoncé", "item.create.example_item.tooltip.control1": "Quand Ctrl enfoncé",
"item.create.example_item.tooltip.action1": "Ces commandes sont affichées.", "item.create.example_item.tooltip.action1": "Ces commandes sont affichées.",
"block.create.andesite_encased_shaft.tooltip": "UNLOCALIZED: ANDESITE ENCASED SHAFT", "block.create.andesite_encased_shaft.tooltip": "UNLOCALIZED: ANDESITE ENCASED SHAFT",
@ -1298,7 +1298,7 @@
"item.create.wand_of_symmetry.tooltip": "BÂTON DE SYMÉTRIE", "item.create.wand_of_symmetry.tooltip": "BÂTON DE SYMÉTRIE",
"item.create.wand_of_symmetry.tooltip.summary": "Reflète parfaitement le placement des blocs sur les plans configurés.", "item.create.wand_of_symmetry.tooltip.summary": "Reflète parfaitement le placement des blocs sur les plans configurés.",
"item.create.wand_of_symmetry.tooltip.condition1": "Lorsque positionné dans la barre active", "item.create.wand_of_symmetry.tooltip.condition1": "Quand positionné dans la barre active",
"item.create.wand_of_symmetry.tooltip.behaviour1": "Reste actif", "item.create.wand_of_symmetry.tooltip.behaviour1": "Reste actif",
"item.create.wand_of_symmetry.tooltip.control1": "Clic droit au sol", "item.create.wand_of_symmetry.tooltip.control1": "Clic droit au sol",
"item.create.wand_of_symmetry.tooltip.action1": "_Créé_ ou _déplace_ le mirroir", "item.create.wand_of_symmetry.tooltip.action1": "_Créé_ ou _déplace_ le mirroir",
@ -1325,13 +1325,13 @@
"item.create.handheld_worldshaper.tooltip.control3": "Clic droit en étant accroupi", "item.create.handheld_worldshaper.tooltip.control3": "Clic droit en étant accroupi",
"item.create.handheld_worldshaper.tooltip.action3": "Ouvre l'_interface_ _de_ _configuration_", "item.create.handheld_worldshaper.tooltip.action3": "Ouvre l'_interface_ _de_ _configuration_",
"item.create.tree_fertilizer.tooltip": "ENGRAIS POUR ARBRE", "item.create.tree_fertilizer.tooltip": "ENGRAIS POUR ARBRES",
"item.create.tree_fertilizer.tooltip.summary": "Une puissante combinaison de minéraux adaptée pour accélérer la croissance des types d'arbres communs.", "item.create.tree_fertilizer.tooltip.summary": "Une puissante combinaison de minéraux adaptée pour accélérer la croissance des types d'rotors communs.",
"item.create.tree_fertilizer.tooltip.condition1": "Lorsqu'utilisé sur une pousse d'arbre", "item.create.tree_fertilizer.tooltip.condition1": "Lorsqu'utilisé sur une pousse d'rotor",
"item.create.tree_fertilizer.tooltip.behaviour1": "Fait pousser des arbres _indépendamment_ de leurs _conditions_ _d'emplacement_", "item.create.tree_fertilizer.tooltip.behaviour1": "Fait pousser des rotors _indépendamment_ de leurs _conditions_ _d'emplacement_",
"item.create.deforester.tooltip": "DÉFORESTEUR", "item.create.deforester.tooltip": "DÉFORESTEUR",
"item.create.deforester.tooltip.summary": "Une _hache_ _rayonnante_ capable d'abattre des arbres en une fraction de seconde.", "item.create.deforester.tooltip.summary": "Une _hache_ _rayonnante_ capable d'abattre des rotors en une fraction de seconde.",
"item.create.extendo_grip.tooltip": "UNLOCALIZED: EXTENDO GRIP", "item.create.extendo_grip.tooltip": "UNLOCALIZED: EXTENDO GRIP",
"item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder.", "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder.",
@ -1340,14 +1340,14 @@
"item.create.filter.tooltip": "FILTRE", "item.create.filter.tooltip": "FILTRE",
"item.create.filter.tooltip.summary": "_Contrôle_ les _sorties_ et _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.", "item.create.filter.tooltip.summary": "_Contrôle_ les _sorties_ et _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.",
"item.create.filter.tooltip.condition1": "Lorsque dans l'emplacement de filtre", "item.create.filter.tooltip.condition1": "Quand dans l'emplacement de filtre",
"item.create.filter.tooltip.behaviour1": "_Contrôle_ le flux d'object selon sa _configuration_.", "item.create.filter.tooltip.behaviour1": "_Contrôle_ le flux d'object selon sa _configuration_.",
"item.create.filter.tooltip.condition2": "Clic droit", "item.create.filter.tooltip.condition2": "Clic droit",
"item.create.filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.", "item.create.filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.",
"item.create.attribute_filter.tooltip": "FILTRE D'ATTRIBUTS", "item.create.attribute_filter.tooltip": "FILTRE D'ATTRIBUTS",
"item.create.attribute_filter.tooltip.summary": "_Contrôle_ les _sorties_ et les _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.", "item.create.attribute_filter.tooltip.summary": "_Contrôle_ les _sorties_ et les _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.",
"item.create.attribute_filter.tooltip.condition1": "Lorsque dans l'emplacement de filtre", "item.create.attribute_filter.tooltip.condition1": "Quand dans l'emplacement de filtre",
"item.create.attribute_filter.tooltip.behaviour1": "_Contrôle_ le flux d'object selon sa _configuration_.", "item.create.attribute_filter.tooltip.behaviour1": "_Contrôle_ le flux d'object selon sa _configuration_.",
"item.create.attribute_filter.tooltip.condition2": "Clic droit", "item.create.attribute_filter.tooltip.condition2": "Clic droit",
"item.create.attribute_filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.", "item.create.attribute_filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.",
@ -1357,7 +1357,7 @@
"item.create.schematic.tooltip": "SCHÉMA", "item.create.schematic.tooltip": "SCHÉMA",
"item.create.schematic.tooltip.summary": "Contient une structure à positionner et à placer dans le monde. Positionnez l'hologramme comme vous le souhaitez et utilisez un _schémacanon_ pour le construire.", "item.create.schematic.tooltip.summary": "Contient une structure à positionner et à placer dans le monde. Positionnez l'hologramme comme vous le souhaitez et utilisez un _schémacanon_ pour le construire.",
"item.create.schematic.tooltip.condition1": "Lorsque tenu en main", "item.create.schematic.tooltip.condition1": "Quand tenu en main",
"item.create.schematic.tooltip.behaviour1": "Peut être positionné à l'aide des outils à l'écran.", "item.create.schematic.tooltip.behaviour1": "Peut être positionné à l'aide des outils à l'écran.",
"item.create.schematic.tooltip.control1": "Clic droit en étant accroupi", "item.create.schematic.tooltip.control1": "Clic droit en étant accroupi",
"item.create.schematic.tooltip.action1": "Ouvre une _interface_ pour rentrer les _coordonées_ correctes.", "item.create.schematic.tooltip.action1": "Ouvre une _interface_ pour rentrer les _coordonées_ correctes.",
@ -1382,31 +1382,31 @@
"block.create.schematic_table.tooltip": "TABLE À SCHÉMA", "block.create.schematic_table.tooltip": "TABLE À SCHÉMA",
"block.create.schematic_table.tooltip.summary": "Écrit les schémas enregistrés dans un _schéma_ _vide_.", "block.create.schematic_table.tooltip.summary": "Écrit les schémas enregistrés dans un _schéma_ _vide_.",
"block.create.schematic_table.tooltip.condition1": "Lorsque donné un schéma vide", "block.create.schematic_table.tooltip.condition1": "Quand donné un schéma vide",
"block.create.schematic_table.tooltip.behaviour1": "Télécharge un fichier choisi à partir de votre dossier de schémas.", "block.create.schematic_table.tooltip.behaviour1": "Télécharge un fichier choisi à partir de votre dossier de schémas.",
"block.create.shaft.tooltip": "ARBRE MÉCANIQUE", "block.create.shaft.tooltip": "ROTOR",
"block.create.shaft.tooltip.summary": "_Relais_ la _rotation_ en ligne droite.", "block.create.shaft.tooltip.summary": "_Relaie_ la _rotation_ en ligne droite.",
"block.create.cogwheel.tooltip": "ROUE DENTÉE", "block.create.cogwheel.tooltip": "ROUE DENTÉE",
"block.create.cogwheel.tooltip.summary": "_Relais_ la _rotation_ en ligne droite, et aux _roues_ _dentées_ adjacentes.", "block.create.cogwheel.tooltip.summary": "_Relaie_ la _rotation_ en ligne droite, et aux _roues_ _dentées_ adjacentes.",
"block.create.large_cogwheel.tooltip": "GRANDE ROUE DENTÉE", "block.create.large_cogwheel.tooltip": "GRANDE ROUE DENTÉE",
"block.create.large_cogwheel.tooltip.summary": "Une version plus grande de la _roue_ _dentée_, permettant des _changements_ dans la _vitesse_ _de_ _rotation_ lorsqu'il est connecté à son homologue plus petit.", "block.create.large_cogwheel.tooltip.summary": "Une version plus grande de la _roue_ _dentée_, permettant des _changements_ dans la _vitesse_ _de_ _rotation_ lorsqu'il est connecté à son homologue plus petit.",
"block.create.encased_shaft.tooltip": "ARBRE MÉCANIQUE ENBOÎTÉ", "block.create.encased_shaft.tooltip": "ROTOR ENCASTRÉ",
"block.create.encased_shaft.tooltip.summary": "_Relais_ la _rotation_ en ligne droite. Convient pour propager la rotation à travers les murs.", "block.create.encased_shaft.tooltip.summary": "_Relaie_ la _rotation_ en ligne droite. Convient pour propager la rotation à travers les murs.",
"block.create.gearbox.tooltip": "BOÎTE DE VITESSES", "block.create.gearbox.tooltip": "BOÎTE DE VITESSES",
"block.create.gearbox.tooltip.summary": "_Relais_ la _rotation_ dans _quatre_ _directions_. Inverse les connexions directes.", "block.create.gearbox.tooltip.summary": "_Relaie_ la _rotation_ dans _quatre_ _directions_. Inverse les connexions directes.",
"block.create.gearshift.tooltip": "DÉCALEUR DE ROTATION", "block.create.gearshift.tooltip": "BOÎTE DE VITESSES",
"block.create.gearshift.tooltip.summary": "Une commande pour basculer le sens de rotation des arbres connectés.", "block.create.gearshift.tooltip.summary": "Une commande pour basculer le sens de rotation des rotors connectés.",
"block.create.gearshift.tooltip.condition1": "Lorsqu'alimenté", "block.create.gearshift.tooltip.condition1": "Lorsqu'alimenté",
"block.create.gearshift.tooltip.behaviour1": "_Inverse_ la rotation sortante.", "block.create.gearshift.tooltip.behaviour1": "_Inverse_ la rotation sortante.",
"block.create.clutch.tooltip": "EMBRAYAGE", "block.create.clutch.tooltip": "EMBRAYAGE",
"block.create.clutch.tooltip.summary": "Une commande pour engager / désengager la rotation des arbres connectés.", "block.create.clutch.tooltip.summary": "Une commande pour engager / désengager la rotation des rotors connectés.",
"block.create.clutch.tooltip.condition1": "Lorsqu'alimenté", "block.create.clutch.tooltip.condition1": "Lorsqu'alimenté",
"block.create.clutch.tooltip.behaviour1": "_Arrête_ de transmettre la rotation de l'autre côté.", "block.create.clutch.tooltip.behaviour1": "_Arrête_ de transmettre la rotation de l'autre côté.",
@ -1421,23 +1421,23 @@
"block.create.adjustable_chain_gearshift.tooltip.behaviour1": "UNLOCALIZED: _Without_ a signal, adjacent chain drives will relay the _same speed._ With a _full strength_ signal, adjacent chain drives will relay exactly _twice its speed._ Anything inbetween will give results between 1-2x its speed.", "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "UNLOCALIZED: _Without_ a signal, adjacent chain drives will relay the _same speed._ With a _full strength_ signal, adjacent chain drives will relay exactly _twice its speed._ Anything inbetween will give results between 1-2x its speed.",
"item.create.belt_connector.tooltip": "CONNECTEUR DE TAPIS ROULANTS", "item.create.belt_connector.tooltip": "CONNECTEUR DE TAPIS ROULANTS",
"item.create.belt_connector.tooltip.summary": "Connecte deux _arbres_ ou plus à un _tapis_ _roulant_ _mécanique_. Les arbres connectés auront exactement la même vitesse et le même sens de rotation. La ceinture peut agir comme un _convoyeur_ pour _objets_ et _entités_.", "item.create.belt_connector.tooltip.summary": "Connecte deux _rotors_ ou plus à un _tapis_ _roulant_ _mécanique_. Les rotors connectés auront exactement la même vitesse et le même sens de rotation. La ceinture peut agir comme un _convoyeur_ pour _objets_ et _entités_.",
"item.create.belt_connector.tooltip.control1": "Clic droit sur arbre", "item.create.belt_connector.tooltip.control1": "Clic droit sur rotor",
"item.create.belt_connector.tooltip.action1": "Sélectionne l'arbre comme une poulie de la courroie. Les deux arbres sélectionnés doivent être _alignés_ soit _verticalement_, _horizontalement_, ou _diagonalement_ en direction de la courroie.", "item.create.belt_connector.tooltip.action1": "Sélectionne le rotor comme une poulie de la courroie. Les deux rotors sélectionnés doivent être _alignés_ soit _verticalement_, _horizontalement_, ou _diagonalement_ en direction de la courroie.",
"item.create.belt_connector.tooltip.control2": "Clic droit en étant accroupi", "item.create.belt_connector.tooltip.control2": "Clic droit en étant accroupi",
"item.create.belt_connector.tooltip.action2": "_Réinitialise_ la première position sélectionnée pour le tapis roulant.", "item.create.belt_connector.tooltip.action2": "_Réinitialise_ la première position sélectionnée pour le tapis roulant.",
"item.create.goggles.tooltip": "LUNETTES", "item.create.goggles.tooltip": "LUNETTES",
"item.create.goggles.tooltip.summary": "Une paire de lunettes pour augmenter votre vision avec des _informations_ _kinétiques_ utiles.", "item.create.goggles.tooltip.summary": "Une paire de lunettes pour augmenter votre vision avec des _informations_ _kinétiques_ utiles.",
"item.create.goggles.tooltip.condition1": "Lorsque portées", "item.create.goggles.tooltip.condition1": "Quand portées",
"item.create.goggles.tooltip.behaviour1": "Affiche des _indicateurs_ _colorés_ correspondants au _niveau_ _de_ _vitesse_ d'un composant cinétique placé ainsi que _l'impact_ du _stress_ et la _capacité_ des composants individuels.", "item.create.goggles.tooltip.behaviour1": "Affiche des _indicateurs_ _colorés_ correspondants au _niveau_ _de_ _vitesse_ d'un composant cinétique placé ainsi que _l'impact_ du _stress_ et la _capacité_ des composants individuels.",
"item.create.goggles.tooltip.condition2": "Lorsque vision portée sur une jauge", "item.create.goggles.tooltip.condition2": "Quand vision portée sur une jauge",
"item.create.goggles.tooltip.behaviour2": "Affiche des informations détaillées sur la _vitesse_ ou le _stress_ du réseau auquel la jauge est connectée.", "item.create.goggles.tooltip.behaviour2": "Affiche des informations détaillées sur la _vitesse_ ou le _stress_ du réseau auquel la jauge est connectée.",
"item.create.wrench.tooltip": "CLÉ", "item.create.wrench.tooltip": "CLÉ",
"item.create.wrench.tooltip.summary": "Un outil utile pour travailler sur les engins cinétiques. Peut être utilisé pour _tourner_, _démonter_ et _configurer_ les composants.", "item.create.wrench.tooltip.summary": "Un outil utile pour travailler sur les engins cinétiques. Peut être utilisé pour _tourner_, _démonter_ et _configurer_ les composants.",
"item.create.wrench.tooltip.control1": "Clic droit a kinetic block", "item.create.wrench.tooltip.control1": "Clic droit sur un bloc de Create",
"item.create.wrench.tooltip.action1": "_Tourne_ les _composents_ proche ou loin de la face avec lequel vous avez interagi.", "item.create.wrench.tooltip.action1": "_Tourne_ le _composant_ le long de l'axe dépendant de la face avec lequel vous avez interagi.",
"item.create.wrench.tooltip.control2": "Clic droit en étant accroupi", "item.create.wrench.tooltip.control2": "Clic droit en étant accroupi",
"item.create.wrench.tooltip.action2": "_Démonte_ les _composants_ _cinétiques_ et les replace dans _votre_ _inventaire_.", "item.create.wrench.tooltip.action2": "_Démonte_ les _composants_ _cinétiques_ et les replace dans _votre_ _inventaire_.",
@ -1447,17 +1447,17 @@
"block.create.water_wheel.tooltip": "ROUE À EAU", "block.create.water_wheel.tooltip": "ROUE À EAU",
"block.create.water_wheel.tooltip.summary": "Fournit une _force_ _de_ _rotation_ provenant de _courants_ _d'eau_ adjacents.", "block.create.water_wheel.tooltip.summary": "Fournit une _force_ _de_ _rotation_ provenant de _courants_ _d'eau_ adjacents.",
"block.create.encased_fan.tooltip": "VENTILATEUR ENFERMÉ", "block.create.encased_fan.tooltip": "VENTILATEUR ENCHÂSSÉ",
"block.create.encased_fan.tooltip.summary": "Convertit _force_ _de_ _rotation_ en _courants_ _d'air_ et inversement. A une variété d'utilisations.", "block.create.encased_fan.tooltip.summary": "Convertit _force_ _de_ _rotation_ en _courants_ _d'air_ et inversement. A une variété d'utilisations.",
"block.create.encased_fan.tooltip.condition1": "Lorsqu'alimenté par de la redstone", "block.create.encased_fan.tooltip.condition1": "Lorsqu'alimenté par de la redstone",
"block.create.encased_fan.tooltip.behaviour1": "Fournit _force_ _de_ _rotation_ à partir de toute _source_ _de_ _chaleur_ immédiatement en dessous de lui. Le ventilateur doit être tourné vers le bas.", "block.create.encased_fan.tooltip.behaviour1": "Fournit _force_ _de_ _rotation_ à partir de toute _source_ _de_ _chaleur_ immédiatement en dessous de lui. Le ventilateur doit être tourné vers le bas.",
"block.create.encased_fan.tooltip.condition2": "Lorsque tourné", "block.create.encased_fan.tooltip.condition2": "Quand tourné",
"block.create.encased_fan.tooltip.behaviour2": "_Pousse_ ou _tire_ les entités, selon la vitesse de rotation entrante.", "block.create.encased_fan.tooltip.behaviour2": "_Pousse_ ou _tire_ les entités, selon la vitesse de rotation entrante.",
"block.create.encased_fan.tooltip.condition3": "Lorsque souffle à travers des blocs spéciaux", "block.create.encased_fan.tooltip.condition3": "Quand souffle à travers des blocs spéciaux",
"block.create.encased_fan.tooltip.behaviour3": "Des particules de _liquides_ et de _feu_ sont émises dans le flux d'air. Cela peut être utilisé pour _traiter_ des _objets_.", "block.create.encased_fan.tooltip.behaviour3": "Des particules de _liquides_ et de _feu_ sont émises dans le flux d'air. Cela peut être utilisé pour _traiter_ des _objets_.",
"block.create.nozzle.tooltip": "BUSE", "block.create.nozzle.tooltip": "BUSE",
"block.create.nozzle.tooltip.summary": "Attachez-le à l'avant d'un _ventilateur_ _enfermé_ pour répartir son effet sur les entités dans _toutes_ les _directions_.", "block.create.nozzle.tooltip.summary": "Attachez-le à l'avant d'un _ventilateur_ enchâssé_ pour répartir son effet sur les entités dans _toutes_ les _directions_.",
"block.create.hand_crank.tooltip": "MANIVELLE", "block.create.hand_crank.tooltip": "MANIVELLE",
"block.create.hand_crank.tooltip.summary": "Une simple _source_ de _force_ _de_ _rotation_ qui nécessite l'interaction des joueurs.", "block.create.hand_crank.tooltip.summary": "Une simple _source_ de _force_ _de_ _rotation_ qui nécessite l'interaction des joueurs.",
@ -1466,11 +1466,11 @@
"block.create.cuckoo_clock.tooltip": "COUCOU", "block.create.cuckoo_clock.tooltip": "COUCOU",
"block.create.cuckoo_clock.tooltip.summary": "Un bel artisanat pour _décorer_ un espace et _garder_ la _notion_ _du_ _temps_.", "block.create.cuckoo_clock.tooltip.summary": "Un bel artisanat pour _décorer_ un espace et _garder_ la _notion_ _du_ _temps_.",
"block.create.cuckoo_clock.tooltip.condition1": "Lorsque tourné", "block.create.cuckoo_clock.tooltip.condition1": "Quand tourné",
"block.create.cuckoo_clock.tooltip.behaviour1": "Affiche le _temps_ _présent_ et joue une mélodie deux fois par jour. _S'active_ une fois le _midi_ et une fois au crépuscule, dès que les _joueurs_ _peuvent_ _dormir_.", "block.create.cuckoo_clock.tooltip.behaviour1": "Affiche le _temps_ _présent_ et joue une mélodie deux fois par jour. _S'active_ une fois le _midi_ et une fois au crépuscule, dès que les _joueurs_ _peuvent_ _dormir_.",
"block.create.turntable.tooltip": "PLAQUE TOURNANTE", "block.create.turntable.tooltip": "PLAQUE TOURNANTE",
"block.create.turntable.tooltip.summary": "Transforme la _force_ _de_ _rotation_ en une nausée.", "block.create.turntable.tooltip.summary": "Transforme la _force_ _de_ _rotation_ en énergie cinétique.",
"block.create.millstone.tooltip": "UNLOCALIZED: MILLSTONE", "block.create.millstone.tooltip": "UNLOCALIZED: MILLSTONE",
"block.create.millstone.tooltip.summary": "UNLOCALIZED: A kinetic component suitable for _grinding_ inserted _materials_. Can be powered by an adjacent cogwheel or by connecting to the shaft at the bottom. Results have to be extracted from the component.", "block.create.millstone.tooltip.summary": "UNLOCALIZED: A kinetic component suitable for _grinding_ inserted _materials_. Can be powered by an adjacent cogwheel or by connecting to the shaft at the bottom. Results have to be extracted from the component.",
@ -1481,7 +1481,7 @@
"block.create.crushing_wheel.tooltip": "ROUE DE CONCASSAGE", "block.create.crushing_wheel.tooltip": "ROUE DE CONCASSAGE",
"block.create.crushing_wheel.tooltip.summary": "Grandes roues rotatives qui _cassent_ n'importe quoi.", "block.create.crushing_wheel.tooltip.summary": "Grandes roues rotatives qui _cassent_ n'importe quoi.",
"block.create.crushing_wheel.tooltip.condition1": "Lorsque fixé à une autre roue de concassage", "block.create.crushing_wheel.tooltip.condition1": "Quand fixé à une autre roue de concassage",
"block.create.crushing_wheel.tooltip.behaviour1": "Forme une machine de concassage pour traiter une variété de choses. Les dents des roues doivent se connecter et se déplacer avec la _même_ _vitesse_ dans des _directions_ _opposées_.", "block.create.crushing_wheel.tooltip.behaviour1": "Forme une machine de concassage pour traiter une variété de choses. Les dents des roues doivent se connecter et se déplacer avec la _même_ _vitesse_ dans des _directions_ _opposées_.",
"block.create.mechanical_press.tooltip": "PRESSE MÉCANIQUE", "block.create.mechanical_press.tooltip": "PRESSE MÉCANIQUE",
@ -1511,11 +1511,11 @@
"block.create.mechanical_mixer.tooltip": "MIXEUR MÉCANIQUE", "block.create.mechanical_mixer.tooltip": "MIXEUR MÉCANIQUE",
"block.create.mechanical_mixer.tooltip.summary": "Un fouet cinétique pour appliquer toutes les recettes d'artisanat informes aux objets en dessous. Nécessite une _force_ _de_ _rotation_ constant et un _bassin_ placé en dessous (avec un espace entre les deux).", "block.create.mechanical_mixer.tooltip.summary": "Un fouet cinétique pour appliquer toutes les recettes d'artisanat informes aux objets en dessous. Nécessite une _force_ _de_ _rotation_ constant et un _bassin_ placé en dessous (avec un espace entre les deux).",
"block.create.mechanical_mixer.tooltip.condition1": "Lorsqu'au-dessus d'un bassin", "block.create.mechanical_mixer.tooltip.condition1": "Lorsqu'au-dessus d'un bassin",
"block.create.mechanical_mixer.tooltip.behaviour1": "Commence à mélanger les objets dans le bassin lorsque tous les ingrédients nécessaires sont présents.", "block.create.mechanical_mixer.tooltip.behaviour1": "Commence à mélanger les objets dans le bassin Quand tous les ingrédients nécessaires sont présents.",
"block.create.mechanical_crafter.tooltip": "ÉTABLI MÉCANIQUE", "block.create.mechanical_crafter.tooltip": "ÉTABLI MÉCANIQUE",
"block.create.mechanical_crafter.tooltip.summary": "Un assembleur cinétique pour _automatiser_ n'importe quelle recette _en_ _forme_. Placez-en _plusieurs_ _dans_ _une_ _grille_ correspondant à votre recette, et _arrangez_ _leurs_ _tapis_ _roulant_ pour créer un _flux_ qui sort de la grille sur l'un des établis.", "block.create.mechanical_crafter.tooltip.summary": "Un assembleur cinétique pour _automatiser_ n'importe quelle recette _en_ _forme_. Placez-en _plusieurs_ _dans_ _une_ _grille_ correspondant à votre recette, et _arrangez_ _leurs_ _tapis_ _roulant_ pour créer un _flux_ qui sort de la grille sur l'un des établis.",
"block.create.mechanical_crafter.tooltip.condition1": "Lorsque tourné", "block.create.mechanical_crafter.tooltip.condition1": "Quand tourné",
"block.create.mechanical_crafter.tooltip.behaviour1": "_Démarre_ _le_ _processus_ _d'artisanat_ dès que _tous_ les _établis_ dans la grille ont _reçu_ _un_ _objet_.", "block.create.mechanical_crafter.tooltip.behaviour1": "_Démarre_ _le_ _processus_ _d'artisanat_ dès que _tous_ les _établis_ dans la grille ont _reçu_ _un_ _objet_.",
"block.create.mechanical_crafter.tooltip.condition2": "UNLOCALIZED: On Redstone Pulse", "block.create.mechanical_crafter.tooltip.condition2": "UNLOCALIZED: On Redstone Pulse",
"block.create.mechanical_crafter.tooltip.behaviour2": "UNLOCALIZED: _Forces_ the start of the _crafting process_ with all currently given _items_ in the grid.", "block.create.mechanical_crafter.tooltip.behaviour2": "UNLOCALIZED: _Forces_ the start of the _crafting process_ with all currently given _items_ in the grid.",
@ -1537,7 +1537,7 @@
"block.create.portable_storage_interface.tooltip": "INTERFACE DE STOCKAGE PORTABLE", "block.create.portable_storage_interface.tooltip": "INTERFACE DE STOCKAGE PORTABLE",
"block.create.portable_storage_interface.tooltip.summary": "Un point d'échange portable pour _déplacer_ des _objets_ vers et depuis une _structure_ déplacée par un piston, un roulement, un chariot ou une poulie.", "block.create.portable_storage_interface.tooltip.summary": "Un point d'échange portable pour _déplacer_ des _objets_ vers et depuis une _structure_ déplacée par un piston, un roulement, un chariot ou une poulie.",
"block.create.portable_storage_interface.tooltip.condition1": "Lorsqu'en mouvement", "block.create.portable_storage_interface.tooltip.condition1": "Lorsqu'en mouvement",
"block.create.portable_storage_interface.tooltip.behaviour1": "Interagit avec les _transposeurs_ stationnaires de sorte que les transposeurs faisant _face_ _autrepart_ de l'interface tirent les objets, et les transposeurs ciblant l'interface y _insereront_ les _objets_ de l'inventaire joint. L'engin se bloquera brièvement lorsque les objets seront échangés.", "block.create.portable_storage_interface.tooltip.behaviour1": "Interagit avec les _transposeurs_ stationnaires de sorte que les transposeurs faisant _face_ _autrepart_ de l'interface tirent les objets, et les transposeurs ciblant l'interface y _insereront_ les _objets_ de l'inventaire joint. L'engin se bloquera brièvement Quand les objets seront échangés.",
"block.create.portable_storage_interface.tooltip.condition2": "UNLOCALIZED: When Powered by Redstone", "block.create.portable_storage_interface.tooltip.condition2": "UNLOCALIZED: When Powered by Redstone",
"block.create.portable_storage_interface.tooltip.behaviour2": "UNLOCALIZED: _Disengages_ any active connection immediately.", "block.create.portable_storage_interface.tooltip.behaviour2": "UNLOCALIZED: _Disengages_ any active connection immediately.",
@ -1555,17 +1555,17 @@
"block.create.mechanical_piston.tooltip": "PISTON MÉCANIQUE", "block.create.mechanical_piston.tooltip": "PISTON MÉCANIQUE",
"block.create.mechanical_piston.tooltip.summary": "Une version plus avancée du _piston_. Il utilise une _force_ _de_ rotation_ pour déplacer précisément les structures attachées. Les _pôles_ _d'extension_ _de_ _piston_ à l'arrière définissent la _portée_ de cet appareil. Sans extensions, le piston ne bougera pas. Utilisez un _châssis_ ou un _bloc_ _de_ slime_ pour déplacer plus d'une seule ligne de blocs.", "block.create.mechanical_piston.tooltip.summary": "Une version plus avancée du _piston_. Il utilise une _force_ _de_ rotation_ pour déplacer précisément les structures attachées. Les _pôles_ _d'extension_ _de_ _piston_ à l'arrière définissent la _portée_ de cet appareil. Sans extensions, le piston ne bougera pas. Utilisez un _châssis_ ou un _bloc_ _de_ slime_ pour déplacer plus d'une seule ligne de blocs.",
"block.create.mechanical_piston.tooltip.condition1": "Lorsque tourné", "block.create.mechanical_piston.tooltip.condition1": "Quand tourné",
"block.create.mechanical_piston.tooltip.behaviour1": "Commence à déplacer la structure attachée. La vitesse et la direction sont corrélées à la vitesse de rotation entrante.", "block.create.mechanical_piston.tooltip.behaviour1": "Commence à déplacer la structure attachée. La vitesse et la direction sont corrélées à la vitesse de rotation entrante.",
"block.create.piston_extension_pole.tooltip": "PÔLE DE PISTON", "block.create.piston_extension_pole.tooltip": "BARRE DE PISTON",
"block.create.piston_extension_pole.tooltip.summary": "Étend la portée des _pistons_ _mécaniques.", "block.create.piston_extension_pole.tooltip.summary": "Étend la portée des _pistons_ _mécaniques.",
"block.create.piston_extension_pole.tooltip.condition1": "Lorsqu'attaché à un piston mécanique", "block.create.piston_extension_pole.tooltip.condition1": "Lorsqu'attaché à un piston mécanique",
"block.create.piston_extension_pole.tooltip.behaviour1": "Étend la portée du _piston_ d'un bloc", "block.create.piston_extension_pole.tooltip.behaviour1": "Étend la portée du _piston_ d'un bloc",
"block.create.mechanical_bearing.tooltip": "ROULEMENT MÉCANIQUE", "block.create.mechanical_bearing.tooltip": "ROULEMENT MÉCANIQUE",
"block.create.mechanical_bearing.tooltip.summary": "Utilisé pour faire tourner de _plus_ _grande_ _structures_ ou pour exploiter une _force_ _de_ rotation_ contre le vent.", "block.create.mechanical_bearing.tooltip.summary": "Utilisé pour faire tourner de _plus_ _grande_ _structures_ ou pour exploiter une _force_ _de_ rotation_ contre le vent.",
"block.create.mechanical_bearing.tooltip.condition1": "Lorsque tourné", "block.create.mechanical_bearing.tooltip.condition1": "Quand tourné",
"block.create.mechanical_bearing.tooltip.behaviour1": "Démarre les blocs attachés en rotation. Utilisez un _châssis_ ou _bloc_ _de_ _slime_ pour déplacer plus d'un seul bloc.", "block.create.mechanical_bearing.tooltip.behaviour1": "Démarre les blocs attachés en rotation. Utilisez un _châssis_ ou _bloc_ _de_ _slime_ pour déplacer plus d'un seul bloc.",
"block.create.windmill_bearing.tooltip": "UNLOCALIZED: WINDMILL BEARING", "block.create.windmill_bearing.tooltip": "UNLOCALIZED: WINDMILL BEARING",
@ -1583,20 +1583,20 @@
"block.create.clockwork_bearing.tooltip": "ROULEMENT MÉCANIQUE HORLOGER", "block.create.clockwork_bearing.tooltip": "ROULEMENT MÉCANIQUE HORLOGER",
"block.create.clockwork_bearing.tooltip.summary": "Une version avancée du _roulement_ _mécanique_ pour faire tourner jusqu'à deux _aiguilles_ _d'horloge_ en fonction du _temps_ _en-jeu_ actuel.", "block.create.clockwork_bearing.tooltip.summary": "Une version avancée du _roulement_ _mécanique_ pour faire tourner jusqu'à deux _aiguilles_ _d'horloge_ en fonction du _temps_ _en-jeu_ actuel.",
"block.create.clockwork_bearing.tooltip.condition1": "Lorsque tourné", "block.create.clockwork_bearing.tooltip.condition1": "Quand tourné",
"block.create.clockwork_bearing.tooltip.behaviour1": "Commence la rotation de la structure attachée vers l'_heure_ _actuelle_. Si une seconde structure est présente, elle servira _d'aiguille_ _des_ _minutes_.", "block.create.clockwork_bearing.tooltip.behaviour1": "Commence la rotation de la structure attachée vers l'_heure_ _actuelle_. Si une seconde structure est présente, elle servira _d'aiguille_ _des_ _minutes_.",
"block.create.sequenced_gearshift.tooltip": "DÉCALEUR DE ROTATION SÉQUENCÉ", "block.create.sequenced_gearshift.tooltip": "BOÎITE À VITESSES SÉQUENCÉE",
"block.create.sequenced_gearshift.tooltip.summary": "Un _composant_ _utilitaire_ _programmable_, qui peut changer son _débit_ _de_ _rotation_ suivant jusqu'à _5_ _instructions_ _consécutives_. Utilisez-le pour alimenter des roulements mécaniques, des pistons ou des poulies avec plus de contrôle sur le timing et la vitesse. Peut devenir moins précis à des vitesses plus élevées.", "block.create.sequenced_gearshift.tooltip.summary": "Un _composant_ _utilitaire_ _programmable_, qui peut changer son _débit_ _de_ _rotation_ suivant jusqu'à _5_ _instructions_ _consécutives_. Utilisez-le pour alimenter des roulements mécaniques, des pistons ou des poulies avec plus de contrôle sur le timing et la vitesse. Peut devenir moins précis à des vitesses plus élevées.",
"block.create.sequenced_gearshift.tooltip.condition1": "Lorsqu'alimenté par de la redstone", "block.create.sequenced_gearshift.tooltip.condition1": "Lorsqu'alimenté par de la redstone",
"block.create.sequenced_gearshift.tooltip.behaviour1": "_Commence_ _à_ _exécuter_ les instructions programmées en fonction de la vitesse d'entrée.", "block.create.sequenced_gearshift.tooltip.behaviour1": "_Commence_ _à_ _exécuter_ les instructions programmées en fonction de la vitesse d'entrée.",
"block.create.sequenced_gearshift.tooltip.condition2": "Clic droit", "block.create.sequenced_gearshift.tooltip.condition2": "Clic droit",
"block.create.sequenced_gearshift.tooltip.behaviour2": "Ouvre _l'interface_ _de_ _configuration_", "block.create.sequenced_gearshift.tooltip.behaviour2": "Ouvre _l'interface_ _de_ _configuration_",
"block.create.cart_assembler.tooltip": "ASSEMBLEUR DE CHARIOT", "block.create.cart_assembler.tooltip": "ASSEMBLEUR DE WAGON",
"block.create.cart_assembler.tooltip.summary": "Monte une structure connectée sur un _chariot_ _passant_.", "block.create.cart_assembler.tooltip.summary": "Monte une structure connectée sur un _wagon_ _passant_.",
"block.create.cart_assembler.tooltip.condition1": "Lorsqu'alimenté par de la redstone", "block.create.cart_assembler.tooltip.condition1": "Lorsqu'alimenté par de la redstone",
"block.create.cart_assembler.tooltip.behaviour1": "_Démonte_ les structures montées un _chariot_ _passant_ et les remet dans le monde.", "block.create.cart_assembler.tooltip.behaviour1": "_Démonte_ les structures montées un _wagon passant_ et les remet dans le monde.",
"block.create.cart_assembler.tooltip.condition2": "UNLOCALIZED: Carriage Contraptions", "block.create.cart_assembler.tooltip.condition2": "UNLOCALIZED: Carriage Contraptions",
"block.create.cart_assembler.tooltip.behaviour2": "UNLOCALIZED: Two cart assembers _connected by_ a _structure_ will, once both contain a minecart, connect those carts with a _contraption mounted between_ the _two_ of them. The structure will behave similarly to a _Minecart Coupling_.", "block.create.cart_assembler.tooltip.behaviour2": "UNLOCALIZED: Two cart assembers _connected by_ a _structure_ will, once both contain a minecart, connect those carts with a _contraption mounted between_ the _two_ of them. The structure will behave similarly to a _Minecart Coupling_.",
"block.create.cart_assembler.tooltip.control1": "UNLOCALIZED: When placed above Rail", "block.create.cart_assembler.tooltip.control1": "UNLOCALIZED: When placed above Rail",
@ -1608,35 +1608,35 @@
"block.create.cart_assembler.tooltip.control4": "UNLOCALIZED: When placed above Activator Rail", "block.create.cart_assembler.tooltip.control4": "UNLOCALIZED: When placed above Activator Rail",
"block.create.cart_assembler.tooltip.action4": "UNLOCALIZED: _Disassembles_ carts when powered.", "block.create.cart_assembler.tooltip.action4": "UNLOCALIZED: _Disassembles_ carts when powered.",
"block.create.rope_pulley.tooltip": "POULIE DE CORDE", "block.create.rope_pulley.tooltip": "POULIE",
"block.create.rope_pulley.tooltip.summary": "Déplace les _blocs_ et _structures_ attachés _verticalement_. Utilisez un _châssis_ ou _bloc_ _de_ _slime_ pour déplacer plus d'un seul bloc.", "block.create.rope_pulley.tooltip.summary": "Déplace les _blocs_ et _structures_ attachés _verticalement_. Utilisez un _châssis_ ou _bloc_ _de_ _slime_ pour déplacer plus d'un seul bloc.",
"block.create.rope_pulley.tooltip.condition1": "Lorsque tourné", "block.create.rope_pulley.tooltip.condition1": "Quand tourné",
"block.create.rope_pulley.tooltip.behaviour1": "Commence à déplacer la structure attachée. La vitesse et la direction sont corrélées à la vitesse de rotation entrante.", "block.create.rope_pulley.tooltip.behaviour1": "Commence à déplacer la structure attachée. La vitesse et la direction sont corrélées à la vitesse de rotation entrante.",
"block.create.linear_chassis.tooltip": "CHÂSSIS DE TRADUCTION", "block.create.linear_chassis.tooltip": "CHÂSSIS LINÉAIRE",
"block.create.linear_chassis.tooltip.summary": "Un bloc de base configurable reliant les structures pour le mouvement.", "block.create.linear_chassis.tooltip.summary": "Un bloc de base configurable reliant les structures pour le mouvement.",
"block.create.linear_chassis.tooltip.condition1": "Lorsque déplacé", "block.create.linear_chassis.tooltip.condition1": "Quand déplacé",
"block.create.linear_chassis.tooltip.behaviour1": "_Déplace_ tous les _châssis_ _attachés_ avec la même orientation, et une colonne de blocs dans sa portée. Les blocs ne seront tirés que si la face du châssis est _collante_ (Voir [Ctrl]).", "block.create.linear_chassis.tooltip.behaviour1": "_Déplace_ tous les _châssis_ _attachés_ avec la même orientation, et une colonne de blocs dans sa portée. Les blocs ne seront tirés que si la face du châssis est _collante_ (Voir [Ctrl]).",
"block.create.linear_chassis.tooltip.condition2": "Lorsqu'utilisé avec une clé", "block.create.linear_chassis.tooltip.condition2": "Lorsqu'utilisé avec une clé",
"block.create.linear_chassis.tooltip.behaviour2": "Configurez la _portée_ pour ce bloc de châssis. Maintenez CTRL pour modifier également la plage de tous les blocs de châssis connectés.", "block.create.linear_chassis.tooltip.behaviour2": "Configurez la _portée_ pour ce bloc de châssis. Maintenez CTRL pour modifier également la plage de tous les blocs de châssis connectés.",
"block.create.linear_chassis.tooltip.control1": "Clic droit avec une boule de slime", "block.create.linear_chassis.tooltip.control1": "Clic droit avec une boule de slime",
"block.create.linear_chassis.tooltip.action1": "Rends la face _collante_. Lorsque déplace, le châssis va _tirer_ les blocs attachés, quelle que soit la direction du mouvement.", "block.create.linear_chassis.tooltip.action1": "Rend la face _collante_. Quand déplacé, le châssis va _tirer_ les blocs attachés, quelle que soit la direction du mouvement.",
"block.create.secondary_linear_chassis.tooltip": "UNLOCALIZED: SECONDARY LINEAR CHASSIS", "block.create.secondary_linear_chassis.tooltip": "CHÂSSIS LINÉAIRE SECONDAIRE",
"block.create.secondary_linear_chassis.tooltip.summary": "UNLOCALIZED: A second type of _Linear Chassis_ that does not connect to the other.", "block.create.secondary_linear_chassis.tooltip.summary": "Un deuxième type de _châssis linéaire_ qui ne se connecte pas au premier.",
"block.create.radial_chassis.tooltip": "CHÂSSIS DE ROTATION", "block.create.radial_chassis.tooltip": "CHÂSSIS DE ROTATION",
"block.create.radial_chassis.tooltip.summary": "Un bloc de base configurable reliant les structures pour le mouvement.", "block.create.radial_chassis.tooltip.summary": "Un bloc de base configurable reliant les structures pour le mouvement.",
"block.create.radial_chassis.tooltip.condition1": "Lorsque déplacé", "block.create.radial_chassis.tooltip.condition1": "Quand déplacé",
"block.create.radial_chassis.tooltip.behaviour1": "_Déplace_ tous les _châssis_ _attachés_ en colonne, et un cylindre de blocs autour de lui. Les blocs qui l'entourent ne sont déplacés que lorsqu'ils sont à portée et attachés à un côté collant (voir [Ctrl]).", "block.create.radial_chassis.tooltip.behaviour1": "_Déplace_ tous les _châssis_ _attachés_ en colonne, et un cylindre de blocs autour de lui. Les blocs qui l'entourent ne sont déplacés que lorsqu'ils sont à portée et attachés à un côté collant (voir [Ctrl]).",
"block.create.radial_chassis.tooltip.condition2": "Lorsqu'utilisé avec une clé", "block.create.radial_chassis.tooltip.condition2": "Lorsqu'utilisé avec une clé",
"block.create.radial_chassis.tooltip.behaviour2": "Configure la _portée_ pour ce bloc de châssis. Maintenez CTRL pour modifier également la portée de tous les blocs de châssis connectés.", "block.create.radial_chassis.tooltip.behaviour2": "Configure la _portée_ pour ce bloc de châssis. Maintenez CTRL pour modifier également la portée de tous les blocs de châssis connectés.",
"block.create.radial_chassis.tooltip.control1": "Clic droit avec une boule de slime", "block.create.radial_chassis.tooltip.control1": "Clic droit avec une boule de slime",
"block.create.radial_chassis.tooltip.action1": "Rend la face _collante_. Lorsque le châssis se déplace, tous les blocs désignés attachés au côté collant sont déplacés avec lui.", "block.create.radial_chassis.tooltip.action1": "Rend la face _collante_. Quand le châssis se déplace, tous les blocs désignés attachés au côté collant sont déplacés avec lui.",
"block.create.mechanical_drill.tooltip": "PERCEUSE MÉCANIQUE", "block.create.mechanical_drill.tooltip": "PERCEUSE MÉCANIQUE",
"block.create.mechanical_drill.tooltip.summary": "Un dispositif mécanique adapté pour _casser_ les _blocs_. Il est déplaceable avec _pistons_ _mécaniques_ ou _roulements_.", "block.create.mechanical_drill.tooltip.summary": "Un dispositif mécanique adapté pour _casser_ les _blocs_. Il est déplaceable avec _pistons_ _mécaniques_ ou _roulements_.",
"block.create.mechanical_drill.tooltip.condition1": "Lorsque tourné", "block.create.mechanical_drill.tooltip.condition1": "Quand tourné",
"block.create.mechanical_drill.tooltip.behaviour1": "Agit comme un casseur de bloc _stationnaire_. Inflige aussi des _dégats_ aux _entités_ se situant dans sa zone effective.", "block.create.mechanical_drill.tooltip.behaviour1": "Agit comme un casseur de bloc _stationnaire_. Inflige aussi des _dégats_ aux _entités_ se situant dans sa zone effective.",
"block.create.mechanical_drill.tooltip.condition2": "Lorsqu'en mouvement", "block.create.mechanical_drill.tooltip.condition2": "Lorsqu'en mouvement",
"block.create.mechanical_drill.tooltip.behaviour2": "Casse les blocs avec lesquels la perceuse entre en collision.", "block.create.mechanical_drill.tooltip.behaviour2": "Casse les blocs avec lesquels la perceuse entre en collision.",
@ -1646,36 +1646,36 @@
"block.create.mechanical_harvester.tooltip.condition1": "Lorsqu'en mouvement", "block.create.mechanical_harvester.tooltip.condition1": "Lorsqu'en mouvement",
"block.create.mechanical_harvester.tooltip.behaviour1": "_Récolte_ toutes les _cultures_ _matures_ que la lame entre en touche et les remet à leur état de croissance initial.", "block.create.mechanical_harvester.tooltip.behaviour1": "_Récolte_ toutes les _cultures_ _matures_ que la lame entre en touche et les remet à leur état de croissance initial.",
"block.create.mechanical_plough.tooltip": "UNLOCALIZED: MECHANICAL PLOUGH", "block.create.mechanical_plough.tooltip": "CHARRUE MÉCANIQUE",
"block.create.mechanical_plough.tooltip.summary": "UNLOCALIZED: A mechanical plough has a variety of uses. It is movable with _Mechanical Pistons_, _Bearings_ or other controllers.", "block.create.mechanical_plough.tooltip.summary": "Une charrue mécanique a divers usages. Elle peut être déplacée à l'aide de _pistons mécaniques_, de _roulements_ ou d'autres dispositifs de commande.",
"block.create.mechanical_plough.tooltip.condition1": "UNLOCALIZED: While Moving", "block.create.mechanical_plough.tooltip.condition1": "Lorsquen mouvement",
"block.create.mechanical_plough.tooltip.behaviour1": "UNLOCALIZED: _Breaks blocks_ which _cannot be collided_ with, such as torches, tracks or snow layers. _Applies_ its _motion_ to _entities_ without hurting them. _Tills soil blocks_ as though a Hoe would be used on them.", "block.create.mechanical_plough.tooltip.behaviour1": "_Casse les blocs_ avec lesquels _on ne peut pas entrer en collision_, tels que les torches, les sentiers ou les couches de neige. _Applique_ son _mouvement_ aux _entités_ sans les blesser. _Bêche les blocs de terre_ comme si une houe était utilisée sur ceux-ci.",
"block.create.mechanical_saw.tooltip": "SCIE MÉCANIQUE", "block.create.mechanical_saw.tooltip": "SCIE MÉCANIQUE",
"block.create.mechanical_saw.tooltip.summary": "Convient pour _couper_ des _arbres_ efficacement et pour _tailler_ des _blocs_ dans leurs homologues menuisés. Il est déplaceable à l'aide de _pistons_ _mécaniques_ ou _roulements_.", "block.create.mechanical_saw.tooltip.summary": "Convient pour _couper_ des _rotors_ efficacement et pour _tailler_ des _blocs_ dans leurs homologues menuisés. Il est déplaceable à l'aide de _pistons_ _mécaniques_ ou _roulements_.",
"block.create.mechanical_saw.tooltip.condition1": "Lorsque tourné vers le haut", "block.create.mechanical_saw.tooltip.condition1": "Quand tourné vers le haut",
"block.create.mechanical_saw.tooltip.behaviour1": "Applique les _recettes_ de _sciage_ et de _taillerie_ aux éléments jetés ou insérés dedans. Lorsque plusieurs sorties sont possibles, il les parcourt à moins qu'un _filtre_ ne soit affecté.", "block.create.mechanical_saw.tooltip.behaviour1": "Applique les _recettes_ de _sciage_ et de _taillerie_ aux éléments jetés ou insérés dedans. Quand plusieurs sorties sont possibles, il les parcourt à moins qu'un _filtre_ ne soit affecté.",
"block.create.mechanical_saw.tooltip.condition2": "Lorsqu'à l'horizontal", "block.create.mechanical_saw.tooltip.condition2": "Lorsqu'à l'horizontal",
"block.create.mechanical_saw.tooltip.behaviour2": "_Casse_ les _troncs_ devant elle. Si le tronc a supportait un arbre, _l'arbre_ _tombera_ loin de la scie.", "block.create.mechanical_saw.tooltip.behaviour2": "_Casse_ les _troncs_ devant elle. Si le tronc a supportait un rotor, _le rotor_ _tombera_ loin de la scie.",
"block.create.mechanical_saw.tooltip.condition3": "Lorsqu'en mouvement", "block.create.mechanical_saw.tooltip.condition3": "Lorsqu'en mouvement",
"block.create.mechanical_saw.tooltip.behaviour3": "_Coupe_ tous les _arbres_ avec lesquels la scie entre en collision.", "block.create.mechanical_saw.tooltip.behaviour3": "_Coupe_ tous les _rotors_ avec lesquels la scie entre en collision.",
"block.create.stockpile_switch.tooltip": "DÉTÉCTEUR DE STOCKAGE", "block.create.stockpile_switch.tooltip": "DÉTÉCTEUR DE STOCKAGE",
"block.create.stockpile_switch.tooltip.summary": "Bascule un signal Redstone basé sur _l'espace_ _de_ _stockage_ dans le conteneur attaché.", "block.create.stockpile_switch.tooltip.summary": "Bascule un signal Redstone basé sur _l'espace_ _de_ _stockage_ dans le conteneur attaché.",
"block.create.stockpile_switch.tooltip.condition1": "Lorsqu'en dessous de la limite de stockage minimum", "block.create.stockpile_switch.tooltip.condition1": "Lorsqu'en dessous de la limite de stockage minimum",
"block.create.stockpile_switch.tooltip.behaviour1": "Arrête de fournir de _l'énergie_", "block.create.stockpile_switch.tooltip.behaviour1": "Arrête de fournir de _l'énergie_",
"block.create.content_observer.tooltip": "UNLOCALIZED: CONTENT OBSERVER", "block.create.content_observer.tooltip": "OBSERVATEUR DE CONTENU",
"block.create.content_observer.tooltip.summary": "UNLOCALIZED: _Detects Items_ inside _containers_ and _conveyors_ matching a configured _filter_. While the observed _inventory_, _belt_ or _chute contains_ a matching item, this component will emit a _Redstone Signal_. When an observed _funnel transfers_ a matching item, this component will emit a _Redstone Pulse_.", "block.create.content_observer.tooltip.summary": "_Détecte les objets_ à l'intérieur des _conteneurs_ et des _transporteurs_ correspondant à un _filtre_ configuré. Tant que l'_inventaire_, le _tapis roulant_ ou la _glissière_ observé _contient_ un objet correspondant, ce composant émet un _signal de redstone_. Quand un _entonnoir_ observé _transfère_ un objet correspondant, ce composant émet une _impulsion de redstone_.",
"block.create.redstone_link.tooltip": "LIAISON REDSTONE", "block.create.redstone_link.tooltip": "LIEN DE REDSTONE",
"block.create.redstone_link.tooltip.summary": "Points de terminaison pour les connexions de _redstone_ _sans-fil_. Peut être attribué des _fréquences_ en utilisant n'importe quel objet. La portée du signal est limitée, quoique raisonnablement loin.", "block.create.redstone_link.tooltip.summary": "Terminaux pour les connexions de _redstone_ _sans-fil_. Peut être attribué des _fréquences_ en utilisant n'importe quel objet. La portée du signal est limitée, nonobstant raisonnablement loin.",
"block.create.redstone_link.tooltip.condition1": "Lorsqu'alimenté", "block.create.redstone_link.tooltip.condition1": "Quand alimenté",
"block.create.redstone_link.tooltip.behaviour1": "La réception de liens de la même _fréquence_ produira un signal redstone.", "block.create.redstone_link.tooltip.behaviour1": "Les liens de la même _fréquence_ configurés en réception produira un signal redstone.",
"block.create.redstone_link.tooltip.control1": "Clic droit avec un objet", "block.create.redstone_link.tooltip.control1": "Clic droit avec un objet",
"block.create.redstone_link.tooltip.action1": "Définit la _fréquence_ sur cet élément. Un total de _deux_ _différents_ _objets_ peuvent être utilisés en combinaison pour définir une fréquence.", "block.create.redstone_link.tooltip.action1": "Définit la _fréquence_ sur cet élément. Un total de _deux_ _différents_ _objets_ peuvent être utilisés en combinaison pour définir une fréquence.",
"block.create.redstone_link.tooltip.control2": "Clic droit en étant accroupi", "block.create.redstone_link.tooltip.control2": "Clic droit en étant accroupi",
"block.create.redstone_link.tooltip.action2": "TBascule entre le mode _receveur_ et _transmetteur_.", "block.create.redstone_link.tooltip.action2": "Bascule entre le mode _récepteur_ et _transmetteur_.",
"block.create.nixie_tube.tooltip": "UNLOCALIZED: NIXIE TUBE", "block.create.nixie_tube.tooltip": "UNLOCALIZED: NIXIE TUBE",
"block.create.nixie_tube.tooltip.summary": "UNLOCALIZED: A fancy redstone-powered _Number_ and _Text Display_.", "block.create.nixie_tube.tooltip.summary": "UNLOCALIZED: A fancy redstone-powered _Number_ and _Text Display_.",
@ -1684,12 +1684,12 @@
"block.create.nixie_tube.tooltip.condition2": "UNLOCALIZED: With Name Tag", "block.create.nixie_tube.tooltip.condition2": "UNLOCALIZED: With Name Tag",
"block.create.nixie_tube.tooltip.behaviour2": "UNLOCALIZED: Display _contents_ of your _name tag_ with several nixie tubes _arranged_ in a _line_.", "block.create.nixie_tube.tooltip.behaviour2": "UNLOCALIZED: Display _contents_ of your _name tag_ with several nixie tubes _arranged_ in a _line_.",
"block.create.redstone_contact.tooltip": "redstone_contact REDSTONE", "block.create.redstone_contact.tooltip": "CONTACT DE REDSTONE",
"block.create.redstone_contact.tooltip.summary": "N'émet de l'énergie que par paires. Il est mobile avec _pistons_ _mécaniques_ ou _roulements_.", "block.create.redstone_contact.tooltip.summary": "N'émet de l'énergie que par paires. Il est mobile avec des _pistons_ _mécaniques_ ou _roulements_.",
"block.create.redstone_contact.tooltip.condition1": "Lorsque tourné vers un autre redstone_contact", "block.create.redstone_contact.tooltip.condition1": "Quand tourné vers un autre contact de redstone",
"block.create.redstone_contact.tooltip.behaviour1": "Fournit un _signal_ _redstone_.", "block.create.redstone_contact.tooltip.behaviour1": "Fournit un _signal_ de _redstone_.",
"block.create.redstone_contact.tooltip.condition2": "Lorsqu'en mouvement", "block.create.redstone_contact.tooltip.condition2": "Quand en mouvement",
"block.create.redstone_contact.tooltip.behaviour2": "Déclenche tous les redstone_contacts fixes qu'il passe.", "block.create.redstone_contact.tooltip.behaviour2": "Déclenche tous les contacts de redstone fixes qu'il passe.",
"block.create.adjustable_crate.tooltip": "CAISSE AJUSTABLE", "block.create.adjustable_crate.tooltip": "CAISSE AJUSTABLE",
"block.create.adjustable_crate.tooltip.summary": "Ce _conteneur_ _de_ _stockage_ permet un contrôle manuel de sa capacité. Il peut contenir jusqu'à _16_ _piles_ de n'importe quel objet. Prend en charge les _comparateurs_ _de_ _redstone_.", "block.create.adjustable_crate.tooltip.summary": "Ce _conteneur_ _de_ _stockage_ permet un contrôle manuel de sa capacité. Il peut contenir jusqu'à _16_ _piles_ de n'importe quel objet. Prend en charge les _comparateurs_ _de_ _redstone_.",
@ -1698,20 +1698,20 @@
"block.create.creative_crate.tooltip": "CAISSE CRÉATIVE", "block.create.creative_crate.tooltip": "CAISSE CRÉATIVE",
"block.create.creative_crate.tooltip.summary": "Fournit une réserve infinie de blocs aux _Schémacanons_ adjacents.", "block.create.creative_crate.tooltip.summary": "Fournit une réserve infinie de blocs aux _Schémacanons_ adjacents.",
"block.create.creative_crate.tooltip.condition1": "UNLOCALIZED: When Item in Filter Slot", "block.create.creative_crate.tooltip.condition1": "Quand un objet se trouve dans l'emplacement de filtrage",
"block.create.creative_crate.tooltip.behaviour1": "UNLOCALIZED: Anything _extracting_ from this container will provide an _endless supply_ of the item specified. Items _inserted_ into this crate will be _voided._", "block.create.creative_crate.tooltip.behaviour1": "Tout ce qui _extrait_ de ce conteneur aura une _alimentation illimitée_ de l'objet spécifié. Les objets _insérés_ dans cette caisse seront _éliminés_.",
"block.create.deployer.tooltip": "DÉPLOYEUR", "block.create.deployer.tooltip": "DÉPLOYEUR",
"block.create.deployer.tooltip.summary": "_Frappe_, _utilise_ et _active_. Cette machine essaiera _d'imiter_ un _joueur_ autant que possible. Peut _prendre_ et _déposer_ des _objets_ dans _l'inventaire_ adjacent. Peut être affecté à une pile d'éléments en tant que _filtre_.", "block.create.deployer.tooltip.summary": "_Frappe_, _utilise_ et _active_. Cette machine essaiera _d'imiter_ un _joueur_ autant que possible. Peut _prendre_ et _déposer_ des _objets_ dans _l'inventaire_ adjacent. Peut être affecté à une pile d'éléments en tant que _filtre_.",
"block.create.deployer.tooltip.condition1": "Lorsque tourné", "block.create.deployer.tooltip.condition1": "Quand tourné",
"block.create.deployer.tooltip.behaviour1": "Étend son bras et _active_ dans l'espace de bloc _2m_ _devant_ de lui-même.", "block.create.deployer.tooltip.behaviour1": "Étend son bras et _active_ dans l'espace de bloc _2m_ _devant_ de lui-même.",
"block.create.deployer.tooltip.condition2": "Clic droit avec une clé", "block.create.deployer.tooltip.condition2": "Clic droit avec une clé",
"block.create.deployer.tooltip.behaviour2": "Bascule le mode frappe. Dans le _mode_ _frappe_, le déployeur tentera d'utiliser son élément pour _casser_ les _blocs_ ou infliger des _dégats_ aux _entités_.", "block.create.deployer.tooltip.behaviour2": "Bascule le mode frappe. Dans le _mode_ _frappe_, le déployeur tentera d'utiliser son élément pour _casser_ les _blocs_ ou infliger des _dégats_ aux _entités_.",
"block.create.deployer.tooltip.condition3": "UNLOCALIZED: When Filter assigned", "block.create.deployer.tooltip.condition3": "Quand un filtre est attribué",
"block.create.deployer.tooltip.behaviour3": "UNLOCALIZED: Deployer will not activate unless held item _matches_ the _filter._ Items not matching cannot be inserted; Held items matching the filter cannot be extracted.", "block.create.deployer.tooltip.behaviour3": "Le déploiement n'est activé que si l'élément tenu _correspond_ au _filtre._ Les éléments ne correspondant pas ne peuvent pas être insérés ; les éléments tenus correspondant au filtre ne peuvent pas être extraits.",
"block.create.brass_casing.tooltip": "BOÎTIER EN LAITON", "block.create.brass_casing.tooltip": "REVÊTEMENT EN LAITON",
"block.create.brass_casing.tooltip.summary": "Boîtier de machine robuste avec une variété d'utilisations. Sans danger pour la décoration.", "block.create.brass_casing.tooltip.summary": "Revêtement de machine robuste avec une variété d'utilisations. Sans danger pour la décoration.",
"block.create.pulse_repeater.tooltip": "RÉPÉTEUR D'IMPULSIONS", "block.create.pulse_repeater.tooltip": "RÉPÉTEUR D'IMPULSIONS",
"block.create.pulse_repeater.tooltip.summary": "Un circuit simple pour couper les signaux de redstone passant à une longueur de _1_ _tick_.", "block.create.pulse_repeater.tooltip.summary": "Un circuit simple pour couper les signaux de redstone passant à une longueur de _1_ _tick_.",
@ -1738,28 +1738,28 @@
"block.create.speedometer.tooltip": "COMPTEUR DE VITESSE", "block.create.speedometer.tooltip": "COMPTEUR DE VITESSE",
"block.create.speedometer.tooltip.summary": "Mesure et affiche la _ vitesse de rotation _ des composants cinétiques attachés. Prend en charge les _comparateurs_ _de_ _redstone_.", "block.create.speedometer.tooltip.summary": "Mesure et affiche la _ vitesse de rotation _ des composants cinétiques attachés. Prend en charge les _comparateurs_ _de_ _redstone_.",
"block.create.speedometer.tooltip.condition1": "Lorsque tourné", "block.create.speedometer.tooltip.condition1": "Quand tourné",
"block.create.speedometer.tooltip.behaviour1": "Indique une couleur correspondant au niveau de vitesse. _Vert_ indique une rotation lente, _Bleu_ modérée et _violet_ rapide. Certains composants mécaniques nécessitent une vitesse suffisante pour fonctionner correctement.", "block.create.speedometer.tooltip.behaviour1": "Indique une couleur correspondant au niveau de vitesse. _Vert_ indique une rotation lente, _Bleu_ modérée et _violet_ rapide. Certains composants mécaniques nécessitent une vitesse suffisante pour fonctionner correctement.",
"block.create.stressometer.tooltip": "STRESSOMÈTRE", "block.create.stressometer.tooltip": "STRESSOMÈTRE",
"block.create.stressometer.tooltip.summary": "Mesure et affiche la _stress__ globale du réseau cinétique attaché. Prend en charge les _comparateurs_ _de_ _redstone_.", "block.create.stressometer.tooltip.summary": "Mesure et affiche la _stress__ globale du réseau cinétique attaché. Prend en charge les _comparateurs_ _de_ _redstone_.",
"block.create.stressometer.tooltip.condition1": "Lorsque tourné", "block.create.stressometer.tooltip.condition1": "Quand tourné",
"block.create.stressometer.tooltip.behaviour1": "Indique une couleur correspondant au niveau de contrainte. Les _réseaux_ _surchargés_ cesseront de bouger. Le stress peut être soulagé en ajoutant plus de _sources_ _rotationnelles_ au réseau.", "block.create.stressometer.tooltip.behaviour1": "Indique une couleur correspondant au niveau de contrainte. Les _réseaux_ _surchargés_ cesseront de bouger. Le stress peut être soulagé en ajoutant plus de _sources_ _rotationnelles_ au réseau.",
"item.create.sand_paper.tooltip": "UNLOCALIZED: SAND PAPER", "item.create.sand_paper.tooltip": "PAPIER DE VERRE",
"item.create.sand_paper.tooltip.summary": "UNLOCALIZED: A rough paper that can be used to _polish materials_. Can be automatically applied using the Deployer.", "item.create.sand_paper.tooltip.summary": "Un papier rugueux qui peut être utilisé pour _polir des matériaux_. Peut être appliqué automatiquement à l'aide du déployeur.",
"item.create.sand_paper.tooltip.condition1": "UNLOCALIZED: When Used", "item.create.sand_paper.tooltip.condition1": "Quand utilisé",
"item.create.sand_paper.tooltip.behaviour1": "UNLOCALIZED: Applies polish to items held in the _offhand_ or lying on the _floor_ when _looking at them_", "item.create.sand_paper.tooltip.behaviour1": "Polit les objets qui se tenus dans la _main secondaire_ ou par terre quand on les _regarde_.",
"item.create.super_glue.tooltip": "UNLOCALIZED: SUPER GLUE", "item.create.super_glue.tooltip": "COLLE EXTRA-FORTE",
"item.create.super_glue.tooltip.summary": "UNLOCALIZED: Glue a block to another, and they will forever be inseparable.", "item.create.super_glue.tooltip.summary": "Collez un bloc à un autre, et ils seront à jamais inséparables.",
"item.create.super_glue.tooltip.condition1": "UNLOCALIZED: When Used", "item.create.super_glue.tooltip.condition1": "Quand utilisé",
"item.create.super_glue.tooltip.behaviour1": "UNLOCALIZED: Makes the _clicked face_ of a block _sticky_. Blocks attached to sticky faces will be _dragged along_ when moved by _mechanical pistons_, _bearings_ and other controllers.", "item.create.super_glue.tooltip.behaviour1": "Rend la face _cliquée_ d'un bloc _collante_. Les blocs attachés aux faces collantes seront entraînés par des _pistons mécaniques_, _des roulements_ et d'autres contrôleurs.",
"item.create.super_glue.tooltip.condition2": "UNLOCALIZED: When Held in Offhand", "item.create.super_glue.tooltip.condition2": "Quand tenu en main secondaire",
"item.create.super_glue.tooltip.behaviour2": "UNLOCALIZED: _Automatically attaches_ blocks placed from the main hand to the _side_ they were _placed against._", "item.create.super_glue.tooltip.behaviour2": "Attache automatiquement les blocs placés de la main principale à la _face_ contre laquelle ils ont été _placés_.",
"item.create.builders_tea.tooltip": "UNLOCALIZED: BUILDERS TEA", "item.create.builders_tea.tooltip": "THÉ DU CONSTRUCTEUR",
"item.create.builders_tea.tooltip.summary": "UNLOCALIZED: The perfect drink to get the day started- _Motivating_ and _Saturating._", "item.create.builders_tea.tooltip.summary": "La boisson parfaite pour commencer la journée - _motivante_ et _rasasiante_.",
"item.create.refined_radiance.tooltip": "ÉCLAT RAFFINÉ", "item.create.refined_radiance.tooltip": "ÉCLAT RAFFINÉ",
"item.create.refined_radiance.tooltip.summary": "Un matériau chromatique forgé à partir de _lumière_ _absorbée_.", "item.create.refined_radiance.tooltip.summary": "Un matériau chromatique forgé à partir de _lumière_ _absorbée_.",
@ -1767,7 +1767,7 @@
"item.create.shadow_steel.tooltip": "ACIER SOMBRE", "item.create.shadow_steel.tooltip": "ACIER SOMBRE",
"item.create.shadow_steel.tooltip.summary": "Un matériau chromatique forgé _dans_ _le_ _néant_.", "item.create.shadow_steel.tooltip.summary": "Un matériau chromatique forgé _dans_ _le_ _néant_.",
"item.create.minecart_coupling.tooltip": "UNLOCALIZED: MINECART COUPLING", "item.create.minecart_coupling.tooltip": "LIEN POUR WAGONS",
"item.create.minecart_coupling.tooltip.summary": "UNLOCALIZED: _Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", "item.create.minecart_coupling.tooltip.summary": "UNLOCALIZED: _Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.",
"item.create.minecart_coupling.tooltip.condition1": "UNLOCALIZED: When Used on Minecart", "item.create.minecart_coupling.tooltip.condition1": "UNLOCALIZED: When Used on Minecart",
"item.create.minecart_coupling.tooltip.behaviour1": "UNLOCALIZED: _Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.", "item.create.minecart_coupling.tooltip.behaviour1": "UNLOCALIZED: _Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.",
@ -1780,7 +1780,7 @@
"create.tooltip.randomWipDescription0": "Veuillez garder cet objet hors de portée des enfants.", "create.tooltip.randomWipDescription0": "Veuillez garder cet objet hors de portée des enfants.",
"create.tooltip.randomWipDescription1": "Un bébé panda meurt chaque fois que vous utilisez cet objet. Chaque. Fois.", "create.tooltip.randomWipDescription1": "Un bébé panda meurt chaque fois que vous utilisez cet objet. Chaque. Fois.",
"create.tooltip.randomWipDescription2": "À utiliser à vos risques et périls.", "create.tooltip.randomWipDescription2": "À utiliser à vos risques et périls.",
"create.tooltip.randomWipDescription3": "Ce n'est pas l'objet que vous recherchez, *agites les doigts* veuillez vous disperser.", "create.tooltip.randomWipDescription3": "Ce n'est pas l'objet que vous recherchez, *agite les doigts* circulez.",
"create.tooltip.randomWipDescription4": "Cet objet s'autodétruit en 10 secondes. 10, 9, 8...", "create.tooltip.randomWipDescription4": "Cet objet s'autodétruit en 10 secondes. 10, 9, 8...",
"create.tooltip.randomWipDescription5": "Croyez-moi, c'est inutile.", "create.tooltip.randomWipDescription5": "Croyez-moi, c'est inutile.",
"create.tooltip.randomWipDescription6": "En utilisant cet article, vous êtes responsables et acceptez ses conditions.", "create.tooltip.randomWipDescription6": "En utilisant cet article, vous êtes responsables et acceptez ses conditions.",

View file

@ -23,6 +23,7 @@
"create:redstone_link", "create:redstone_link",
"create:analog_lever", "create:analog_lever",
"create:adjustable_repeater", "create:adjustable_repeater",
"create:adjustable_pulse_repeater" "create:adjustable_pulse_repeater",
"#minecraft:signs"
] ]
} }

View file

@ -187,5 +187,7 @@ public class AllTags {
AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS); AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS);
AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE); AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE);
AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS);
} }
} }

View file

@ -8,7 +8,6 @@ import java.util.stream.Collectors;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter; import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;

View file

@ -38,7 +38,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity {
if (!(tileEntity instanceof KineticTileEntity)) if (!(tileEntity instanceof KineticTileEntity))
return; return;
KineticTileEntity sourceTe = (KineticTileEntity) tileEntity; KineticTileEntity sourceTe = (KineticTileEntity) tileEntity;
if (reActivateSource && sourceTe != null && Math.abs(sourceTe.getSpeed()) >= Math.abs(getGeneratedSpeed())) if (reActivateSource && Math.abs(sourceTe.getSpeed()) >= Math.abs(getGeneratedSpeed()))
reActivateSource = false; reActivateSource = false;
} }

View file

@ -183,7 +183,6 @@ public class DeployerTileEntity extends KineticTileEntity {
if (state == State.EXPANDING) { if (state == State.EXPANDING) {
if (boop) if (boop)
triggerBoop(); triggerBoop();
else
activate(); activate();
state = State.RETRACTING; state = State.RETRACTING;

View file

@ -82,7 +82,7 @@ public class AirCurrent {
protected void tickAffectedEntities(World world, Direction facing) { protected void tickAffectedEntities(World world, Direction facing) {
for (Iterator<Entity> iterator = caughtEntities.iterator(); iterator.hasNext();) { for (Iterator<Entity> iterator = caughtEntities.iterator(); iterator.hasNext();) {
Entity entity = iterator.next(); Entity entity = iterator.next();
if (!entity.getBoundingBox() if (!entity.isAlive() || !entity.getBoundingBox()
.intersects(bounds)) { .intersects(bounds)) {
iterator.remove(); iterator.remove();
continue; continue;

View file

@ -1,6 +1,5 @@
package com.simibubi.create.content.contraptions.components.fan; package com.simibubi.create.content.contraptions.components.fan;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock; import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
@ -33,9 +32,16 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
@Override @Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
super.onBlockAdded(state, worldIn, pos, oldState, isMoving);
blockUpdate(state, worldIn, pos); blockUpdate(state, worldIn, pos);
} }
@Override
public void updateNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags) {
super.updateNeighbors(stateIn, worldIn, pos, flags);
blockUpdate(stateIn, worldIn, pos);
}
@Override @Override
public void onReplaced(BlockState state, World world, BlockPos pos, BlockState p_196243_4_, boolean p_196243_5_) { public void onReplaced(BlockState state, World world, BlockPos pos, BlockState p_196243_4_, boolean p_196243_5_) {
if (state.hasTileEntity() && (state.getBlock() != p_196243_4_.getBlock() || !p_196243_4_.hasTileEntity())) { if (state.hasTileEntity() && (state.getBlock() != p_196243_4_.getBlock() || !p_196243_4_.hasTileEntity())) {
@ -70,13 +76,13 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
.isSneaking() ? preferredFacing : preferredFacing.getOpposite()); .isSneaking() ? preferredFacing : preferredFacing.getOpposite());
} }
protected void blockUpdate(BlockState state, World worldIn, BlockPos pos) { protected void blockUpdate(BlockState state, IWorld worldIn, BlockPos pos) {
if (worldIn instanceof WrappedWorld) if (worldIn instanceof WrappedWorld)
return; return;
notifyFanTile(worldIn, pos); notifyFanTile(worldIn, pos);
if (worldIn.isRemote) if (worldIn.isRemote())
return; return;
withTileEntityDo(worldIn, pos, te -> te.updateGenerator(state.get(FACING))); withTileEntityDo(worldIn, pos, te -> te.queueGeneratorUpdate());
} }
protected void notifyFanTile(IWorld world, BlockPos pos) { protected void notifyFanTile(IWorld world, BlockPos pos) {

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.fan;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
@ -18,7 +19,6 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements IAirCurrentSource { public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements IAirCurrentSource {
@ -27,17 +27,20 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
protected int entitySearchCooldown; protected int entitySearchCooldown;
protected boolean isGenerator; protected boolean isGenerator;
protected boolean updateAirFlow; protected boolean updateAirFlow;
protected boolean updateGenerator;
public EncasedFanTileEntity(TileEntityType<? extends EncasedFanTileEntity> type) { public EncasedFanTileEntity(TileEntityType<? extends EncasedFanTileEntity> type) {
super(type); super(type);
isGenerator = false; isGenerator = false;
airCurrent = new AirCurrent(this); airCurrent = new AirCurrent(this);
updateAirFlow = true; updateAirFlow = true;
updateGenerator = false;
} }
@Override @Override
protected void read(CompoundNBT compound, boolean clientPacket) { protected void read(CompoundNBT compound, boolean clientPacket) {
super.read(compound, clientPacket); super.read(compound, clientPacket);
if (!wasMoved)
isGenerator = compound.getBoolean("Generating"); isGenerator = compound.getBoolean("Generating");
if (clientPacket) if (clientPacket)
airCurrent.rebuild(); airCurrent.rebuild();
@ -64,12 +67,20 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
return isGenerator ? AllConfigs.SERVER.kinetics.generatingFanSpeed.get() : 0; return isGenerator ? AllConfigs.SERVER.kinetics.generatingFanSpeed.get() : 0;
} }
public void updateGenerator(Direction facing) { public void queueGeneratorUpdate() {
boolean shouldGenerate = world.isBlockPowered(pos) && facing == Direction.DOWN updateGenerator = true;
&& world.isBlockPresent(pos.down()) && blockBelowIsHot(); }
if (shouldGenerate == isGenerator)
public void updateGenerator() {
BlockState blockState = getBlockState();
if (!AllBlocks.ENCASED_FAN.has(blockState))
return;
if (blockState.get(EncasedFanBlock.FACING) != Direction.DOWN)
return; return;
boolean shouldGenerate = world.isBlockPowered(pos) && world.isBlockPresent(pos.down()) && blockBelowIsHot();
if (shouldGenerate == isGenerator)
return;
isGenerator = shouldGenerate; isGenerator = shouldGenerate;
updateGeneratedRotation(); updateGeneratedRotation();
} }
@ -171,6 +182,11 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
sendData(); sendData();
} }
if (updateGenerator) {
updateGenerator = false;
updateGenerator();
}
if (getSpeed() == 0 || isGenerator) if (getSpeed() == 0 || isGenerator)
return; return;

View file

@ -153,6 +153,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
for (ItemEntity itemEntity : world.getEntitiesWithinAABB(ItemEntity.class, for (ItemEntity itemEntity : world.getEntitiesWithinAABB(ItemEntity.class,
new AxisAlignedBB(pos.down()).shrink(.125f))) { new AxisAlignedBB(pos.down()).shrink(.125f))) {
if (!itemEntity.isAlive() || !itemEntity.onGround)
continue;
ItemStack stack = itemEntity.getItem(); ItemStack stack = itemEntity.getItem();
Optional<PressingRecipe> recipe = getRecipe(stack); Optional<PressingRecipe> recipe = getRecipe(stack);
if (!recipe.isPresent()) if (!recipe.isPresent())
@ -233,7 +235,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) { for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) {
if (!(entity instanceof ItemEntity)) if (!(entity instanceof ItemEntity))
continue; continue;
if (!entity.isAlive()) if (!entity.isAlive() || !entity.onGround)
continue; continue;
ItemEntity itemEntity = (ItemEntity) entity; ItemEntity itemEntity = (ItemEntity) entity;
pressedItems.add(itemEntity.getItem()); pressedItems.add(itemEntity.getItem());

View file

@ -0,0 +1,91 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import com.simibubi.create.foundation.config.AllConfigs;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
public class AssemblyException extends Exception {
public final ITextComponent component;
private BlockPos position = null;
public static void write(CompoundNBT compound, AssemblyException exception) {
if (exception == null)
return;
CompoundNBT nbt = new CompoundNBT();
nbt.putString("Component", ITextComponent.Serializer.toJson(exception.component));
if (exception.hasPosition())
nbt.putLong("Position", exception.getPosition().toLong());
compound.put("LastException", nbt);
}
public static AssemblyException read(CompoundNBT compound) {
if (!compound.contains("LastException"))
return null;
CompoundNBT nbt = compound.getCompound("LastException");
String string = nbt.getString("Component");
AssemblyException exception = new AssemblyException(ITextComponent.Serializer.fromJson(string));
if (nbt.contains("Position"))
exception.position = BlockPos.fromLong(nbt.getLong("Position"));
return exception;
}
public AssemblyException(ITextComponent component) {
this.component = component;
}
public AssemblyException(String langKey, Object... objects) {
this(new TranslationTextComponent("create.gui.assembly.exception." + langKey, objects));
}
public static AssemblyException unmovableBlock(BlockPos pos, BlockState state) {
AssemblyException e = new AssemblyException("unmovableBlock",
pos.getX(),
pos.getY(),
pos.getZ(),
new TranslationTextComponent(state.getBlock().getTranslationKey()));
e.position = pos;
return e;
}
public static AssemblyException unloadedChunk(BlockPos pos) {
AssemblyException e = new AssemblyException("chunkNotLoaded",
pos.getX(),
pos.getY(),
pos.getZ());
e.position = pos;
return e;
}
public static AssemblyException structureTooLarge() {
return new AssemblyException("structureTooLarge",
AllConfigs.SERVER.kinetics.maxBlocksMoved.get());
}
public static AssemblyException tooManyPistonPoles() {
return new AssemblyException("tooManyPistonPoles",
AllConfigs.SERVER.kinetics.maxPistonPoles.get());
}
public static AssemblyException noPistonPoles() {
return new AssemblyException("noPistonPoles");
}
public String getFormattedText() {
return component.getFormattedText();
}
public boolean hasPosition() {
return position != null;
}
public BlockPos getPosition() {
return position;
}
}

View file

@ -53,8 +53,7 @@ import net.minecraft.world.World;
public class BlockMovementTraits { public class BlockMovementTraits {
public static boolean movementNecessary(World world, BlockPos pos) { public static boolean movementNecessary(BlockState state, World world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
if (isBrittle(state)) if (isBrittle(state))
return true; return true;
if (state.getBlock() instanceof FenceGateBlock) if (state.getBlock() instanceof FenceGateBlock)
@ -68,18 +67,17 @@ public class BlockMovementTraits {
return true; return true;
} }
public static boolean movementAllowed(World world, BlockPos pos) { public static boolean movementAllowed(BlockState state, World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos); Block block = state.getBlock();
Block block = blockState.getBlock();
if (block instanceof AbstractChassisBlock) if (block instanceof AbstractChassisBlock)
return true; return true;
if (blockState.getBlockHardness(world, pos) == -1) if (state.getBlockHardness(world, pos) == -1)
return false; return false;
if (AllBlockTags.NON_MOVABLE.matches(blockState)) if (AllBlockTags.NON_MOVABLE.matches(state))
return false; return false;
// Move controllers only when they aren't moving // Move controllers only when they aren't moving
if (block instanceof MechanicalPistonBlock && blockState.get(MechanicalPistonBlock.STATE) != PistonState.MOVING) if (block instanceof MechanicalPistonBlock && state.get(MechanicalPistonBlock.STATE) != PistonState.MOVING)
return true; return true;
if (block instanceof MechanicalBearingBlock) { if (block instanceof MechanicalBearingBlock) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
@ -97,11 +95,11 @@ public class BlockMovementTraits {
return !((PulleyTileEntity) te).running; return !((PulleyTileEntity) te).running;
} }
if (AllBlocks.BELT.has(blockState)) if (AllBlocks.BELT.has(state))
return true; return true;
if (blockState.getBlock() instanceof GrindstoneBlock) if (state.getBlock() instanceof GrindstoneBlock)
return true; return true;
return blockState.getPushReaction() != PushReaction.BLOCK; return state.getPushReaction() != PushReaction.BLOCK;
} }
/** /**
@ -227,6 +225,12 @@ public class BlockMovementTraits {
if (state.getBlock() instanceof SailBlock) if (state.getBlock() instanceof SailBlock)
return facing.getAxis() == state.get(SailBlock.FACING) return facing.getAxis() == state.get(SailBlock.FACING)
.getAxis(); .getAxis();
if (AllBlocks.PISTON_EXTENSION_POLE.has(state))
return facing.getAxis() != state.get(BlockStateProperties.FACING)
.getAxis();
if (AllBlocks.MECHANICAL_PISTON_HEAD.has(state))
return facing.getAxis() != state.get(BlockStateProperties.FACING)
.getAxis();
return isBrittle(state); return isBrittle(state);
} }

View file

@ -1,28 +1,8 @@
package com.simibubi.create.content.contraptions.components.structureMovement; package com.simibubi.create.content.contraptions.components.structureMovement;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.actors.SeatBlock; import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
import com.simibubi.create.content.contraptions.components.actors.SeatEntity; import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
@ -35,6 +15,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.glu
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueHandler; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueHandler;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonHeadBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.MagnetBlock; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.MagnetBlock;
@ -50,17 +31,11 @@ import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.NBTProcessors;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.block.*;
import net.minecraft.block.AbstractButtonBlock; import net.minecraft.block.material.PushReaction;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.ChestBlock;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.block.PressurePlateBlock;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.fluid.Fluids; import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState; import net.minecraft.fluid.IFluidState;
@ -71,6 +46,7 @@ import net.minecraft.nbt.NBTUtil;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.ChestType; import net.minecraft.state.properties.ChestType;
import net.minecraft.state.properties.DoubleBlockHalf; import net.minecraft.state.properties.DoubleBlockHalf;
import net.minecraft.state.properties.PistonType;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
@ -91,6 +67,16 @@ import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.templates.FluidTank; import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.CombinedInvWrapper; import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
public abstract class Contraption { public abstract class Contraption {
@ -134,9 +120,9 @@ public abstract class Contraption {
stabilizedSubContraptions = new HashMap<>(); stabilizedSubContraptions = new HashMap<>();
} }
public abstract boolean assemble(World world, BlockPos pos); public abstract boolean assemble(World world, BlockPos pos) throws AssemblyException;
protected abstract boolean canAxisBeStabilized(Axis axis); public abstract boolean canBeStabilized(Direction facing, BlockPos localPos);
protected abstract ContraptionType getType(); protected abstract ContraptionType getType();
@ -149,7 +135,7 @@ public abstract class Contraption {
} }
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection, protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection,
List<BlockPos> frontier) { Queue<BlockPos> frontier) throws AssemblyException {
return true; return true;
} }
@ -160,9 +146,9 @@ public abstract class Contraption {
return contraption; return contraption;
} }
public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) { public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) throws AssemblyException {
initialPassengers.clear(); initialPassengers.clear();
List<BlockPos> frontier = new ArrayList<>(); Queue<BlockPos> frontier = new LinkedList<>();
Set<BlockPos> visited = new HashSet<>(); Set<BlockPos> visited = new HashSet<>();
anchor = pos; anchor = pos;
@ -176,10 +162,10 @@ public abstract class Contraption {
for (int limit = 100000; limit > 0; limit--) { for (int limit = 100000; limit > 0; limit--) {
if (frontier.isEmpty()) if (frontier.isEmpty())
return true; return true;
if (!moveBlock(world, frontier.remove(0), forcedDirection, frontier, visited)) if (!moveBlock(world, forcedDirection, frontier, visited))
return false; return false;
} }
return false; throw AssemblyException.structureTooLarge();
} }
public void onEntityCreated(AbstractContraptionEntity entity) { public void onEntityCreated(AbstractContraptionEntity entity) {
@ -191,8 +177,12 @@ public abstract class Contraption {
StabilizedContraption subContraption = new StabilizedContraption(face); StabilizedContraption subContraption = new StabilizedContraption(face);
World world = entity.world; World world = entity.world;
BlockPos pos = blockFace.getPos(); BlockPos pos = blockFace.getPos();
try {
if (!subContraption.assemble(world, pos)) if (!subContraption.assemble(world, pos))
continue; continue;
} catch (AssemblyException e) {
continue;
}
subContraption.removeBlocksFromWorld(world, BlockPos.ZERO); subContraption.removeBlocksFromWorld(world, BlockPos.ZERO);
OrientedContraptionEntity movedContraption = OrientedContraptionEntity movedContraption =
OrientedContraptionEntity.create(world, subContraption, Optional.of(face)); OrientedContraptionEntity.create(world, subContraption, Optional.of(face));
@ -242,20 +232,25 @@ public abstract class Contraption {
fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isRemote)); fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isRemote));
} }
protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List<BlockPos> frontier, /** move the first block in frontier queue */
Set<BlockPos> visited) { protected boolean moveBlock(World world, @Nullable Direction forcedDirection, Queue<BlockPos> frontier,
visited.add(pos); Set<BlockPos> visited) throws AssemblyException {
frontier.remove(pos); BlockPos pos = frontier.poll();
if (pos == null)
if (!world.isBlockPresent(pos))
return false; return false;
visited.add(pos);
if (World.isOutsideBuildHeight(pos))
return true;
if (!world.isBlockPresent(pos))
throw AssemblyException.unloadedChunk(pos);
if (isAnchoringBlockAt(pos)) if (isAnchoringBlockAt(pos))
return true; return true;
if (!BlockMovementTraits.movementNecessary(world, pos))
return true;
if (!movementAllowed(world, pos))
return false;
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (!BlockMovementTraits.movementNecessary(state, world, pos))
return true;
if (!movementAllowed(state, world, pos))
throw AssemblyException.unmovableBlock(pos, state);
if (state.getBlock() instanceof AbstractChassisBlock if (state.getBlock() instanceof AbstractChassisBlock
&& !moveChassis(world, pos, forcedDirection, frontier, visited)) && !moveChassis(world, pos, forcedDirection, frontier, visited))
return false; return false;
@ -266,25 +261,11 @@ public abstract class Contraption {
if (AllBlocks.BELT.has(state)) if (AllBlocks.BELT.has(state))
moveBelt(pos, frontier, visited, state); moveBelt(pos, frontier, visited, state);
if (AllBlocks.GANTRY_PINION.has(state)) { if (AllBlocks.GANTRY_PINION.has(state))
BlockPos offset = pos.offset(state.get(GantryPinionBlock.FACING)); moveGantryPinion(world, pos, frontier, visited, state);
if (!visited.contains(offset))
frontier.add(offset);
}
if (AllBlocks.GANTRY_SHAFT.has(state)) if (AllBlocks.GANTRY_SHAFT.has(state))
for (Direction d : Iterate.directions) { moveGantryShaft(world, pos, frontier, visited, state);
BlockPos offset = pos.offset(d);
if (!visited.contains(offset)) {
BlockState offsetState = world.getBlockState(offset);
Direction facing = state.get(GantryShaftBlock.FACING);
if (d.getAxis() == facing.getAxis() && AllBlocks.GANTRY_SHAFT.has(offsetState)
&& offsetState.get(GantryShaftBlock.FACING) == facing)
frontier.add(offset);
else if (AllBlocks.GANTRY_PINION.has(offsetState) && offsetState.get(GantryPinionBlock.FACING) == d)
frontier.add(offset);
}
}
// Bearings potentially create stabilized sub-contraptions // Bearings potentially create stabilized sub-contraptions
if (AllBlocks.MECHANICAL_BEARING.has(state)) if (AllBlocks.MECHANICAL_BEARING.has(state))
@ -302,6 +283,10 @@ public abstract class Contraption {
if (state.getBlock() instanceof MechanicalPistonBlock) if (state.getBlock() instanceof MechanicalPistonBlock)
if (!moveMechanicalPiston(world, pos, frontier, visited, state)) if (!moveMechanicalPiston(world, pos, frontier, visited, state))
return false; return false;
if (isExtensionPole(state))
movePistonPole(world, pos, frontier, visited, state);
if (isPistonHead(state))
movePistonHead(world, pos, frontier, visited, state);
// Doors try to stay whole // Doors try to stay whole
if (state.getBlock() instanceof DoorBlock) { if (state.getBlock() instanceof DoorBlock) {
@ -311,22 +296,22 @@ public abstract class Contraption {
} }
// Cart assemblers attach themselves // Cart assemblers attach themselves
BlockState stateBelow = world.getBlockState(pos.down()); BlockPos posDown = pos.down();
if (!visited.contains(pos.down()) && AllBlocks.CART_ASSEMBLER.has(stateBelow)) BlockState stateBelow = world.getBlockState(posDown);
frontier.add(pos.down()); if (!visited.contains(posDown) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
frontier.add(posDown);
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos); Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
// Slime blocks and super glue drag adjacent blocks if possible // Slime blocks and super glue drag adjacent blocks if possible
boolean isStickyBlock = state.isStickyBlock();
for (Direction offset : Iterate.directions) { for (Direction offset : Iterate.directions) {
BlockPos offsetPos = pos.offset(offset); BlockPos offsetPos = pos.offset(offset);
BlockState blockState = world.getBlockState(offsetPos); BlockState blockState = world.getBlockState(offsetPos);
if (isAnchoringBlockAt(offsetPos)) if (isAnchoringBlockAt(offsetPos))
continue; continue;
if (!movementAllowed(world, offsetPos)) { if (!movementAllowed(blockState, world, offsetPos)) {
if (offset == forcedDirection && isStickyBlock) if (offset == forcedDirection)
return false; throw AssemblyException.unmovableBlock(pos, state);
continue; continue;
} }
@ -335,20 +320,112 @@ public abstract class Contraption {
boolean blockAttachedTowardsFace = boolean blockAttachedTowardsFace =
BlockMovementTraits.isBlockAttachedTowards(world, offsetPos, blockState, offset.getOpposite()); BlockMovementTraits.isBlockAttachedTowards(world, offsetPos, blockState, offset.getOpposite());
boolean brittle = BlockMovementTraits.isBrittle(blockState); boolean brittle = BlockMovementTraits.isBrittle(blockState);
boolean canStick = !brittle && state.canStickTo(blockState) && blockState.canStickTo(state);
if (canStick) {
if (state.getPushReaction() == PushReaction.PUSH_ONLY || blockState.getPushReaction() == PushReaction.PUSH_ONLY) {
canStick = false;
}
if (BlockMovementTraits.notSupportive(state, offset)) {
canStick = false;
}
if (BlockMovementTraits.notSupportive(blockState, offset.getOpposite())) {
canStick = false;
}
}
if (!wasVisited && ((isStickyBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue)) if (!wasVisited && (canStick || blockAttachedTowardsFace || faceHasGlue || (offset == forcedDirection && !BlockMovementTraits.notSupportive(state, forcedDirection))))
frontier.add(offsetPos); frontier.add(offsetPos);
if (faceHasGlue) if (faceHasGlue)
addGlue(superglue.get(offset)); addGlue(superglue.get(offset));
} }
addBlock(pos, capture(world, pos)); addBlock(pos, capture(world, pos));
return blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get(); if (blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get())
return true;
else
throw AssemblyException.structureTooLarge();
} }
private void moveBearing(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, BlockState state) { protected void movePistonHead(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
Direction direction = state.get(MechanicalPistonHeadBlock.FACING);
BlockPos offset = pos.offset(direction.getOpposite());
if (!visited.contains(offset)) {
BlockState blockState = world.getBlockState(offset);
if (isExtensionPole(blockState) && blockState.get(PistonExtensionPoleBlock.FACING)
.getAxis() == direction.getAxis())
frontier.add(offset);
if (blockState.getBlock() instanceof MechanicalPistonBlock) {
Direction pistonFacing = blockState.get(MechanicalPistonBlock.FACING);
if (pistonFacing == direction && blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED)
frontier.add(offset);
}
}
if (state.get(MechanicalPistonHeadBlock.TYPE) == PistonType.STICKY) {
BlockPos attached = pos.offset(direction);
if (!visited.contains(attached))
frontier.add(attached);
}
}
protected void movePistonPole(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
for (Direction d : Iterate.directionsInAxis(state.get(PistonExtensionPoleBlock.FACING)
.getAxis())) {
BlockPos offset = pos.offset(d);
if (!visited.contains(offset)) {
BlockState blockState = world.getBlockState(offset);
if (isExtensionPole(blockState) && blockState.get(PistonExtensionPoleBlock.FACING)
.getAxis() == d.getAxis())
frontier.add(offset);
if (isPistonHead(blockState) && blockState.get(MechanicalPistonHeadBlock.FACING)
.getAxis() == d.getAxis())
frontier.add(offset);
if (blockState.getBlock() instanceof MechanicalPistonBlock) {
Direction pistonFacing = blockState.get(MechanicalPistonBlock.FACING);
if (pistonFacing == d || pistonFacing == d.getOpposite()
&& blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED)
frontier.add(offset);
}
}
}
}
protected void moveGantryPinion(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
BlockPos offset = pos.offset(state.get(GantryPinionBlock.FACING));
if (!visited.contains(offset))
frontier.add(offset);
Axis rotationAxis = ((IRotate) state.getBlock()).getRotationAxis(state);
for (Direction d : Iterate.directionsInAxis(rotationAxis)) {
offset = pos.offset(d);
BlockState offsetState = world.getBlockState(offset);
if (AllBlocks.GANTRY_SHAFT.has(offsetState) && offsetState.get(GantryShaftBlock.FACING)
.getAxis() == d.getAxis())
if (!visited.contains(offset))
frontier.add(offset);
}
}
protected void moveGantryShaft(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
for (Direction d : Iterate.directions) {
BlockPos offset = pos.offset(d);
if (!visited.contains(offset)) {
BlockState offsetState = world.getBlockState(offset);
Direction facing = state.get(GantryShaftBlock.FACING);
if (d.getAxis() == facing.getAxis() && AllBlocks.GANTRY_SHAFT.has(offsetState)
&& offsetState.get(GantryShaftBlock.FACING) == facing)
frontier.add(offset);
else if (AllBlocks.GANTRY_PINION.has(offsetState) && offsetState.get(GantryPinionBlock.FACING) == d)
frontier.add(offset);
}
}
}
private void moveBearing(BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) {
Direction facing = state.get(MechanicalBearingBlock.FACING); Direction facing = state.get(MechanicalBearingBlock.FACING);
if (!canAxisBeStabilized(facing.getAxis())) { if (!canBeStabilized(facing, pos.subtract(anchor))) {
BlockPos offset = pos.offset(facing); BlockPos offset = pos.offset(facing);
if (!visited.contains(offset)) if (!visited.contains(offset))
frontier.add(offset); frontier.add(offset);
@ -357,7 +434,7 @@ public abstract class Contraption {
pendingSubContraptions.add(new BlockFace(pos, facing)); pendingSubContraptions.add(new BlockFace(pos, facing));
} }
private void moveBelt(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, BlockState state) { private void moveBelt(BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) {
BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true); BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true);
BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false); BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false);
if (nextPos != null && !visited.contains(nextPos)) if (nextPos != null && !visited.contains(nextPos))
@ -378,7 +455,7 @@ public abstract class Contraption {
} }
} }
private void movePulley(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited) { private void movePulley(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited) {
int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get(); int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get();
BlockPos ropePos = pos; BlockPos ropePos = pos;
while (limit-- >= 0) { while (limit-- >= 0) {
@ -396,53 +473,31 @@ public abstract class Contraption {
} }
} }
private boolean moveMechanicalPiston(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, private boolean moveMechanicalPiston(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) throws AssemblyException {
BlockState state) {
int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get(); int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get();
Direction direction = state.get(MechanicalPistonBlock.FACING); Direction direction = state.get(MechanicalPistonBlock.FACING);
if (state.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) { PistonState pistonState = state.get(MechanicalPistonBlock.STATE);
BlockPos searchPos = pos; if (pistonState == PistonState.MOVING)
while (limit-- >= 0) {
searchPos = searchPos.offset(direction);
BlockState blockState = world.getBlockState(searchPos);
if (isExtensionPole(blockState)) {
if (blockState.get(PistonExtensionPoleBlock.FACING)
.getAxis() != direction.getAxis())
break;
if (!visited.contains(searchPos))
frontier.add(searchPos);
continue;
}
if (isPistonHead(blockState))
if (!visited.contains(searchPos))
frontier.add(searchPos);
break;
}
if (limit <= -1)
return false; return false;
BlockPos offset = pos.offset(direction.getOpposite());
if (!visited.contains(offset)) {
BlockState poleState = world.getBlockState(offset);
if (AllBlocks.PISTON_EXTENSION_POLE.has(poleState) && poleState.get(PistonExtensionPoleBlock.FACING)
.getAxis() == direction.getAxis())
frontier.add(offset);
} }
BlockPos searchPos = pos; if (pistonState == PistonState.EXTENDED || MechanicalPistonBlock.isStickyPiston(state)) {
while (limit-- >= 0) { offset = pos.offset(direction);
searchPos = searchPos.offset(direction.getOpposite()); if (!visited.contains(offset))
BlockState blockState = world.getBlockState(searchPos); frontier.add(offset);
if (isExtensionPole(blockState)) {
if (blockState.get(PistonExtensionPoleBlock.FACING)
.getAxis() != direction.getAxis())
break;
if (!visited.contains(searchPos))
frontier.add(searchPos);
continue;
}
break;
} }
if (limit <= -1)
return false;
return true; return true;
} }
private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, List<BlockPos> frontier, private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, Queue<BlockPos> frontier,
Set<BlockPos> visited) { Set<BlockPos> visited) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
if (!(te instanceof ChassisTileEntity)) if (!(te instanceof ChassisTileEntity))
@ -527,8 +582,8 @@ public abstract class Contraption {
return globalPos.subtract(anchor); return globalPos.subtract(anchor);
} }
protected boolean movementAllowed(World world, BlockPos pos) { protected boolean movementAllowed(BlockState state, World world, BlockPos pos) {
return BlockMovementTraits.movementAllowed(world, pos); return BlockMovementTraits.movementAllowed(state, world, pos);
} }
protected boolean isAnchoringBlockAt(BlockPos pos) { protected boolean isAnchoringBlockAt(BlockPos pos) {
@ -825,6 +880,8 @@ public abstract class Contraption {
TileEntity tileEntity = world.getTileEntity(targetPos); TileEntity tileEntity = world.getTileEntity(targetPos);
CompoundNBT tag = block.nbt; CompoundNBT tag = block.nbt;
if (tileEntity != null)
tag = NBTProcessors.process(tileEntity, tag, false);
if (tileEntity != null && tag != null) { if (tileEntity != null && tag != null) {
tag.putInt("x", targetPos.getX()); tag.putInt("x", targetPos.getX());
tag.putInt("y", targetPos.getY()); tag.putInt("y", targetPos.getY());
@ -855,9 +912,10 @@ public abstract class Contraption {
} }
} }
for (BlockInfo block : blocks.values()) { for (BlockInfo block : blocks.values()) {
BlockPos targetPos = transform.apply(block.pos);
if (!shouldUpdateAfterMovement(block)) if (!shouldUpdateAfterMovement(block))
continue; continue;
BlockPos targetPos = transform.apply(block.pos);
BlockState state = world.getBlockState(targetPos);
world.markAndNotifyBlock(targetPos, null, block.state, block.state, world.markAndNotifyBlock(targetPos, null, block.state, block.state,
BlockFlags.IS_MOVING | BlockFlags.DEFAULT); BlockFlags.IS_MOVING | BlockFlags.DEFAULT);
} }

View file

@ -0,0 +1,28 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.util.text.TextFormatting;
import java.util.Arrays;
import java.util.List;
public interface IDisplayAssemblyExceptions {
default boolean addExceptionToTooltip(List<String> tooltip) {
AssemblyException e = getLastAssemblyException();
if (e == null)
return false;
if (!tooltip.isEmpty())
tooltip.add("");
tooltip.add(IHaveGoggleInformation.spacing + TextFormatting.GOLD + Lang.translate("gui.assembly.exception"));
String text = e.getFormattedText();
Arrays.stream(text.split("\n")).forEach(l -> tooltip.add(IHaveGoggleInformation.spacing + TextFormatting.GRAY + l));
return true;
}
AssemblyException getLastAssemblyException();
}

View file

@ -5,7 +5,6 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
@ -48,7 +47,7 @@ public abstract class TranslatingContraption extends Contraption {
} }
@Override @Override
protected boolean canAxisBeStabilized(Axis axis) { public boolean canBeStabilized(Direction facing, BlockPos localPos) {
return false; return false;
} }

View file

@ -4,12 +4,12 @@ import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
@ -29,7 +29,7 @@ public class BearingContraption extends Contraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockPos offset = pos.offset(facing); BlockPos offset = pos.offset(facing);
if (!searchMovedStructure(world, offset, null)) if (!searchMovedStructure(world, offset, null))
return false; return false;
@ -84,8 +84,10 @@ public class BearingContraption extends Contraption {
} }
@Override @Override
protected boolean canAxisBeStabilized(Axis axis) { public boolean canBeStabilized(Direction facing, BlockPos localPos) {
return axis == facing.getAxis(); if (facing.getOpposite() == this.facing && BlockPos.ZERO.equals(localPos))
return false;
return facing.getAxis() == this.facing.getAxis();
} }
} }

View file

@ -1,12 +1,10 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing; package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType;
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.AllIcons;
@ -16,7 +14,6 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOpt
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
@ -25,8 +22,11 @@ import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import org.apache.commons.lang3.tuple.Pair;
public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity { import java.util.List;
public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions {
protected ControlledContraptionEntity hourHand; protected ControlledContraptionEntity hourHand;
protected ControlledContraptionEntity minuteHand; protected ControlledContraptionEntity minuteHand;
@ -37,6 +37,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
protected boolean running; protected boolean running;
protected boolean assembleNextTick; protected boolean assembleNextTick;
protected AssemblyException lastException;
protected ScrollOptionBehaviour<ClockHands> operationMode; protected ScrollOptionBehaviour<ClockHands> operationMode;
@ -105,6 +106,11 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
applyRotations(); applyRotations();
} }
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected void applyRotations() { protected void applyRotations() {
BlockState blockState = getBlockState(); BlockState blockState = getBlockState();
Axis axis = Axis.X; Axis axis = Axis.X;
@ -199,8 +205,15 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
Direction direction = getBlockState().get(BlockStateProperties.FACING); Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct // Collect Construct
Pair<ClockworkContraption, ClockworkContraption> contraption = Pair<ClockworkContraption, ClockworkContraption> contraption;
ClockworkContraption.assembleClockworkAt(world, pos, direction); try {
contraption = ClockworkContraption.assembleClockworkAt(world, pos, direction);
lastException = null;
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (contraption == null) if (contraption == null)
return; return;
if (contraption.getLeft() == null) if (contraption.getLeft() == null)
@ -284,6 +297,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
compound.putBoolean("Running", running); compound.putBoolean("Running", running);
compound.putFloat("HourAngle", hourAngle); compound.putFloat("HourAngle", hourAngle);
compound.putFloat("MinuteAngle", minuteAngle); compound.putFloat("MinuteAngle", minuteAngle);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket); super.write(compound, clientPacket);
} }
@ -295,6 +309,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
running = compound.getBoolean("Running"); running = compound.getBoolean("Running");
hourAngle = compound.getFloat("HourAngle"); hourAngle = compound.getFloat("HourAngle");
minuteAngle = compound.getFloat("MinuteAngle"); minuteAngle = compound.getFloat("MinuteAngle");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket); super.read(compound, clientPacket);
if (!clientPacket) if (!clientPacket)

View file

@ -7,14 +7,18 @@ import java.util.Set;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
public class ClockworkContraption extends Contraption { public class ClockworkContraption extends Contraption {
@ -39,7 +43,7 @@ public class ClockworkContraption extends Contraption {
} }
public static Pair<ClockworkContraption, ClockworkContraption> assembleClockworkAt(World world, BlockPos pos, public static Pair<ClockworkContraption, ClockworkContraption> assembleClockworkAt(World world, BlockPos pos,
Direction direction) { Direction direction) throws AssemblyException {
int hourArmBlocks = 0; int hourArmBlocks = 0;
ClockworkContraption hourArm = new ClockworkContraption(); ClockworkContraption hourArm = new ClockworkContraption();
@ -82,21 +86,23 @@ public class ClockworkContraption extends Contraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
return searchMovedStructure(world, pos, facing); return searchMovedStructure(world, pos, facing);
} }
@Override @Override
public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) { public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) throws AssemblyException {
return super.searchMovedStructure(world, pos.offset(direction, offset + 1), null); return super.searchMovedStructure(world, pos.offset(direction, offset + 1), null);
} }
@Override @Override
protected boolean moveBlock(World world, BlockPos pos, Direction direction, List<BlockPos> frontier, protected boolean moveBlock(World world, Direction direction, Queue<BlockPos> frontier,
Set<BlockPos> visited) { Set<BlockPos> visited) throws AssemblyException {
if (ignoreBlocks.contains(pos)) if (ignoreBlocks.contains(frontier.peek())) {
frontier.poll();
return true; return true;
return super.moveBlock(world, pos, direction, frontier, visited); }
return super.moveBlock(world, direction, frontier, visited);
} }
@Override @Override
@ -110,15 +116,17 @@ public class ClockworkContraption extends Contraption {
@Override @Override
public void readNBT(World world, CompoundNBT tag, boolean spawnData) { public void readNBT(World world, CompoundNBT tag, boolean spawnData) {
facing = Direction.byIndex(tag.getInt("Facing")); facing = Direction.byIndex(tag.getInt("facing"));
handType = NBTHelper.readEnum(tag, "HandType", HandType.class); handType = NBTHelper.readEnum(tag, "HandType", HandType.class);
offset = tag.getInt("offset"); offset = tag.getInt("offset");
super.readNBT(world, tag, spawnData); super.readNBT(world, tag, spawnData);
} }
@Override @Override
protected boolean canAxisBeStabilized(Axis axis) { public boolean canBeStabilized(Direction facing, BlockPos localPos) {
return axis == facing.getAxis(); if (BlockPos.ZERO.equals(localPos) || BlockPos.ZERO.equals(localPos.offset(facing)))
return false;
return facing.getAxis() == this.facing.getAxis();
} }
public static enum HandType { public static enum HandType {

View file

@ -1,12 +1,10 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing; package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import java.util.List;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@ -14,7 +12,6 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOpt
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
@ -23,7 +20,11 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity implements IBearingTileEntity { import java.util.List;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions {
protected ScrollOptionBehaviour<RotationMode> movementMode; protected ScrollOptionBehaviour<RotationMode> movementMode;
protected ControlledContraptionEntity movedContraption; protected ControlledContraptionEntity movedContraption;
@ -31,6 +32,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
protected boolean running; protected boolean running;
protected boolean assembleNextTick; protected boolean assembleNextTick;
protected float clientAngleDiff; protected float clientAngleDiff;
protected AssemblyException lastException;
public MechanicalBearingTileEntity(TileEntityType<? extends MechanicalBearingTileEntity> type) { public MechanicalBearingTileEntity(TileEntityType<? extends MechanicalBearingTileEntity> type) {
super(type); super(type);
@ -62,6 +64,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
public void write(CompoundNBT compound, boolean clientPacket) { public void write(CompoundNBT compound, boolean clientPacket) {
compound.putBoolean("Running", running); compound.putBoolean("Running", running);
compound.putFloat("Angle", angle); compound.putFloat("Angle", angle);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket); super.write(compound, clientPacket);
} }
@ -70,6 +73,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
float angleBefore = angle; float angleBefore = angle;
running = compound.getBoolean("Running"); running = compound.getBoolean("Running");
angle = compound.getFloat("Angle"); angle = compound.getFloat("Angle");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket); super.read(compound, clientPacket);
if (!clientPacket) if (!clientPacket)
return; return;
@ -104,6 +108,11 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
return speed; return speed;
} }
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected boolean isWindmill() { protected boolean isWindmill() {
return false; return false;
} }
@ -120,9 +129,17 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
Direction direction = getBlockState().get(FACING); Direction direction = getBlockState().get(FACING);
BearingContraption contraption = new BearingContraption(isWindmill(), direction); BearingContraption contraption = new BearingContraption(isWindmill(), direction);
try {
if (!contraption.assemble(world, pos)) if (!contraption.assemble(world, pos))
return; return;
lastException = null;
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (isWindmill()) if (isWindmill())
AllTriggers.triggerForNearbyPlayers(AllTriggers.WINDMILL, world, pos, 5); AllTriggers.triggerForNearbyPlayers(AllTriggers.WINDMILL, world, pos, 5);
if (contraption.getSailBlocks() >= 16 * 8) if (contraption.getSailBlocks() >= 16 * 8)
@ -281,5 +298,4 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
TooltipHelper.addHint(tooltip, "hint.empty_bearing"); TooltipHelper.addHint(tooltip, "hint.empty_bearing");
return true; return true;
} }
} }

View file

@ -64,27 +64,9 @@ public class SailBlock extends ProperDirectionalBlock {
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
ItemStack heldItem = player.getHeldItem(hand); ItemStack heldItem = player.getHeldItem(hand);
if (AllBlocks.SAIL.isIn(heldItem) || AllBlocks.SAIL_FRAME.isIn(heldItem)) {
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray); if (placementHelper.matchesItem(heldItem))
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, ((BlockItem) heldItem.getItem()).getBlock().getDefaultState(), player, heldItem);
/*BlockState blockState = ((BlockItem) heldItem.getItem()).getBlock()
.getDefaultState()
.with(FACING, state.get(FACING));
BlockPos offsetPos = new BlockPos(offset.getPos());
if (!world.isRemote && world.getBlockState(offsetPos).getMaterial().isReplaceable()) {
world.setBlockState(offsetPos, blockState);
if (!player.isCreative())
heldItem.shrink(1);
}*/
return ActionResultType.SUCCESS;
}
if (heldItem.getItem() instanceof ShearsItem) { if (heldItem.getItem() instanceof ShearsItem) {
if (!world.isRemote) if (!world.isRemote)

View file

@ -45,7 +45,7 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
AbstractContraptionEntity entity = context.contraption.entity; AbstractContraptionEntity entity = context.contraption.entity;
if (entity instanceof ControlledContraptionEntity) { if (entity instanceof ControlledContraptionEntity) {
ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity; ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity;
if (controlledCE.getRotationAxis() == axis) if (context.contraption.canBeStabilized(facing, context.localPos))
offset = -controlledCE.getAngle(renderPartialTicks); offset = -controlledCE.getAngle(renderPartialTicks);
} else if (entity instanceof OrientedContraptionEntity) { } else if (entity instanceof OrientedContraptionEntity) {

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing; package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
@ -20,7 +21,7 @@ public class StabilizedContraption extends Contraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockPos offset = pos.offset(facing); BlockPos offset = pos.offset(facing);
if (!searchMovedStructure(world, offset, null)) if (!searchMovedStructure(world, offset, null))
return false; return false;
@ -55,7 +56,7 @@ public class StabilizedContraption extends Contraption {
} }
@Override @Override
protected boolean canAxisBeStabilized(Axis axis) { public boolean canBeStabilized(Direction facing, BlockPos localPos) {
return false; return false;
} }

View file

@ -7,6 +7,7 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue;
import java.util.Set; import java.util.Set;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
@ -76,12 +77,12 @@ public class ChassisTileEntity extends SmartTileEntity {
} }
public List<ChassisTileEntity> collectChassisGroup() { public List<ChassisTileEntity> collectChassisGroup() {
List<BlockPos> frontier = new ArrayList<>(); Queue<BlockPos> frontier = new LinkedList<>();
List<ChassisTileEntity> collected = new ArrayList<>(); List<ChassisTileEntity> collected = new ArrayList<>();
Set<BlockPos> visited = new HashSet<>(); Set<BlockPos> visited = new HashSet<>();
frontier.add(pos); frontier.add(pos);
while (!frontier.isEmpty()) { while (!frontier.isEmpty()) {
BlockPos current = frontier.remove(0); BlockPos current = frontier.poll();
if (visited.contains(current)) if (visited.contains(current))
continue; continue;
visited.add(current); visited.add(current);
@ -96,7 +97,7 @@ public class ChassisTileEntity extends SmartTileEntity {
return collected; return collected;
} }
public boolean addAttachedChasses(List<BlockPos> frontier, Set<BlockPos> visited) { public boolean addAttachedChasses(Queue<BlockPos> frontier, Set<BlockPos> visited) {
BlockState state = getBlockState(); BlockState state = getBlockState();
if (!(state.getBlock() instanceof AbstractChassisBlock)) if (!(state.getBlock() instanceof AbstractChassisBlock))
return false; return false;
@ -166,7 +167,7 @@ public class ChassisTileEntity extends SmartTileEntity {
break; break;
// Ignore replaceable Blocks and Air-like // Ignore replaceable Blocks and Air-like
if (!BlockMovementTraits.movementNecessary(world, current)) if (!BlockMovementTraits.movementNecessary(currentState, world, current))
break; break;
if (BlockMovementTraits.isBrittle(currentState)) if (BlockMovementTraits.isBrittle(currentState))
break; break;
@ -207,7 +208,7 @@ public class ChassisTileEntity extends SmartTileEntity {
continue; continue;
if (!searchPos.withinDistance(pos, chassisRange + .5f)) if (!searchPos.withinDistance(pos, chassisRange + .5f))
continue; continue;
if (!BlockMovementTraits.movementNecessary(world, searchPos)) if (!BlockMovementTraits.movementNecessary(searchedState, world, searchPos))
continue; continue;
if (BlockMovementTraits.isBrittle(searchedState)) if (BlockMovementTraits.isBrittle(searchedState))
continue; continue;

View file

@ -1,9 +1,9 @@
package com.simibubi.create.content.contraptions.components.structureMovement.gantry; package com.simibubi.create.content.contraptions.components.structureMovement.gantry;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -21,7 +21,7 @@ public class GantryContraption extends TranslatingContraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!searchMovedStructure(world, pos, null)) if (!searchMovedStructure(world, pos, null))
return false; return false;
startMoving(world); startMoving(world);

View file

@ -10,11 +10,15 @@ import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
@ -34,10 +38,15 @@ public class GantryPinionBlock extends DirectionalAxisKineticBlock implements IT
.getAxis() != direction.getAxis(); .getAxis() != direction.getAxis();
} }
@Override
public void updateNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags) {
super.updateNeighbors(stateIn, worldIn, pos, flags);
withTileEntityDo(worldIn, pos, GantryPinionTileEntity::checkValidGantryShaft);
}
@Override @Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
super.onBlockAdded(state, worldIn, pos, oldState, isMoving); super.onBlockAdded(state, worldIn, pos, oldState, isMoving);
withTileEntityDo(worldIn, pos, GantryPinionTileEntity::checkValidGantryShaft);
} }
@Override @Override
@ -50,6 +59,18 @@ public class GantryPinionBlock extends DirectionalAxisKineticBlock implements IT
return context.getFace(); return context.getFace();
} }
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
if (!player.isAllowEdit() || player.isSneaking())
return ActionResultType.PASS;
if (player.getHeldItem(handIn)
.isEmpty()) {
withTileEntityDo(worldIn, pos, te -> te.checkValidGantryShaft());
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS;
}
@Override @Override
public BlockState getStateForPlacement(BlockItemUseContext context) { public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState stateForPlacement = super.getStateForPlacement(context); BlockState stateForPlacement = super.getStateForPlacement(context);

View file

@ -1,23 +1,26 @@
package com.simibubi.create.content.contraptions.components.structureMovement.gantry; package com.simibubi.create.content.contraptions.components.structureMovement.gantry;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock;
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileEntity; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
public class GantryPinionTileEntity extends KineticTileEntity { import static net.minecraft.state.properties.BlockStateProperties.FACING;
public class GantryPinionTileEntity extends KineticTileEntity implements IDisplayAssemblyExceptions {
boolean assembleNextTick; boolean assembleNextTick;
protected AssemblyException lastException;
public GantryPinionTileEntity(TileEntityType<?> typeIn) { public GantryPinionTileEntity(TileEntityType<?> typeIn) {
super(typeIn); super(typeIn);
@ -50,6 +53,11 @@ public class GantryPinionTileEntity extends KineticTileEntity {
} }
} }
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
private void tryAssemble() { private void tryAssemble() {
BlockState blockState = getBlockState(); BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof GantryPinionBlock)) if (!(blockState.getBlock() instanceof GantryPinionBlock))
@ -71,8 +79,17 @@ public class GantryPinionTileEntity extends KineticTileEntity {
if (pinionMovementSpeed < 0) if (pinionMovementSpeed < 0)
movementDirection = movementDirection.getOpposite(); movementDirection = movementDirection.getOpposite();
try {
lastException = null;
if (!contraption.assemble(world, pos)) if (!contraption.assemble(world, pos))
return; return;
sendData();
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (ContraptionCollider.isCollidingWithWorld(world, contraption, pos.offset(movementDirection), if (ContraptionCollider.isCollidingWithWorld(world, contraption, pos.offset(movementDirection),
movementDirection)) movementDirection))
return; return;
@ -85,6 +102,18 @@ public class GantryPinionTileEntity extends KineticTileEntity {
world.addEntity(movedContraption); world.addEntity(movedContraption);
} }
@Override
protected void write(CompoundNBT compound, boolean clientPacket) {
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
}
@Override
protected void read(CompoundNBT compound, boolean clientPacket) {
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
}
@Override @Override
public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff,
boolean connectedViaAxes, boolean connectedViaCogs) { boolean connectedViaAxes, boolean connectedViaCogs) {

View file

@ -180,7 +180,7 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (BlockMovementTraits.isBlockAttachedTowards(world, pos, state, direction)) if (BlockMovementTraits.isBlockAttachedTowards(world, pos, state, direction))
return true; return true;
if (!BlockMovementTraits.movementNecessary(world, pos)) if (!BlockMovementTraits.movementNecessary(state, world, pos))
return false; return false;
if (BlockMovementTraits.notSupportive(state, direction)) if (BlockMovementTraits.notSupportive(state, direction))
return false; return false;

View file

@ -1,13 +1,9 @@
package com.simibubi.create.content.contraptions.components.structureMovement.glue; package com.simibubi.create.content.contraptions.components.structureMovement.glue;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld; import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
@ -15,12 +11,8 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent; import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent;
@ -28,6 +20,10 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@EventBusSubscriber @EventBusSubscriber
public class SuperGlueHandler { public class SuperGlueHandler {
@ -65,6 +61,8 @@ public class SuperGlueHandler {
return; return;
if (AllItems.WRENCH.isIn(placer.getHeldItemMainhand())) if (AllItems.WRENCH.isIn(placer.getHeldItemMainhand()))
return; return;
if (event.getPlacedAgainst() == IPlacementHelper.ID)
return;
double distance = placer.getAttribute(PlayerEntity.REACH_DISTANCE) double distance = placer.getAttribute(PlayerEntity.REACH_DISTANCE)
.getValue(); .getValue();

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mo
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
@ -229,14 +230,28 @@ public class CartAssemblerBlock extends AbstractRailBlock
.isCoupledThroughContraption()) .isCoupledThroughContraption())
return; return;
CartMovementMode mode =
getTileEntityOptional(world, pos).map(te -> CartMovementMode.values()[te.movementMode.value]) Optional<CartAssemblerTileEntity> assembler = getTileEntityOptional(world, pos);
CartMovementMode mode = assembler.map(te -> CartMovementMode.values()[te.movementMode.value])
.orElse(CartMovementMode.ROTATE); .orElse(CartMovementMode.ROTATE);
MountedContraption contraption = new MountedContraption(mode); MountedContraption contraption = new MountedContraption(mode);
try {
if (!contraption.assemble(world, pos)) if (!contraption.assemble(world, pos))
return; return;
assembler.ifPresent(te -> {
te.lastException = null;
te.sendData();
});
} catch (AssemblyException e) {
assembler.ifPresent(te -> {
te.lastException = e;
te.sendData();
});
return;
}
boolean couplingFound = contraption.connectedCart != null; boolean couplingFound = contraption.connectedCart != null;
Optional<Direction> initialOrientation = cart.getMotion() Optional<Direction> initialOrientation = cart.getMotion()
.length() < 1 / 512f ? Optional.empty() : Optional.of(cart.getAdjustedHorizontalFacing()); .length() < 1 / 512f ? Optional.empty() : Optional.of(cart.getAdjustedHorizontalFacing());

View file

@ -1,7 +1,7 @@
package com.simibubi.create.content.contraptions.components.structureMovement.mounted; package com.simibubi.create.content.contraptions.components.structureMovement.mounted;
import java.util.List; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@ -11,17 +11,20 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIco
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.RailShape; import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
public class CartAssemblerTileEntity extends SmartTileEntity { import java.util.List;
public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplayAssemblyExceptions {
private static final int assemblyCooldown = 8; private static final int assemblyCooldown = 8;
protected ScrollOptionBehaviour<CartMovementMode> movementMode; protected ScrollOptionBehaviour<CartMovementMode> movementMode;
private int ticksSinceMinecartUpdate; private int ticksSinceMinecartUpdate;
protected AssemblyException lastException;
public CartAssemblerTileEntity(TileEntityType<? extends CartAssemblerTileEntity> type) { public CartAssemblerTileEntity(TileEntityType<? extends CartAssemblerTileEntity> type) {
super(type); super(type);
@ -44,6 +47,23 @@ public class CartAssemblerTileEntity extends SmartTileEntity {
behaviours.add(movementMode); behaviours.add(movementMode);
} }
@Override
public void write(CompoundNBT compound, boolean clientPacket) {
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
}
@Override
protected void read(CompoundNBT compound, boolean clientPacket) {
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
}
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected ValueBoxTransform getMovementModeSlot() { protected ValueBoxTransform getMovementModeSlot() {
return new CartAssemblerValueBoxTransform(); return new CartAssemblerValueBoxTransform();
} }
@ -103,5 +123,4 @@ public class CartAssemblerTileEntity extends SmartTileEntity {
public boolean isMinecartUpdateValid() { public boolean isMinecartUpdateValid() {
return ticksSinceMinecartUpdate >= assemblyCooldown; return ticksSinceMinecartUpdate >= assemblyCooldown;
} }
} }

View file

@ -2,12 +2,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mo
import static com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.RAIL_SHAPE; import static com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.RAIL_SHAPE;
import java.util.List; import java.util.Queue;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
@ -52,7 +53,7 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (!state.has(RAIL_SHAPE)) if (!state.has(RAIL_SHAPE))
return false; return false;
@ -70,7 +71,7 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) { protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, Queue<BlockPos> frontier) {
frontier.clear(); frontier.clear();
frontier.add(pos.up()); frontier.add(pos.up());
return true; return true;
@ -104,11 +105,10 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
protected boolean movementAllowed(World world, BlockPos pos) { protected boolean movementAllowed(BlockState state, World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos); if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(state))
if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(blockState)) return testSecondaryCartAssembler(world, state, pos);
return testSecondaryCartAssembler(world, blockState, pos); return super.movementAllowed(state, world, pos);
return super.movementAllowed(world, pos);
} }
protected boolean testSecondaryCartAssembler(World world, BlockState state, BlockPos pos) { protected boolean testSecondaryCartAssembler(World world, BlockState state, BlockPos pos) {
@ -149,7 +149,7 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
protected boolean canAxisBeStabilized(Axis axis) { public boolean canBeStabilized(Direction facing, BlockPos localPos) {
return true; return true;
} }

View file

@ -1,24 +1,21 @@
package com.simibubi.create.content.contraptions.components.structureMovement.piston; package com.simibubi.create.content.contraptions.components.structureMovement.piston;
import java.util.List;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.*;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
public abstract class LinearActuatorTileEntity extends KineticTileEntity implements IControlContraption { import java.util.List;
public abstract class LinearActuatorTileEntity extends KineticTileEntity implements IControlContraption, IDisplayAssemblyExceptions {
public float offset; public float offset;
public boolean running; public boolean running;
@ -27,6 +24,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
protected boolean forceMove; protected boolean forceMove;
protected ScrollOptionBehaviour<MovementMode> movementMode; protected ScrollOptionBehaviour<MovementMode> movementMode;
protected boolean waitingForSpeedChange; protected boolean waitingForSpeedChange;
protected AssemblyException lastException;
// Custom position sync // Custom position sync
protected float clientOffsetDiff; protected float clientOffsetDiff;
@ -80,7 +78,13 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
return; return;
} else { } else {
if (getSpeed() != 0) if (getSpeed() != 0)
try {
assemble(); assemble();
lastException = null;
} catch (AssemblyException e) {
lastException = e;
}
sendData();
} }
return; return;
} }
@ -153,6 +157,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
compound.putBoolean("Running", running); compound.putBoolean("Running", running);
compound.putBoolean("Waiting", waitingForSpeedChange); compound.putBoolean("Waiting", waitingForSpeedChange);
compound.putFloat("Offset", offset); compound.putFloat("Offset", offset);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket); super.write(compound, clientPacket);
if (clientPacket && forceMove) { if (clientPacket && forceMove) {
@ -169,6 +174,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
running = compound.getBoolean("Running"); running = compound.getBoolean("Running");
waitingForSpeedChange = compound.getBoolean("Waiting"); waitingForSpeedChange = compound.getBoolean("Waiting");
offset = compound.getFloat("Offset"); offset = compound.getFloat("Offset");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket); super.read(compound, clientPacket);
if (!clientPacket) if (!clientPacket)
@ -183,9 +189,14 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
movedContraption = null; movedContraption = null;
} }
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
public abstract void disassemble(); public abstract void disassemble();
protected abstract void assemble(); protected abstract void assemble() throws AssemblyException;
protected abstract int getExtensionRange(); protected abstract int getExtensionRange();
@ -288,5 +299,4 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
public BlockPos getBlockPosition() { public BlockPos getBlockPosition() {
return pos; return pos;
} }
} }

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pi
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot; import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot;
@ -41,7 +42,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
} }
@Override @Override
public void assemble() { public void assemble() throws AssemblyException {
if (!(world.getBlockState(pos) if (!(world.getBlockState(pos)
.getBlock() instanceof MechanicalPistonBlock)) .getBlock() instanceof MechanicalPistonBlock))
return; return;

View file

@ -1,13 +1,15 @@
package com.simibubi.create.content.contraptions.components.structureMovement.piston; package com.simibubi.create.content.contraptions.components.structureMovement.piston;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.CarpetBlock; import net.minecraft.block.CarpetBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.PistonType; import net.minecraft.state.properties.PistonType;
@ -22,6 +24,7 @@ import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Queue;
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD; import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE; import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE;
@ -50,7 +53,7 @@ public class PistonContraption extends TranslatingContraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!collectExtensions(world, pos, orientation)) if (!collectExtensions(world, pos, orientation))
return false; return false;
int count = blocks.size(); int count = blocks.size();
@ -65,7 +68,7 @@ public class PistonContraption extends TranslatingContraption {
return true; return true;
} }
private boolean collectExtensions(World world, BlockPos pos, Direction direction) { private boolean collectExtensions(World world, BlockPos pos, Direction direction) throws AssemblyException {
List<BlockInfo> poles = new ArrayList<>(); List<BlockInfo> poles = new ArrayList<>();
BlockPos actualStart = pos; BlockPos actualStart = pos;
BlockState nextBlock = world.getBlockState(actualStart.offset(direction)); BlockState nextBlock = world.getBlockState(actualStart.offset(direction));
@ -88,7 +91,7 @@ public class PistonContraption extends TranslatingContraption {
nextBlock = world.getBlockState(actualStart.offset(direction)); nextBlock = world.getBlockState(actualStart.offset(direction));
if (extensionsInFront > MechanicalPistonBlock.maxAllowedPistonPoles()) if (extensionsInFront > MechanicalPistonBlock.maxAllowedPistonPoles())
return false; throw AssemblyException.tooManyPistonPoles();
} }
} }
@ -111,7 +114,7 @@ public class PistonContraption extends TranslatingContraption {
nextBlock = world.getBlockState(end.offset(direction.getOpposite())); nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
if (extensionsInFront + extensionsInBack > MechanicalPistonBlock.maxAllowedPistonPoles()) if (extensionsInFront + extensionsInBack > MechanicalPistonBlock.maxAllowedPistonPoles())
return false; throw AssemblyException.tooManyPistonPoles();
} }
anchor = pos.offset(direction, initialExtensionProgress + 1); anchor = pos.offset(direction, initialExtensionProgress + 1);
@ -123,7 +126,7 @@ public class PistonContraption extends TranslatingContraption {
1, 1); 1, 1);
if (extensionLength == 0) if (extensionLength == 0)
return false; throw AssemblyException.noPistonPoles();
bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0); bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
@ -143,7 +146,7 @@ public class PistonContraption extends TranslatingContraption {
} }
@Override @Override
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) { protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, Queue<BlockPos> frontier) throws AssemblyException {
frontier.clear(); frontier.clear();
boolean sticky = isStickyPiston(world.getBlockState(pos.offset(orientation, -1))); boolean sticky = isStickyPiston(world.getBlockState(pos.offset(orientation, -1)));
boolean retracting = direction != orientation; boolean retracting = direction != orientation;
@ -153,17 +156,24 @@ public class PistonContraption extends TranslatingContraption {
if (offset == 1 && retracting) if (offset == 1 && retracting)
return true; return true;
BlockPos currentPos = pos.offset(orientation, offset + initialExtensionProgress); BlockPos currentPos = pos.offset(orientation, offset + initialExtensionProgress);
if (!world.isBlockPresent(currentPos)) if (retracting && World.isOutsideBuildHeight(currentPos))
return false;
if (!BlockMovementTraits.movementNecessary(world, currentPos))
return true; return true;
if (!world.isBlockPresent(currentPos))
throw AssemblyException.unloadedChunk(currentPos);
BlockState state = world.getBlockState(currentPos); BlockState state = world.getBlockState(currentPos);
if (!BlockMovementTraits.movementNecessary(state, world, currentPos))
return true;
if (BlockMovementTraits.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock)) if (BlockMovementTraits.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock))
return true; return true;
if (isPistonHead(state) && state.get(FACING) == direction.getOpposite()) if (isPistonHead(state) && state.get(FACING) == direction.getOpposite())
return true; return true;
if (!BlockMovementTraits.movementAllowed(world, currentPos)) if (!BlockMovementTraits.movementAllowed(state, world, currentPos))
return retracting; if (retracting)
return true;
else
throw AssemblyException.unmovableBlock(currentPos, state);
if (retracting && state.getPushReaction() == PushReaction.PUSH_ONLY)
return true;
frontier.add(currentPos); frontier.add(currentPos);
if (BlockMovementTraits.notSupportive(state, orientation)) if (BlockMovementTraits.notSupportive(state, orientation))
return true; return true;

View file

@ -7,7 +7,6 @@ import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import com.simibubi.create.foundation.utility.placement.util.PoleHelper; import com.simibubi.create.foundation.utility.placement.util.PoleHelper;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -17,6 +16,7 @@ import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids; import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState; import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
@ -114,26 +114,9 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
ItemStack heldItem = player.getHeldItem(hand); ItemStack heldItem = player.getHeldItem(hand);
if (AllBlocks.PISTON_EXTENSION_POLE.isIn(heldItem) && !player.isSneaking()) {
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray); if (placementHelper.matchesItem(heldItem) && !player.isSneaking())
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, AllBlocks.PISTON_EXTENSION_POLE.getDefaultState(), player, heldItem);
/*BlockPos newPos = new BlockPos(offset.getPos());
if (world.isRemote)
return ActionResultType.SUCCESS;
world.setBlockState(newPos, offset.getTransform().apply(AllBlocks.PISTON_EXTENSION_POLE.getDefaultState()));
if (!player.isCreative())
heldItem.shrink(1);*/
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS; return ActionResultType.PASS;
} }

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.components.structureMovement.pulley; package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
@ -23,7 +24,7 @@ public class PulleyContraption extends TranslatingContraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!searchMovedStructure(world, pos, null)) if (!searchMovedStructure(world, pos, null))
return false; return false;
startMoving(world); startMoving(world);

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.structureMovement.pulley; package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
@ -8,7 +9,6 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pis
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.IWaterLoggable; import net.minecraft.block.IWaterLoggable;
@ -42,12 +42,23 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
} }
@Override @Override
protected void assemble() { protected void assemble() throws AssemblyException {
if (!(world.getBlockState(pos) if (!(world.getBlockState(pos)
.getBlock() instanceof PulleyBlock)) .getBlock() instanceof PulleyBlock))
return; return;
if (speed == 0) if (speed == 0)
return; return;
int maxLength = AllConfigs.SERVER.kinetics.maxRopeLength.get();
int i = 1;
while (i <= maxLength) {
BlockPos ropePos = pos.down(i);
BlockState ropeState = world.getBlockState(ropePos);
if (!AllBlocks.ROPE.has(ropeState) && !AllBlocks.PULLEY_MAGNET.has(ropeState)) {
break;
}
++i;
}
offset = i - 1;
if (offset >= getExtensionRange() && getSpeed() > 0) if (offset >= getExtensionRange() && getSpeed() > 0)
return; return;
if (offset <= 0 && getSpeed() < 0) if (offset <= 0 && getSpeed() < 0)
@ -70,7 +81,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
if (!canAssembleStructure && getSpeed() > 0) if (!canAssembleStructure && getSpeed() > 0)
return; return;
for (int i = ((int) offset); i > 0; i--) { for (i = ((int) offset); i > 0; i--) {
BlockPos offset = pos.down(i); BlockPos offset = pos.down(i);
BlockState oldState = world.getBlockState(offset); BlockState oldState = world.getBlockState(offset);
if (oldState.getBlock() instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED) if (oldState.getBlock() instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED)
@ -165,9 +176,10 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
return; return;
BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1); BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1);
if (!BlockMovementTraits.movementNecessary(world, posBelow)) BlockState state = world.getBlockState(posBelow);
if (!BlockMovementTraits.movementNecessary(state, world, posBelow))
return; return;
if (BlockMovementTraits.isBrittle(world.getBlockState(posBelow))) if (BlockMovementTraits.isBrittle(state))
return; return;
disassemble(); disassemble();

View file

@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Abs
import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
@ -45,22 +46,26 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
@Override @Override
public void handle(Supplier<Context> context) { public void handle(Supplier<Context> context) {
context.get() context.get().enqueueWork(() -> {
.enqueueWork(() -> { ServerPlayerEntity sender = context.get().getSender();
ServerPlayerEntity sender = context.get()
.getSender();
if (sender == null) if (sender == null)
return; return;
Entity entityByID = sender.getServerWorld() Entity entityByID = sender.getServerWorld().getEntityByID(target);
.getEntityByID(target);
if (!(entityByID instanceof AbstractContraptionEntity)) if (!(entityByID instanceof AbstractContraptionEntity))
return; return;
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
double d = sender.getAttribute(PlayerEntity.REACH_DISTANCE).getValue();
if (!sender.canEntityBeSeen(entityByID))
d -= 3;
d *= d;
if (sender.getDistanceSq(entityByID) > d) {
// TODO log?
return;
}
if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand)) if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand))
sender.swingHand(interactionHand, true); sender.swingHand(interactionHand, true);
}); });
context.get() context.get().setPacketHandled(true);
.setPacketHandled(true);
} }
} }

View file

@ -21,9 +21,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.PotionItem; import net.minecraft.item.PotionItem;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.BlockParticleData;
import net.minecraft.particles.IParticleData; import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.potion.PotionUtils; import net.minecraft.potion.PotionUtils;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;

View file

@ -4,6 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.CreateClient; import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
@ -92,6 +93,14 @@ public class GoggleOverlayRenderer {
tooltip.remove(tooltip.size() - 1); tooltip.remove(tooltip.size() - 1);
} }
if (te instanceof IDisplayAssemblyExceptions) {
boolean exceptionAdded = ((IDisplayAssemblyExceptions) te).addExceptionToTooltip(tooltip);
if (exceptionAdded) {
hasHoveringInformation = true;
hoverAddedInformation = true;
}
}
// break early if goggle or hover returned false when present // break early if goggle or hover returned false when present
if ((hasGoggleInformation && !goggleAddedInformation) && (hasHoveringInformation && !hoverAddedInformation)) if ((hasGoggleInformation && !goggleAddedInformation) && (hasHoveringInformation && !hoverAddedInformation))
return; return;

View file

@ -9,13 +9,13 @@ import java.util.List;
public interface IHaveGoggleInformation { public interface IHaveGoggleInformation {
DecimalFormat decimalFormat = new DecimalFormat("#.##"); DecimalFormat decimalFormat = new DecimalFormat("#.##");
public static String spacing = " "; String spacing = " ";
/** /**
* this method will be called when looking at a TileEntity that implemented this interface * this method will be called when looking at a TileEntity that implemented this interface
* *
* @return {{@code true}} if the tooltip creation was successful and should be displayed, * @return {@code true} if the tooltip creation was successful and should be displayed,
* or {{@code false}} if the overlay should not be displayed * or {@code false} if the overlay should not be displayed
* */ * */
default boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking){ default boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking){
return false; return false;

View file

@ -1,8 +1,5 @@
package com.simibubi.create.content.contraptions.relays.advanced; package com.simibubi.create.content.contraptions.relays.advanced;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
@ -10,11 +7,17 @@ import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import com.simibubi.create.foundation.utility.placement.util.PoleHelper;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext; import net.minecraft.item.ItemUseContext;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.EnumProperty; import net.minecraft.state.EnumProperty;
@ -25,8 +28,10 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.IStringSerializable; import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
@ -34,11 +39,17 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class GantryShaftBlock extends DirectionalKineticBlock { public class GantryShaftBlock extends DirectionalKineticBlock {
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class); public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
public enum Part implements IStringSerializable { public enum Part implements IStringSerializable {
START, MIDDLE, END, SINGLE; START, MIDDLE, END, SINGLE;
@ -53,6 +64,17 @@ public class GantryShaftBlock extends DirectionalKineticBlock {
super.fillStateContainer(builder.add(PART, POWERED)); super.fillStateContainer(builder.add(PART, POWERED));
} }
@Override
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
ItemStack heldItem = player.getHeldItem(hand);
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
if (!placementHelper.matchesItem(heldItem))
return ActionResultType.PASS;
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, ((BlockItem) heldItem.getItem()), player, hand, ray);
}
@Override @Override
public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_,
ISelectionContext p_220053_4_) { ISelectionContext p_220053_4_) {
@ -113,17 +135,25 @@ public class GantryShaftBlock extends DirectionalKineticBlock {
@Override @Override
public BlockState getStateForPlacement(BlockItemUseContext context) { public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState state = super.getStateForPlacement(context); BlockState state = super.getStateForPlacement(context);
BlockPos pos = context.getPos();
World world = context.getWorld();
Direction face = context.getFace(); Direction face = context.getFace();
BlockState blockState = context.getWorld()
.getBlockState(context.getPos() BlockState neighbour = world.getBlockState(pos.offset(state.get(FACING)
.offset(face.getOpposite())); .getOpposite()));
if (AllBlocks.GANTRY_SHAFT.has(blockState) && blockState.get(FACING)
.getAxis() == face.getAxis()) { BlockState clickedState =
Direction facing = blockState.get(FACING); AllBlocks.GANTRY_SHAFT.has(neighbour) ? neighbour : world.getBlockState(pos.offset(face.getOpposite()));
if (AllBlocks.GANTRY_SHAFT.has(clickedState) && clickedState.get(FACING)
.getAxis() == state.get(FACING)
.getAxis()) {
Direction facing = clickedState.get(FACING);
state = state.with(FACING, context.getPlayer() == null || !context.getPlayer() state = state.with(FACING, context.getPlayer() == null || !context.getPlayer()
.isSneaking() ? facing : facing.getOpposite()); .isSneaking() ? facing : facing.getOpposite());
} }
return state.with(POWERED, shouldBePowered(state, context.getWorld(), context.getPos()));
return state.with(POWERED, shouldBePowered(state, world, pos));
} }
@Override @Override
@ -179,13 +209,9 @@ public class GantryShaftBlock extends DirectionalKineticBlock {
toUpdate.add(pos); toUpdate.add(pos);
for (BlockPos blockPos : toUpdate) { for (BlockPos blockPos : toUpdate) {
BlockState blockState = worldIn.getBlockState(blockPos); BlockState blockState = worldIn.getBlockState(blockPos);
if (!shouldPower) {
TileEntity te = worldIn.getTileEntity(blockPos); TileEntity te = worldIn.getTileEntity(blockPos);
if (te instanceof KineticTileEntity) if (te instanceof KineticTileEntity)
((KineticTileEntity) te).detachKinetics(); ((KineticTileEntity) te).detachKinetics();
}
if (blockState.getBlock() instanceof GantryShaftBlock) if (blockState.getBlock() instanceof GantryShaftBlock)
worldIn.setBlockState(blockPos, blockState.with(POWERED, shouldPower), 2); worldIn.setBlockState(blockPos, blockState.with(POWERED, shouldPower), 2);
} }
@ -233,4 +259,27 @@ public class GantryShaftBlock extends DirectionalKineticBlock {
&& oldState.get(POWERED) == newState.get(POWERED); && oldState.get(POWERED) == newState.get(POWERED);
} }
public static class PlacementHelper extends PoleHelper<Direction> {
public PlacementHelper() {
super(AllBlocks.GANTRY_SHAFT::has, s -> s.get(FACING)
.getAxis(), FACING);
}
@Override
public Predicate<ItemStack> getItemPredicate() {
return AllBlocks.GANTRY_SHAFT::isIn;
}
@Override
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
PlacementOffset offset = super.getOffset(world, state, pos, ray);
if (!offset.isSuccessful())
return offset;
return PlacementOffset.success(offset.getPos(), offset.getTransform()
.andThen(s -> s.with(POWERED, state.get(POWERED))));
}
}
} }

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.relays.advanced; package com.simibubi.create.content.contraptions.relays.advanced;
import java.util.function.Predicate;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
@ -13,11 +11,11 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset; import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -32,6 +30,8 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.util.function.Predicate;
public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE<SpeedControllerTileEntity> { public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE<SpeedControllerTileEntity> {
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
@ -67,19 +67,10 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockRayTraceResult ray) { BlockRayTraceResult ray) {
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
ItemStack heldItem = player.getHeldItem(hand); ItemStack heldItem = player.getHeldItem(hand);
if (helper.matchesItem(heldItem)) { IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = helper.getOffset(world, state, pos, ray); if (helper.matchesItem(heldItem))
return helper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, AllBlocks.LARGE_COGWHEEL.getDefaultState(), player, heldItem);
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS; return ActionResultType.PASS;
} }

View file

@ -1,10 +1,5 @@
package com.simibubi.create.content.contraptions.relays.elementary; package com.simibubi.create.content.contraptions.relays.elementary;
import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS;
import java.util.List;
import java.util.function.Predicate;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
@ -16,13 +11,13 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset; import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
@ -31,6 +26,11 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.util.List;
import java.util.function.Predicate;
import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS;
public class CogwheelBlockItem extends BlockItem { public class CogwheelBlockItem extends BlockItem {
boolean large; boolean large;
@ -47,49 +47,27 @@ public class CogwheelBlockItem extends BlockItem {
} }
@Override @Override
public ActionResultType tryPlace(BlockItemUseContext context) { public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) {
World world = context.getWorld(); World world = context.getWorld();
BlockPos pos = context.getPos() BlockPos pos = context.getPos();
.offset(context.getFace()
.getOpposite());
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
IPlacementHelper helper = PlacementHelpers.get(placementHelperId); IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
PlayerEntity player = context.getPlayer(); PlayerEntity player = context.getPlayer();
BlockRayTraceResult ray = new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true);
if (helper.matchesState(state)) { if (helper.matchesState(state) && player != null && !player.isSneaking()) {
PlacementOffset offset = helper.getOffset(world, state, pos, return helper.getOffset(world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray);
new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
if (!offset.isReplaceable(world))
return super.tryPlace(context);
offset.placeInWorld(world, this, player, context.getItem());
triggerShiftingGearsAdvancement(world, new BlockPos(offset.getPos()), offset.getTransform()
.apply(getBlock().getDefaultState()), player);
return ActionResultType.SUCCESS;
} }
if (integratedCogHelperId != -1) { if (integratedCogHelperId != -1) {
helper = PlacementHelpers.get(integratedCogHelperId); helper = PlacementHelpers.get(integratedCogHelperId);
if (helper.matchesState(state)) { if (helper.matchesState(state) && player != null && !player.isSneaking()) {
PlacementOffset offset = helper.getOffset(world, state, pos, return helper.getOffset(world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray);
new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
if (!offset.isReplaceable(world))
return super.tryPlace(context);
offset.placeInWorld(world, this, player, context.getItem());
triggerShiftingGearsAdvancement(world, new BlockPos(offset.getPos()), offset.getTransform()
.apply(getBlock().getDefaultState()), player);
return ActionResultType.SUCCESS;
} }
} }
return super.tryPlace(context); return super.onItemUseFirst(stack, context);
} }
@Override @Override

View file

@ -7,7 +7,6 @@ import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import com.simibubi.create.foundation.utility.placement.util.PoleHelper; import com.simibubi.create.foundation.utility.placement.util.PoleHelper;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -77,26 +76,8 @@ public class ShaftBlock extends AbstractShaftBlock {
} }
IPlacementHelper helper = PlacementHelpers.get(placementHelperId); IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
if (helper.getItemPredicate().test(heldItem)) { if (helper.matchesItem(heldItem))
PlacementOffset offset = helper.getOffset(world, state, pos, ray); return helper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, (BlockItem) heldItem.getItem(), player, heldItem);
/*BlockPos newPos = new BlockPos(offset.getPos());
if (world.isRemote)
return ActionResultType.SUCCESS;
Block block = ((BlockItem) heldItem.getItem()).getBlock();
world.setBlockState(newPos, offset.getTransform().apply(block.getDefaultState()));
if (!player.isCreative())
heldItem.shrink(1);*/
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS; return ActionResultType.PASS;
} }

View file

@ -14,7 +14,6 @@ import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.material.Material;
import net.minecraft.block.material.MaterialColor; import net.minecraft.block.material.MaterialColor;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.particles.RedstoneParticleData; import net.minecraft.particles.RedstoneParticleData;
@ -114,6 +113,7 @@ public class GaugeBlock extends DirectionalAxisKineticBlock {
return context.getFace(); return context.getFace();
} }
@Override
protected boolean getAxisAlignmentForPlacement(BlockItemUseContext context) { protected boolean getAxisAlignmentForPlacement(BlockItemUseContext context) {
return context.getPlacementHorizontalFacing().getAxis() != Axis.X; return context.getPlacementHorizontalFacing().getAxis() != Axis.X;
} }
@ -127,8 +127,7 @@ public class GaugeBlock extends DirectionalAxisKineticBlock {
return false; return false;
if (getRotationAxis(state) == Axis.Y && face != state.get(FACING)) if (getRotationAxis(state) == Axis.Y && face != state.get(FACING))
return false; return false;
BlockState blockState = world.getBlockState(pos.offset(face)); if (!Block.shouldSideBeRendered(state, world, pos, face)
if (Block.hasSolidSide(blockState, world, pos, face.getOpposite()) && blockState.getMaterial() != Material.GLASS
&& !(world instanceof WrappedWorld)) && !(world instanceof WrappedWorld))
return false; return false;
return true; return true;

View file

@ -5,6 +5,7 @@ import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
@ -53,15 +54,20 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase {
@Override @Override
public void handle(Supplier<Context> context) { public void handle(Supplier<Context> context) {
context.get() context.get().enqueueWork(() -> {
.enqueueWork(() -> { ServerPlayerEntity sender = context.get().getSender();
ServerPlayerEntity sender = context.get()
.getSender();
if (sender == null) if (sender == null)
return; return;
Entity entityByID = sender.getServerWorld() Entity entityByID = sender.getServerWorld().getEntityByID(target);
.getEntityByID(target);
if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) { if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) {
double d = sender.getAttribute(PlayerEntity.REACH_DISTANCE).getValue();
if (!sender.canEntityBeSeen(entityByID))
d -= 3;
d *= d;
if (sender.getDistanceSq(entityByID) > d) {
// TODO log?
return;
}
if (interactionHand == null) if (interactionHand == null)
sender.attackTargetEntityWithCurrentItem(entityByID); sender.attackTargetEntityWithCurrentItem(entityByID);
else if (specificPoint == null) else if (specificPoint == null)
@ -70,8 +76,7 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase {
entityByID.applyPlayerInteraction(sender, specificPoint, interactionHand); entityByID.applyPlayerInteraction(sender, specificPoint, interactionHand);
} }
}); });
context.get() context.get().setPacketHandled(true);
.setPacketHandled(true);
} }
} }

View file

@ -10,6 +10,7 @@ import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.NBTProcessors;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -115,7 +116,7 @@ public abstract class ZapperItem extends Item {
}); });
applyCooldown(player, item, false); applyCooldown(player, item, false);
} }
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item); return new ActionResult<>(ActionResultType.SUCCESS, item);
} }
boolean mainHand = hand == Hand.MAIN_HAND; boolean mainHand = hand == Hand.MAIN_HAND;
@ -125,7 +126,7 @@ public abstract class ZapperItem extends Item {
// Pass To Offhand // Pass To Offhand
if (mainHand && isSwap && gunInOtherHand) if (mainHand && isSwap && gunInOtherHand)
return new ActionResult<ItemStack>(ActionResultType.FAIL, item); return new ActionResult<>(ActionResultType.FAIL, item);
if (mainHand && !isSwap && gunInOtherHand) if (mainHand && !isSwap && gunInOtherHand)
item.getTag() item.getTag()
.putBoolean("_Swap", true); .putBoolean("_Swap", true);
@ -144,7 +145,7 @@ public abstract class ZapperItem extends Item {
world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS, world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS,
1f, 0.5f); 1f, 0.5f);
player.sendStatusMessage(msg.applyTextStyle(TextFormatting.RED), true); player.sendStatusMessage(msg.applyTextStyle(TextFormatting.RED), true);
return new ActionResult<ItemStack>(ActionResultType.FAIL, item); return new ActionResult<>(ActionResultType.FAIL, item);
} }
BlockState stateToUse = Blocks.AIR.getDefaultState(); BlockState stateToUse = Blocks.AIR.getDefaultState();
@ -169,7 +170,7 @@ public abstract class ZapperItem extends Item {
// No target // No target
if (pos == null || stateReplaced.getBlock() == Blocks.AIR) { if (pos == null || stateReplaced.getBlock() == Blocks.AIR) {
applyCooldown(player, item, gunInOtherHand); applyCooldown(player, item, gunInOtherHand);
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item); return new ActionResult<>(ActionResultType.SUCCESS, item);
} }
// Find exact position of gun barrel for VFX // Find exact position of gun barrel for VFX
@ -183,7 +184,7 @@ public abstract class ZapperItem extends Item {
// Client side // Client side
if (world.isRemote) { if (world.isRemote) {
ZapperRenderHandler.dontAnimateItem(hand); ZapperRenderHandler.dontAnimateItem(hand);
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item); return new ActionResult<>(ActionResultType.SUCCESS, item);
} }
// Server side // Server side
@ -195,7 +196,7 @@ public abstract class ZapperItem extends Item {
new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true)); new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true));
} }
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item); return new ActionResult<>(ActionResultType.SUCCESS, item);
} }
public ITextComponent validateUsage(ItemStack item) { public ITextComponent validateUsage(ItemStack item) {
@ -240,10 +241,13 @@ public abstract class ZapperItem extends Item {
return UseAction.NONE; return UseAction.NONE;
} }
public static void setTileData(World world, BlockPos pos, CompoundNBT data) { public static void setTileData(World world, BlockPos pos, BlockState state, CompoundNBT data, PlayerEntity player) {
if (data != null) { if (data != null && AllBlockTags.SAFE_NBT.matches(state)) {
TileEntity tile = world.getTileEntity(pos); TileEntity tile = world.getTileEntity(pos);
if (tile != null && !tile.onlyOpsCanSetNbt()) { if (tile != null) {
data = NBTProcessors.process(tile, data, !player.isCreative());
if (data == null)
return;
data.putInt("x", pos.getX()); data.putInt("x", pos.getX());
data.putInt("y", pos.getY()); data.putInt("y", pos.getY());
data.putInt("z", pos.getZ()); data.putInt("z", pos.getZ());

View file

@ -135,7 +135,7 @@ public class BlockzapperItem extends ZapperItem {
blocksnapshot.restore(true, false); blocksnapshot.restore(true, false);
return false; return false;
} }
setTileData(world, placed, data); setTileData(world, placed, state, data, player);
if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) {
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;

View file

@ -10,6 +10,7 @@ import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -36,7 +37,7 @@ public enum TerrainTools {
return this != Clear && this != Flatten; return this != Clear && this != Flatten;
} }
public void run(World world, List<BlockPos> targetPositions, Direction facing, @Nullable BlockState paintedState, @Nullable CompoundNBT data) { public void run(World world, List<BlockPos> targetPositions, Direction facing, @Nullable BlockState paintedState, @Nullable CompoundNBT data, PlayerEntity player) {
switch (this) { switch (this) {
case Clear: case Clear:
targetPositions.forEach(p -> world.setBlockState(p, Blocks.AIR.getDefaultState())); targetPositions.forEach(p -> world.setBlockState(p, Blocks.AIR.getDefaultState()));
@ -47,7 +48,7 @@ public enum TerrainTools {
if (!isReplaceable(toReplace)) if (!isReplaceable(toReplace))
return; return;
world.setBlockState(p, paintedState); world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data); ZapperItem.setTileData(world, p, paintedState, data, player);
}); });
break; break;
case Flatten: case Flatten:
@ -67,13 +68,13 @@ public enum TerrainTools {
if (!isReplaceable(toReplace)) if (!isReplaceable(toReplace))
return; return;
world.setBlockState(p, paintedState); world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data); ZapperItem.setTileData(world, p, paintedState, data, player);
}); });
break; break;
case Place: case Place:
targetPositions.forEach(p -> { targetPositions.forEach(p -> {
world.setBlockState(p, paintedState); world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data); ZapperItem.setTileData(world, p, paintedState, data, player);
}); });
break; break;
case Replace: case Replace:
@ -82,7 +83,7 @@ public enum TerrainTools {
if (isReplaceable(toReplace)) if (isReplaceable(toReplace))
return; return;
world.setBlockState(p, paintedState); world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data); ZapperItem.setTileData(world, p, paintedState, data, player);
}); });
break; break;
} }

View file

@ -77,7 +77,7 @@ public class WorldshaperItem extends ZapperItem {
for (BlockPos blockPos : brush.getIncludedPositions()) for (BlockPos blockPos : brush.getIncludedPositions())
affectedPositions.add(targetPos.add(blockPos)); affectedPositions.add(targetPos.add(blockPos));
PlacementPatterns.applyPattern(affectedPositions, stack); PlacementPatterns.applyPattern(affectedPositions, stack);
tool.run(world, affectedPositions, raytrace.getFace(), stateToUse, data); tool.run(world, affectedPositions, raytrace.getFace(), stateToUse, data, player);
return true; return true;
} }

View file

@ -223,6 +223,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
AxisAlignedBB searchArea = AxisAlignedBB searchArea =
new AxisAlignedBB(center.add(0, -bottomPullDistance - 0.5, 0), center.add(0, -0.5, 0)).grow(.45f); new AxisAlignedBB(center.add(0, -bottomPullDistance - 0.5, 0), center.add(0, -0.5, 0)).grow(.45f);
for (ItemEntity itemEntity : world.getEntitiesWithinAABB(ItemEntity.class, searchArea)) { for (ItemEntity itemEntity : world.getEntitiesWithinAABB(ItemEntity.class, searchArea)) {
if (!itemEntity.isAlive())
continue;
ItemStack entityItem = itemEntity.getItem(); ItemStack entityItem = itemEntity.getItem();
if (!canAcceptItem(entityItem)) if (!canAcceptItem(entityItem))
continue; continue;
@ -377,29 +379,6 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
.isHorizontal()) .isHorizontal())
return false; return false;
// BlockState stateBelow = world.getBlockState(pos.down());
// if (stateBelow.getBlock() instanceof FunnelBlock) {
// if (stateBelow.has(BrassFunnelBlock.POWERED) && stateBelow.get(BrassFunnelBlock.POWERED))
// return false;
// if (stateBelow.get(BrassFunnelBlock.FACING) != Direction.UP)
// return false;
// ItemStack remainder = FunnelBlock.tryInsert(world, pos.down(), item, simulate);
// if (!simulate)
// setItem(remainder);
// return remainder.isEmpty();
// }
//
// DirectBeltInputBehaviour directInput =
// TileEntityBehaviour.get(world, pos.down(), DirectBeltInputBehaviour.TYPE);
// if (directInput != null) {
// if (!directInput.canInsertFromSide(Direction.UP))
// return false;
// ItemStack remainder = directInput.handleInsertion(item, Direction.UP, simulate);
// if (!simulate)
// setItem(remainder);
// return remainder.isEmpty();
// }
if (Block.hasSolidSideOnTop(world, pos.down())) if (Block.hasSolidSideOnTop(world, pos.down()))
return false; return false;
@ -418,17 +397,6 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
private boolean handleUpwardOutput(boolean simulate) { private boolean handleUpwardOutput(boolean simulate) {
BlockState stateAbove = world.getBlockState(pos.up()); BlockState stateAbove = world.getBlockState(pos.up());
// if (stateAbove.getBlock() instanceof FunnelBlock) {
// boolean powered = stateAbove.has(BrassFunnelBlock.POWERED) && stateAbove.get(BrassFunnelBlock.POWERED);
// if (!powered && stateAbove.get(BrassFunnelBlock.FACING) == Direction.DOWN) {
// ItemStack remainder = FunnelBlock.tryInsert(world, pos.up(), item, simulate);
// if (remainder.isEmpty()) {
// if (!simulate)
// setItem(remainder);
// return true;
// }
// }
// }
if (world == null) if (world == null)
return false; return false;
@ -499,9 +467,12 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
if (world == null) if (world == null)
return LazyOptional.empty(); return LazyOptional.empty();
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
if (te == null if (te == null)
|| (te instanceof ChuteTileEntity) && (side != Direction.DOWN || !(te instanceof SmartChuteTileEntity)))
return LazyOptional.empty(); return LazyOptional.empty();
if (te instanceof ChuteTileEntity) {
if (side != Direction.DOWN || !(te instanceof SmartChuteTileEntity) || getItemMotion() > 0)
return LazyOptional.empty();
}
return te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite()); return te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite());
} }

View file

@ -21,7 +21,7 @@ public class SmartChuteTileEntity extends ChuteTileEntity {
@Override @Override
protected boolean canAcceptItem(ItemStack stack) { protected boolean canAcceptItem(ItemStack stack) {
return super.canAcceptItem(stack) && canCollectItemsFromBelow(); return super.canAcceptItem(stack) && canCollectItemsFromBelow() && filtering.test(stack);
} }
@Override @Override

View file

@ -48,6 +48,9 @@ public class ArmInteractionPointHandler {
World world = event.getWorld(); World world = event.getWorld();
if (!world.isRemote) if (!world.isRemote)
return; return;
PlayerEntity player = event.getPlayer();
if (player != null && player.isSpectator())
return;
ArmInteractionPoint selected = getSelected(pos); ArmInteractionPoint selected = getSelected(pos);
@ -60,7 +63,6 @@ public class ArmInteractionPointHandler {
} }
selected.cycleMode(); selected.cycleMode();
PlayerEntity player = event.getPlayer();
if (player != null) { if (player != null) {
String key = selected.mode == Mode.DEPOSIT ? "mechanical_arm.deposit_to" : "mechanical_arm.extract_from"; String key = selected.mode == Mode.DEPOSIT ? "mechanical_arm.deposit_to" : "mechanical_arm.extract_from";
TextFormatting colour = selected.mode == Mode.DEPOSIT ? TextFormatting.GOLD : TextFormatting.AQUA; TextFormatting colour = selected.mode == Mode.DEPOSIT ? TextFormatting.GOLD : TextFormatting.AQUA;

View file

@ -2,7 +2,6 @@ package com.simibubi.create.content.logistics.block.redstone;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.logistics.block.funnel.FunnelBlock;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;

View file

@ -0,0 +1,64 @@
package com.simibubi.create.content.schematics;
import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.DynamicOps;
import com.simibubi.create.foundation.utility.NBTProcessors;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.IStructureProcessorType;
import net.minecraft.world.gen.feature.template.PlacementSettings;
import net.minecraft.world.gen.feature.template.StructureProcessor;
import net.minecraft.world.gen.feature.template.Template;
import javax.annotation.Nullable;
import java.util.Optional;
public class SchematicProcessor extends StructureProcessor {
public static final SchematicProcessor INSTANCE = new SchematicProcessor();
@Nullable
@Override
public Template.BlockInfo process(IWorldReader world, BlockPos pos, Template.BlockInfo rawInfo,
Template.BlockInfo info, PlacementSettings settings, @Nullable Template template) {
if (info.nbt != null) {
TileEntity te = info.state.createTileEntity(world);
if (te != null) {
CompoundNBT nbt = NBTProcessors.process(te, info.nbt, false);
if (nbt != info.nbt)
return new Template.BlockInfo(info.pos, info.state, nbt);
}
}
return info;
}
@Nullable
@Override
public Template.EntityInfo processEntity(IWorldReader world, BlockPos pos, Template.EntityInfo rawInfo,
Template.EntityInfo info, PlacementSettings settings, Template template) {
return EntityType.readEntityType(info.nbt).flatMap(type -> {
if (world instanceof World) {
Entity e = type.create((World) world);
if (e != null && !e.ignoreItemEntityData()) {
return Optional.of(info);
}
}
return Optional.empty();
}).orElse(null);
}
@Override
protected IStructureProcessorType getType() {
return dynamic -> INSTANCE;
}
@Override
protected <T> Dynamic<T> serialize0(DynamicOps<T> ops) {
return new Dynamic<>(ops, ops.emptyMap());
}
}

View file

@ -5,7 +5,6 @@ import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -14,8 +13,6 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create; import com.simibubi.create.Create;
@ -91,10 +88,8 @@ public class ServerSchematicLoader {
} }
public void handleNewUpload(ServerPlayerEntity player, String schematic, long size, BlockPos pos) { public void handleNewUpload(ServerPlayerEntity player, String schematic, long size, BlockPos pos) {
String playerPath = getSchematicPath() + "/" + player.getName() String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName();
.getFormattedText(); String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
String playerSchematicId = player.getName()
.getFormattedText() + "/" + schematic;
FilesHelper.createFolderIfMissing(playerPath); FilesHelper.createFolderIfMissing(playerPath);
// Unsupported Format // Unsupported Format
@ -103,6 +98,14 @@ public class ServerSchematicLoader {
return; return;
} }
Path playerSchematicsPath = Paths.get(getSchematicPath(), player.getGameProfile().getName()).toAbsolutePath();
Path uploadPath = playerSchematicsPath.resolve(schematic).normalize();
if (!uploadPath.startsWith(playerSchematicsPath)) {
Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId);
return;
}
// Too big // Too big
if (!validateSchematicSizeOnServer(player, size)) if (!validateSchematicSizeOnServer(player, size))
return; return;
@ -118,11 +121,15 @@ public class ServerSchematicLoader {
return; return;
// Delete schematic with same name // Delete schematic with same name
Files.deleteIfExists(Paths.get(getSchematicPath(), playerSchematicId)); Files.deleteIfExists(uploadPath);
// Too many Schematics // Too many Schematics
Stream<Path> list = Files.list(Paths.get(playerPath)); long count;
if (list.count() >= getConfig().maxSchematics.get()) { try (Stream<Path> list = Files.list(Paths.get(playerPath))) {
count = list.count();
}
if (count >= getConfig().maxSchematics.get()) {
Stream<Path> list2 = Files.list(Paths.get(playerPath)); Stream<Path> list2 = Files.list(Paths.get(playerPath));
Optional<Path> lastFilePath = list2.filter(f -> !Files.isDirectory(f)) Optional<Path> lastFilePath = list2.filter(f -> !Files.isDirectory(f))
.min(Comparator.comparingLong(f -> f.toFile() .min(Comparator.comparingLong(f -> f.toFile()
@ -132,11 +139,9 @@ public class ServerSchematicLoader {
Files.deleteIfExists(lastFilePath.get()); Files.deleteIfExists(lastFilePath.get());
} }
} }
list.close();
// Open Stream // Open Stream
OutputStream writer = OutputStream writer = Files.newOutputStream(uploadPath);
Files.newOutputStream(Paths.get(getSchematicPath(), playerSchematicId), StandardOpenOption.CREATE_NEW);
activeUploads.put(playerSchematicId, new SchematicUploadEntry(writer, size, player.getServerWorld(), pos)); activeUploads.put(playerSchematicId, new SchematicUploadEntry(writer, size, player.getServerWorld(), pos));
// Notify Tile Entity // Notify Tile Entity
@ -165,8 +170,7 @@ public class ServerSchematicLoader {
} }
public void handleWriteRequest(ServerPlayerEntity player, String schematic, byte[] data) { public void handleWriteRequest(ServerPlayerEntity player, String schematic, byte[] data) {
String playerSchematicId = player.getName() String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
.getFormattedText() + "/" + schematic;
if (activeUploads.containsKey(playerSchematicId)) { if (activeUploads.containsKey(playerSchematicId)) {
SchematicUploadEntry entry = activeUploads.get(playerSchematicId); SchematicUploadEntry entry = activeUploads.get(playerSchematicId);
@ -236,8 +240,7 @@ public class ServerSchematicLoader {
} }
public void handleFinishedUpload(ServerPlayerEntity player, String schematic) { public void handleFinishedUpload(ServerPlayerEntity player, String schematic) {
String playerSchematicId = player.getName() String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
.getFormattedText() + "/" + schematic;
if (activeUploads.containsKey(playerSchematicId)) { if (activeUploads.containsKey(playerSchematicId)) {
try { try {
@ -258,8 +261,7 @@ public class ServerSchematicLoader {
if (table == null) if (table == null)
return; return;
table.finishUpload(); table.finishUpload();
table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getName() table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getGameProfile().getName()));
.getFormattedText()));
} catch (IOException e) { } catch (IOException e) {
Create.logger.error("Exception Thrown when finishing Upload: " + playerSchematicId); Create.logger.error("Exception Thrown when finishing Upload: " + playerSchematicId);
@ -270,15 +272,21 @@ public class ServerSchematicLoader {
public void handleInstantSchematic(ServerPlayerEntity player, String schematic, World world, BlockPos pos, public void handleInstantSchematic(ServerPlayerEntity player, String schematic, World world, BlockPos pos,
BlockPos bounds) { BlockPos bounds) {
String playerPath = getSchematicPath() + "/" + player.getName() String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName();
.getFormattedText(); String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
String playerSchematicId = player.getName()
.getFormattedText() + "/" + schematic;
FilesHelper.createFolderIfMissing(playerPath); FilesHelper.createFolderIfMissing(playerPath);
// Unsupported Format // Unsupported Format
if (!schematic.endsWith(".nbt")) { if (!schematic.endsWith(".nbt")) {
Create.logger.warn("Attempted Schematic Upload with non-supported Format: " + playerSchematicId); Create.logger.warn("Attempted Schematic Upload with non-supported Format: {}", playerSchematicId);
return;
}
Path schematicPath = Paths.get(getSchematicPath()).toAbsolutePath();
Path path = schematicPath.resolve(playerSchematicId).normalize();
if (!path.startsWith(schematicPath)) {
Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId);
return; return;
} }
@ -288,12 +296,15 @@ public class ServerSchematicLoader {
try { try {
// Delete schematic with same name // Delete schematic with same name
Path path = Paths.get(getSchematicPath(), playerSchematicId);
Files.deleteIfExists(path); Files.deleteIfExists(path);
// Too many Schematics // Too many Schematics
Stream<Path> list = Files.list(Paths.get(playerPath)); long count;
if (list.count() >= getConfig().maxSchematics.get()) { try (Stream<Path> list = Files.list(Paths.get(playerPath))) {
count = list.count();
}
if (count >= getConfig().maxSchematics.get()) {
Stream<Path> list2 = Files.list(Paths.get(playerPath)); Stream<Path> list2 = Files.list(Paths.get(playerPath));
Optional<Path> lastFilePath = list2.filter(f -> !Files.isDirectory(f)) Optional<Path> lastFilePath = list2.filter(f -> !Files.isDirectory(f))
.min(Comparator.comparingLong(f -> f.toFile() .min(Comparator.comparingLong(f -> f.toFile()
@ -302,24 +313,17 @@ public class ServerSchematicLoader {
if (lastFilePath.isPresent()) if (lastFilePath.isPresent())
Files.deleteIfExists(lastFilePath.get()); Files.deleteIfExists(lastFilePath.get());
} }
list.close();
Template t = new Template(); Template t = new Template();
t.takeBlocksFromWorld(world, pos, bounds, true, Blocks.AIR); t.takeBlocksFromWorld(world, pos, bounds, true, Blocks.AIR);
OutputStream outputStream = null; try (OutputStream outputStream = Files.newOutputStream(path)) {
try {
outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE);
CompoundNBT nbttagcompound = t.writeToNBT(new CompoundNBT()); CompoundNBT nbttagcompound = t.writeToNBT(new CompoundNBT());
CompressedStreamTools.writeCompressed(nbttagcompound, outputStream); CompressedStreamTools.writeCompressed(nbttagcompound, outputStream);
player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getName() player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getGameProfile().getName()));
.getFormattedText()));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
if (outputStream != null)
IOUtils.closeQuietly(outputStream);
} }
} catch (IOException e) { } catch (IOException e) {
Create.logger.error("Exception Thrown in direct Schematic Upload: " + playerSchematicId); Create.logger.error("Exception Thrown in direct Schematic Upload: " + playerSchematicId);

View file

@ -422,8 +422,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
} }
protected void sendOptionUpdate(Option option, boolean set) { protected void sendOptionUpdate(Option option, boolean set) {
AllPackets.channel.sendToServer(ConfigureSchematicannonPacket.setOption(container.getTileEntity() AllPackets.channel.sendToServer(new ConfigureSchematicannonPacket(option, set));
.getPos(), option, set));
} }
} }

View file

@ -27,6 +27,7 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTProcessors;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -466,8 +467,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
CompoundNBT data = null; CompoundNBT data = null;
if (AllBlockTags.SAFE_NBT.matches(blockState)) { if (AllBlockTags.SAFE_NBT.matches(blockState)) {
TileEntity tile = blockReader.getTileEntity(target); TileEntity tile = blockReader.getTileEntity(target);
if (tile != null && !tile.onlyOpsCanSetNbt()) { if (tile != null) {
data = tile.write(new CompoundNBT()); data = tile.write(new CompoundNBT());
data = NBTProcessors.process(tile, data, true);
} }
} }
launchBlock(target, icon, blockState, data); launchBlock(target, icon, blockState, data);

View file

@ -9,7 +9,6 @@ import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.content.schematics.SchematicWorld;
import com.simibubi.create.content.schematics.item.SchematicItem; import com.simibubi.create.content.schematics.item.SchematicItem;
import com.simibubi.create.foundation.utility.Debug;
import com.simibubi.create.foundation.utility.WorldAttached; import com.simibubi.create.foundation.utility.WorldAttached;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -63,10 +62,6 @@ public class SchematicInstances {
PlacementSettings settings = SchematicItem.getSettings(schematic); PlacementSettings settings = SchematicItem.getSettings(schematic);
activeTemplate.addBlocksToWorld(world, anchor, settings); activeTemplate.addBlocksToWorld(world, anchor, settings);
Debug.debugChat("Loading Schematic Instance of " + schematic.getTag()
.getString("File") + ". Total active instances: " + (loadedSchematics.get(wrapped).size() + 1));
return world; return world;
} }

View file

@ -1,17 +1,22 @@
package com.simibubi.create.content.schematics.item; package com.simibubi.create.content.schematics.item;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.List; import java.util.List;
import java.util.zip.GZIPInputStream;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.content.schematics.SchematicProcessor;
import com.simibubi.create.content.schematics.client.SchematicEditScreen; import com.simibubi.create.content.schematics.client.SchematicEditScreen;
import com.simibubi.create.content.schematics.filtering.SchematicInstances; import com.simibubi.create.content.schematics.filtering.SchematicInstances;
import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.ScreenOpener;
@ -25,6 +30,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext; import net.minecraft.item.ItemUseContext;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTSizeTracker;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
@ -46,6 +52,8 @@ import net.minecraftforge.fml.common.thread.SidedThreadGroups;
public class SchematicItem extends Item { public class SchematicItem extends Item {
private static final Logger LOGGER = LogManager.getLogger();
public SchematicItem(Properties properties) { public SchematicItem(Properties properties) {
super(properties.maxStackSize(1)); super(properties.maxStackSize(1));
} }
@ -96,6 +104,7 @@ public class SchematicItem extends Item {
PlacementSettings settings = new PlacementSettings(); PlacementSettings settings = new PlacementSettings();
settings.setRotation(Rotation.valueOf(tag.getString("Rotation"))); settings.setRotation(Rotation.valueOf(tag.getString("Rotation")));
settings.setMirror(Mirror.valueOf(tag.getString("Mirror"))); settings.setMirror(Mirror.valueOf(tag.getString("Mirror")));
settings.addProcessor(SchematicProcessor.INSTANCE);
return settings; return settings;
} }
@ -106,25 +115,30 @@ public class SchematicItem extends Item {
String schematic = blueprint.getTag() String schematic = blueprint.getTag()
.getString("File"); .getString("File");
String filepath = ""; if (!schematic.endsWith(".nbt"))
return t;
if (Thread.currentThread() Path dir;
.getThreadGroup() == SidedThreadGroups.SERVER) Path file;
filepath = "schematics/uploaded/" + owner + "/" + schematic;
else
filepath = "schematics/" + schematic;
InputStream stream = null; if (Thread.currentThread().getThreadGroup() == SidedThreadGroups.SERVER) {
try { dir = Paths.get("schematics", "uploaded").toAbsolutePath();
stream = Files.newInputStream(Paths.get(filepath), StandardOpenOption.READ); file = Paths.get(owner, schematic);
CompoundNBT nbt = CompressedStreamTools.readCompressed(stream); } else {
dir = Paths.get("schematics").toAbsolutePath();
file = Paths.get(schematic);
}
Path path = dir.resolve(file).normalize();
if (!path.startsWith(dir))
return t;
try (DataInputStream stream = new DataInputStream(new BufferedInputStream(
new GZIPInputStream(Files.newInputStream(path, StandardOpenOption.READ))))) {
CompoundNBT nbt = CompressedStreamTools.read(stream, new NBTSizeTracker(0x20000000L));
t.read(nbt); t.read(nbt);
} catch (IOException e) { } catch (IOException e) {
// Player/Server doesnt have schematic saved LOGGER.warn("Failed to read schematic", e);
} finally {
if (stream != null)
IOUtils.closeQuietly(stream);
} }
return t; return t;
@ -142,7 +156,7 @@ public class SchematicItem extends Item {
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
if (!onItemUse(playerIn, handIn)) if (!onItemUse(playerIn, handIn))
return super.onItemRightClick(worldIn, playerIn, handIn); return super.onItemRightClick(worldIn, playerIn, handIn);
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn)); return new ActionResult<>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn));
} }
private boolean onItemUse(PlayerEntity player, Hand hand) { private boolean onItemUse(PlayerEntity player, Hand hand) {

View file

@ -2,15 +2,13 @@ package com.simibubi.create.content.schematics.packet;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.simibubi.create.content.schematics.block.SchematicannonContainer;
import com.simibubi.create.content.schematics.block.SchematicannonTileEntity; import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
import com.simibubi.create.content.schematics.block.SchematicannonTileEntity.State; import com.simibubi.create.content.schematics.block.SchematicannonTileEntity.State;
import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkEvent.Context; import net.minecraftforge.fml.network.NetworkEvent.Context;
public class ConfigureSchematicannonPacket extends SimplePacketBase { public class ConfigureSchematicannonPacket extends SimplePacketBase {
@ -21,45 +19,28 @@ public class ConfigureSchematicannonPacket extends SimplePacketBase {
private Option option; private Option option;
private boolean set; private boolean set;
private BlockPos pos;
public static ConfigureSchematicannonPacket setOption(BlockPos pos, Option option, boolean set) { public ConfigureSchematicannonPacket(Option option, boolean set) {
ConfigureSchematicannonPacket packet = new ConfigureSchematicannonPacket(pos); this.option = option;
packet.option = option; this.set = set;
packet.set = set;
return packet;
}
public ConfigureSchematicannonPacket(BlockPos pos) {
this.pos = pos;
} }
public ConfigureSchematicannonPacket(PacketBuffer buffer) { public ConfigureSchematicannonPacket(PacketBuffer buffer) {
pos = buffer.readBlockPos(); this(buffer.readEnumValue(Option.class), buffer.readBoolean());
option = Option.values()[buffer.readInt()];
set = buffer.readBoolean();
} }
public void write(PacketBuffer buffer) { public void write(PacketBuffer buffer) {
buffer.writeBlockPos(pos); buffer.writeEnumValue(option);
buffer.writeInt(option.ordinal());
buffer.writeBoolean(set); buffer.writeBoolean(set);
} }
public void handle(Supplier<Context> context) { public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> { context.get().enqueueWork(() -> {
ServerPlayerEntity player = context.get().getSender(); ServerPlayerEntity player = context.get().getSender();
if (player == null) if (player == null || !(player.openContainer instanceof SchematicannonContainer))
return;
World world = player.world;
if (world == null || !world.isBlockPresent(pos))
return; return;
TileEntity tileEntity = world.getTileEntity(pos); SchematicannonTileEntity te = ((SchematicannonContainer) player.openContainer).getTileEntity();
if (!(tileEntity instanceof SchematicannonTileEntity))
return;
SchematicannonTileEntity te = (SchematicannonTileEntity) tileEntity;
switch (option) { switch (option) {
case DONT_REPLACE: case DONT_REPLACE:
case REPLACE_ANY: case REPLACE_ANY:

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.schematics.packet;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.simibubi.create.content.schematics.SchematicProcessor;
import com.simibubi.create.content.schematics.item.SchematicItem; import com.simibubi.create.content.schematics.item.SchematicItem;
import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -36,6 +37,8 @@ public class SchematicPlacePacket extends SimplePacketBase {
return; return;
Template t = SchematicItem.loadSchematic(stack); Template t = SchematicItem.loadSchematic(stack);
PlacementSettings settings = SchematicItem.getSettings(stack); PlacementSettings settings = SchematicItem.getSettings(stack);
if (player.canUseCommandBlock())
settings.func_215220_b(SchematicProcessor.INSTANCE); // remove processor
settings.setIgnoreEntities(false); settings.setIgnoreEntities(false);
t.addBlocksToWorld(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")), t.addBlocksToWorld(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")),
settings); settings);

View file

@ -1,6 +1,7 @@
package com.simibubi.create.events; package com.simibubi.create.events;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllFluids; import com.simibubi.create.AllFluids;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.CreateClient; import com.simibubi.create.CreateClient;
@ -124,6 +125,7 @@ public class ClientEvents {
CreateClient.outliner.renderOutlines(ms, buffer); CreateClient.outliner.renderOutlines(ms, buffer);
// CollisionDebugger.render(ms, buffer); // CollisionDebugger.render(ms, buffer);
buffer.draw(); buffer.draw();
RenderSystem.enableCull();
ms.pop(); ms.pop();
} }

View file

@ -1,19 +1,28 @@
package com.simibubi.create.foundation.command; package com.simibubi.create.foundation.command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import net.minecraft.entity.player.PlayerEntity;
import java.util.Collections;
import java.util.function.Predicate;
public class AllCommands { public class AllCommands {
public static Predicate<CommandSource> sourceIsPlayer = (cs) -> cs.getEntity() instanceof PlayerEntity;
public static void register(CommandDispatcher<CommandSource> dispatcher) { public static void register(CommandDispatcher<CommandSource> dispatcher) {
dispatcher.register(Commands.literal("create")
LiteralCommandNode<CommandSource> createRoot = dispatcher.register(Commands.literal("create")
//general purpose //general purpose
.then(ToggleDebugCommand.register()) .then(ToggleDebugCommand.register())
.then(OverlayConfigCommand.register()) .then(OverlayConfigCommand.register())
.then(FixLightingCommand.register()) .then(FixLightingCommand.register())
.then(ReplaceInCommandBlocksCommand.register()) .then(ReplaceInCommandBlocksCommand.register())
.then(HighlightCommand.register())
//dev-util //dev-util
//Comment out for release //Comment out for release
@ -21,5 +30,13 @@ public class AllCommands {
.then(ChunkUtilCommand.register()) .then(ChunkUtilCommand.register())
//.then(KillTPSCommand.register()) //.then(KillTPSCommand.register())
); );
CommandNode<CommandSource> c = dispatcher.findNode(Collections.singleton("c"));
if (c != null)
return;
dispatcher.register(Commands.literal("c")
.redirect(createRoot)
);
} }
} }

View file

@ -0,0 +1,103 @@
package com.simibubi.create.foundation.command;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.foundation.networking.AllPackets;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.command.arguments.BlockPosArgument;
import net.minecraft.command.arguments.EntityArgument;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.*;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.PacketDistributor;
import java.util.Collection;
public class HighlightCommand {
public static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("highlight")
.requires(cs -> cs.hasPermissionLevel(0))
.requires(AllCommands.sourceIsPlayer)
.then(Commands.argument("pos", BlockPosArgument.blockPos())
.requires(AllCommands.sourceIsPlayer)
.executes(ctx -> {
BlockPos pos = BlockPosArgument.getLoadedBlockPos(ctx, "pos");
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()),
new HighlightPacket(pos)
);
return Command.SINGLE_SUCCESS;
})
.then(Commands.argument("players", EntityArgument.players())
.executes(ctx -> {
Collection<ServerPlayerEntity> players = EntityArgument.getPlayers(ctx, "players");
BlockPos pos = BlockPosArgument.getBlockPos(ctx, "pos");
for (ServerPlayerEntity p : players) {
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> p),
new HighlightPacket(pos)
);
}
return players.size();
})
)
)
.executes(ctx -> {
ServerPlayerEntity player = ctx.getSource().asPlayer();
return highlightAssemblyExceptionFor(player, ctx.getSource());
});
}
private static void sendMissMessage(CommandSource source) {
source.sendFeedback(new StringTextComponent("Try looking at a Block that has failed to assemble a Contraption and try again."), true);
}
private static int highlightAssemblyExceptionFor(ServerPlayerEntity player, CommandSource source) {
double distance = player.getAttribute(PlayerEntity.REACH_DISTANCE).getValue();
Vec3d start = player.getEyePosition(1);
Vec3d look = player.getLook(1);
Vec3d end = start.add(look.x * distance, look.y * distance, look.z * distance);
World world = player.world;
BlockRayTraceResult ray = world.rayTraceBlocks(new RayTraceContext(start, end, RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, player));
if (ray.getType() == RayTraceResult.Type.MISS) {
sendMissMessage(source);
return 0;
}
BlockPos pos = ray.getPos();
TileEntity te = world.getTileEntity(pos);
if (!(te instanceof IDisplayAssemblyExceptions)) {
sendMissMessage(source);
return 0;
}
IDisplayAssemblyExceptions display = (IDisplayAssemblyExceptions) te;
AssemblyException exception = display.getLastAssemblyException();
if (exception == null) {
sendMissMessage(source);
return 0;
}
if (!exception.hasPosition()) {
source.sendFeedback(new StringTextComponent("Can't highlight a specific position for this issue"), true);
return Command.SINGLE_SUCCESS;
}
BlockPos p = exception.getPosition();
String command = "/create highlight " + p.getX() + " " + p.getY() + " " + p.getZ();
return player.server.getCommandManager().handleCommand(source, command);
}
}

View file

@ -0,0 +1,55 @@
package com.simibubi.create.foundation.command;
import com.simibubi.create.AllSpecialTextures;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier;
public class HighlightPacket extends SimplePacketBase {
private final BlockPos pos;
public HighlightPacket(BlockPos pos) {
this.pos = pos;
}
public HighlightPacket(PacketBuffer buffer) {
this.pos = BlockPos.fromLong(buffer.readLong());
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeLong(pos.toLong());
}
@Override
public void handle(Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
performHighlight(pos);
}));
ctx.get().setPacketHandled(true);
}
@OnlyIn(Dist.CLIENT)
public static void performHighlight(BlockPos pos) {
if (Minecraft.getInstance().world == null || !Minecraft.getInstance().world.isBlockPresent(pos))
return;
CreateClient.outliner.showAABB("highlightCommand", VoxelShapes.fullCube().getBoundingBox().offset(pos), 200)
.lineWidth(1 / 32f)
.colored(0xEeEeEe)
//.colored(0x243B50)
.withFaceTexture(AllSpecialTextures.SELECTION);
}
}

View file

@ -1,19 +1,11 @@
package com.simibubi.create.foundation.networking; package com.simibubi.create.foundation.networking;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionDisassemblyPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionDisassemblyPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionUpdatePacket; import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionUpdatePacket;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket; import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.*;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.LimbSwingUpdatePacket;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingCreationPacket; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingCreationPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartControllerUpdatePacket; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartControllerUpdatePacket;
import com.simibubi.create.content.contraptions.fluids.actors.FluidSplashPacket; import com.simibubi.create.content.contraptions.fluids.actors.FluidSplashPacket;
@ -25,62 +17,67 @@ import com.simibubi.create.content.logistics.block.mechanicalArm.ArmPlacementPac
import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket; import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket;
import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket; import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket;
import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket; import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket;
import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket; import com.simibubi.create.content.schematics.packet.*;
import com.simibubi.create.content.schematics.packet.InstantSchematicPacket;
import com.simibubi.create.content.schematics.packet.SchematicPlacePacket;
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket;
import com.simibubi.create.foundation.command.ConfigureConfigPacket; import com.simibubi.create.foundation.command.ConfigureConfigPacket;
import com.simibubi.create.foundation.command.HighlightPacket;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkDirection;
import net.minecraftforge.fml.network.NetworkEvent.Context; import net.minecraftforge.fml.network.NetworkEvent.Context;
import net.minecraftforge.fml.network.NetworkRegistry; import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.fml.network.PacketDistributor.TargetPoint; import net.minecraftforge.fml.network.PacketDistributor.TargetPoint;
import net.minecraftforge.fml.network.simple.SimpleChannel; import net.minecraftforge.fml.network.simple.SimpleChannel;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_CLIENT;
import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_SERVER;
public enum AllPackets { public enum AllPackets {
// Client to Server // Client to Server
NBT(NbtPacket.class, NbtPacket::new), NBT(NbtPacket.class, NbtPacket::new, PLAY_TO_SERVER),
CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new), CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new, PLAY_TO_SERVER),
CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new), CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new, PLAY_TO_SERVER),
CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new), CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new, PLAY_TO_SERVER),
CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new), CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new, PLAY_TO_SERVER),
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new), PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new, PLAY_TO_SERVER),
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new), UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER),
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new), CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new, PLAY_TO_SERVER),
CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new), CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new, PLAY_TO_SERVER),
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new), CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new, PLAY_TO_SERVER),
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new), EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new, PLAY_TO_SERVER),
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new), CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new, PLAY_TO_SERVER),
CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new), CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new, PLAY_TO_SERVER),
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new), PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new, PLAY_TO_SERVER),
MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new), MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new, PLAY_TO_SERVER),
INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new), INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new, PLAY_TO_SERVER),
SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new), SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new, PLAY_TO_SERVER),
LEFT_CLICK(LeftClickPacket.class, LeftClickPacket::new), LEFT_CLICK(LeftClickPacket.class, LeftClickPacket::new, PLAY_TO_SERVER),
// Server to Client // Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new), SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new), SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT),
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new), BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT),
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new), CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new), CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new), CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new), GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new), CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new, PLAY_TO_CLIENT),
LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new), LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new, PLAY_TO_CLIENT),
MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new), MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new, PLAY_TO_CLIENT),
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new), FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new), CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new, PLAY_TO_CLIENT),
GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new), GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new, PLAY_TO_CLIENT),
BLOCK_HIGHLIGHT(HighlightPacket.class, HighlightPacket::new, PLAY_TO_CLIENT)
; ;
@ -90,14 +87,14 @@ public enum AllPackets {
private LoadedPacket<?> packet; private LoadedPacket<?> packet;
private <T extends SimplePacketBase> AllPackets(Class<T> type, Function<PacketBuffer, T> factory) { private <T extends SimplePacketBase> AllPackets(Class<T> type, Function<PacketBuffer, T> factory, NetworkDirection direction) {
packet = new LoadedPacket<>(type, factory); packet = new LoadedPacket<>(type, factory, direction);
} }
public static void registerPackets() { public static void registerPackets() {
channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME) channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME)
.serverAcceptedVersions(s -> true) .serverAcceptedVersions(NETWORK_VERSION::equals)
.clientAcceptedVersions(s -> true) .clientAcceptedVersions(NETWORK_VERSION::equals)
.networkProtocolVersion(() -> NETWORK_VERSION) .networkProtocolVersion(() -> NETWORK_VERSION)
.simpleChannel(); .simpleChannel();
for (AllPackets packet : values()) for (AllPackets packet : values())
@ -117,16 +114,18 @@ public enum AllPackets {
Function<PacketBuffer, T> decoder; Function<PacketBuffer, T> decoder;
BiConsumer<T, Supplier<Context>> handler; BiConsumer<T, Supplier<Context>> handler;
Class<T> type; Class<T> type;
NetworkDirection direction;
private LoadedPacket(Class<T> type, Function<PacketBuffer, T> factory) { private LoadedPacket(Class<T> type, Function<PacketBuffer, T> factory, NetworkDirection direction) {
encoder = T::write; encoder = T::write;
decoder = factory; decoder = factory;
handler = T::handle; handler = T::handle;
this.type = type; this.type = type;
this.direction = direction;
} }
private void register() { private void register() {
channel.messageBuilder(type, index++) channel.messageBuilder(type, index++, direction)
.encoder(encoder) .encoder(encoder)
.decoder(decoder) .decoder(decoder)
.consumer(handler) .consumer(handler)

View file

@ -37,7 +37,7 @@ public class EdgeInteractionHandler {
Hand hand = event.getHand(); Hand hand = event.getHand();
ItemStack heldItem = player.getHeldItem(hand); ItemStack heldItem = player.getHeldItem(hand);
if (player.isSneaking()) if (player.isSneaking() || player.isSpectator())
return; return;
EdgeInteractionBehaviour behaviour = TileEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE); EdgeInteractionBehaviour behaviour = TileEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE);
if (behaviour == null) if (behaviour == null)

View file

@ -43,7 +43,7 @@ public class FilteringHandler {
PlayerEntity player = event.getPlayer(); PlayerEntity player = event.getPlayer();
Hand hand = event.getHand(); Hand hand = event.getHand();
if (player.isSneaking()) if (player.isSneaking() || player.isSpectator())
return; return;
FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE); FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
@ -75,12 +75,12 @@ public class FilteringHandler {
if (event.getSide() != LogicalSide.CLIENT) { if (event.getSide() != LogicalSide.CLIENT) {
if (!player.isCreative()) { if (!player.isCreative()) {
if (behaviour.getFilter()
.getItem() instanceof FilterItem)
player.inventory.placeItemBackInInventory(world, behaviour.getFilter());
if (toApply.getItem() instanceof FilterItem) if (toApply.getItem() instanceof FilterItem)
player.getHeldItem(hand) player.getHeldItem(hand)
.shrink(1); .shrink(1);
if (behaviour.getFilter()
.getItem() instanceof FilterItem)
player.inventory.placeItemBackInInventory(world, behaviour.getFilter());
} }
if (toApply.getItem() instanceof FilterItem) if (toApply.getItem() instanceof FilterItem)
toApply.setCount(1); toApply.setCount(1);

View file

@ -28,7 +28,7 @@ public class LinkHandler {
PlayerEntity player = event.getPlayer(); PlayerEntity player = event.getPlayer();
Hand hand = event.getHand(); Hand hand = event.getHand();
if (player.isSneaking()) if (player.isSneaking() || player.isSpectator())
return; return;
LinkBehaviour behaviour = TileEntityBehaviour.get(world, pos, LinkBehaviour.TYPE); LinkBehaviour behaviour = TileEntityBehaviour.get(world, pos, LinkBehaviour.TYPE);

View file

@ -5,7 +5,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
@ -21,17 +20,10 @@ import net.minecraft.nbt.CompoundNBT;
public class FilesHelper { public class FilesHelper {
public static void createFolderIfMissing(String name) { public static void createFolderIfMissing(String name) {
Path path = Paths.get(name);
if (path.getParent() != null)
createFolderIfMissing(path.getParent()
.toString());
if (!Files.isDirectory(path)) {
try { try {
Files.createDirectory(path); Files.createDirectories(Paths.get(name));
} catch (IOException e) { } catch (IOException e) {
Create.logger.warn("Could not create Folder: " + name); Create.logger.warn("Could not create Folder: {}", name);
}
} }
} }

View file

@ -0,0 +1,69 @@
package com.simibubi.create.foundation.utility;
import java.util.HashMap;
import java.util.Map;
import java.util.function.UnaryOperator;
import javax.annotation.Nullable;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.text.ITextComponent;
public final class NBTProcessors {
private static final Map<TileEntityType<?>, UnaryOperator<CompoundNBT>> processors = new HashMap<>();
private static final Map<TileEntityType<?>, UnaryOperator<CompoundNBT>> survivalProcessors = new HashMap<>();
public static synchronized void addProcessor(TileEntityType<?> type, UnaryOperator<CompoundNBT> processor) {
processors.put(type, processor);
}
public static synchronized void addSurvivalProcessor(TileEntityType<?> type, UnaryOperator<CompoundNBT> processor) {
survivalProcessors.put(type, processor);
}
static {
addProcessor(TileEntityType.SIGN, data -> {
for (int i = 0; i < 4; ++i) {
String s = data.getString("Text" + (i + 1));
ITextComponent textcomponent = ITextComponent.Serializer.fromJson(s.isEmpty() ? "\"\"" : s);
if (textcomponent != null && textcomponent.getStyle() != null
&& textcomponent.getStyle().getClickEvent() != null)
return null;
}
return data;
});
addSurvivalProcessor(AllTileEntities.FUNNEL.get(), data -> {
if (data.contains("Filter")) {
ItemStack filter = ItemStack.read(data.getCompound("Filter"));
if (filter.getItem() instanceof FilterItem)
data.remove("Filter");
}
return data;
});
}
private NBTProcessors() {
}
@Nullable
public static CompoundNBT process(TileEntity tileEntity, CompoundNBT compound, boolean survival) {
if (compound == null)
return null;
TileEntityType<?> type = tileEntity.getType();
if (survival && survivalProcessors.containsKey(type))
compound = survivalProcessors.get(type).apply(compound);
if (processors.containsKey(type))
return processors.get(type).apply(compound);
if (tileEntity.onlyOpsCanSetNbt())
return null;
return compound;
}
}

View file

@ -1,24 +1,18 @@
package com.simibubi.create.foundation.utility.outliner; package com.simibubi.create.foundation.utility.outliner;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox;
import com.simibubi.create.foundation.utility.outliner.LineOutline.EndChasingLineOutline; import com.simibubi.create.foundation.utility.outliner.LineOutline.EndChasingLineOutline;
import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams; import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import java.util.*;
public class Outliner { public class Outliner {
final Map<Object, OutlineEntry> outlines; final Map<Object, OutlineEntry> outlines;
@ -57,6 +51,13 @@ public class Outliner {
return entry.outline.getParams(); return entry.outline.getParams();
} }
public OutlineParams showAABB(Object slot, AxisAlignedBB bb, int ttl) {
createAABBOutlineIfMissing(slot, bb);
ChasingAABBOutline outline = getAndRefreshAABB(slot, ttl);
outline.prevBB = outline.targetBB = bb;
return outline.getParams();
}
public OutlineParams showAABB(Object slot, AxisAlignedBB bb) { public OutlineParams showAABB(Object slot, AxisAlignedBB bb) {
createAABBOutlineIfMissing(slot, bb); createAABBOutlineIfMissing(slot, bb);
ChasingAABBOutline outline = getAndRefreshAABB(slot); ChasingAABBOutline outline = getAndRefreshAABB(slot);
@ -112,6 +113,12 @@ public class Outliner {
return (ChasingAABBOutline) entry.getOutline(); return (ChasingAABBOutline) entry.getOutline();
} }
private ChasingAABBOutline getAndRefreshAABB(Object slot, int ttl) {
OutlineEntry entry = outlines.get(slot);
entry.ticksTillRemoval = ttl;
return (ChasingAABBOutline) entry.getOutline();
}
// Maintenance // Maintenance
public Outliner() { public Outliner() {

View file

@ -6,6 +6,7 @@ import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -22,6 +23,11 @@ import java.util.stream.Collectors;
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
public interface IPlacementHelper { public interface IPlacementHelper {
/**
* used as an identifier in SuperGlueHandler to skip blocks placed by helpers
*/
BlockState ID = new BlockState(Blocks.AIR, null);
/** /**
* @return a predicate that gets tested with the items held in the players hands, * @return a predicate that gets tested with the items held in the players hands,
* should return true if this placement helper is active with the given item * should return true if this placement helper is active with the given item
@ -61,24 +67,6 @@ public interface IPlacementHelper {
CreateClient.outliner.showLine("placementArrowB" + center + target, start.add(offset), endB.add(offset)).lineWidth(1/16f); CreateClient.outliner.showLine("placementArrowB" + center + target, start.add(offset), endB.add(offset)).lineWidth(1/16f);
} }
/*@OnlyIn(Dist.CLIENT)
static void renderArrow(Vec3d center, Direction towards, BlockRayTraceResult ray) {
Direction hitFace = ray.getFace();
if (hitFace.getAxis() == towards.getAxis())
return;
//get the two perpendicular directions to form the arrow
Direction[] directions = Arrays.stream(Direction.Axis.values()).filter(axis -> axis != hitFace.getAxis() && axis != towards.getAxis()).map(Iterate::directionsInAxis).findFirst().orElse(new Direction[]{});
Vec3d startOffset = new Vec3d(towards.getDirectionVec());
Vec3d start = center.add(startOffset);
for (Direction dir : directions) {
Vec3d arrowOffset = new Vec3d(dir.getDirectionVec()).scale(.25);
Vec3d target = center.add(startOffset.scale(0.75)).add(arrowOffset);
CreateClient.outliner.showLine("placementArrow" + towards + dir, start, target).lineWidth(1/16f);
}
}*/
static List<Direction> orderedByDistanceOnlyAxis(BlockPos pos, Vec3d hit, Direction.Axis axis) { static List<Direction> orderedByDistanceOnlyAxis(BlockPos pos, Vec3d hit, Direction.Axis axis) {
return orderedByDistance(pos, hit, dir -> dir.getAxis() == axis); return orderedByDistance(pos, hit, dir -> dir.getAxis() == axis);
} }

View file

@ -1,15 +1,26 @@
package com.simibubi.create.foundation.utility.placement; package com.simibubi.create.foundation.utility.placement;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.SoundType;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.fluid.Fluids; import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState; import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.stats.Stats;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.world.BlockEvent;
import java.util.function.Function; import java.util.function.Function;
@ -56,24 +67,48 @@ public class PlacementOffset {
return world.getBlockState(new BlockPos(pos)).getMaterial().isReplaceable(); return world.getBlockState(new BlockPos(pos)).getMaterial().isReplaceable();
} }
public void placeInWorld(World world, BlockItem blockItem, PlayerEntity player, ItemStack item) { public ActionResultType placeInWorld(World world, BlockItem blockItem, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
placeInWorld(world, blockItem.getBlock().getDefaultState(), player, item);
}
public void placeInWorld(World world, BlockState defaultState, PlayerEntity player, ItemStack item) { ItemUseContext context = new ItemUseContext(player, hand, ray);
if (world.isRemote)
return;
BlockPos newPos = new BlockPos(pos); BlockPos newPos = new BlockPos(pos);
BlockState state = stateTransform.apply(defaultState);
if (!world.isBlockModifiable(player, newPos))
return ActionResultType.PASS;
if (!isReplaceable(world))
return ActionResultType.PASS;
BlockState state = stateTransform.apply(blockItem.getBlock().getDefaultState());
if (state.has(BlockStateProperties.WATERLOGGED)) { if (state.has(BlockStateProperties.WATERLOGGED)) {
IFluidState fluidState = world.getFluidState(newPos); IFluidState fluidState = world.getFluidState(newPos);
state = state.with(BlockStateProperties.WATERLOGGED, fluidState.getFluid() == Fluids.WATER); state = state.with(BlockStateProperties.WATERLOGGED, fluidState.getFluid() == Fluids.WATER);
} }
BlockSnapshot snapshot = BlockSnapshot.getBlockSnapshot(world, newPos);
world.setBlockState(newPos, state); world.setBlockState(newPos, state);
BlockEvent.EntityPlaceEvent event = new BlockEvent.EntityPlaceEvent(snapshot, IPlacementHelper.ID, player);
if (MinecraftForge.EVENT_BUS.post(event)) {
snapshot.restore(true, false);
return ActionResultType.FAIL;
}
BlockState newState = world.getBlockState(newPos);
SoundType soundtype = newState.getSoundType(world, newPos, player);
world.playSound(player, newPos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
player.addStat(Stats.ITEM_USED.get(blockItem));
if (world.isRemote)
return ActionResultType.SUCCESS;
if (player instanceof ServerPlayerEntity)
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, newPos, context.getItem());
if (!player.isCreative()) if (!player.isCreative())
item.shrink(1); context.getItem().shrink(1);
return ActionResultType.SUCCESS;
} }
} }

View file

@ -173,6 +173,13 @@
"create.gui.goggles.at_current_speed": "at current speed", "create.gui.goggles.at_current_speed": "at current speed",
"create.gui.goggles.pole_length": "Pole Length:", "create.gui.goggles.pole_length": "Pole Length:",
"create.gui.assembly.exception": "This Contraption was unable to assemble:",
"create.gui.assembly.exception.unmovableBlock": "Unmovable Block (%4$s) at [%1$s %2$s %3$s]",
"create.gui.assembly.exception.chunkNotLoaded": "The Block at [%1$s %2$s %3$s] was not in a loaded chunk",
"create.gui.assembly.exception.structureTooLarge": "There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.tooManyPistonPoles": "There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.noPistonPoles": "The Piston is missing some extension Poles",
"create.gui.gauge.info_header": "Gauge Information:", "create.gui.gauge.info_header": "Gauge Information:",
"create.gui.speedometer.title": "Rotation Speed", "create.gui.speedometer.title": "Rotation Speed",
"create.gui.stressometer.title": "Network Stress", "create.gui.stressometer.title": "Network Stress",

View file

@ -1,5 +1,4 @@
{ {
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
"block.create.acacia_window": "Fenêtre en acacia", "block.create.acacia_window": "Fenêtre en acacia",
@ -8,49 +7,88 @@
"block.create.adjustable_pulse_repeater": "Répéteur d'impulsions réglable", "block.create.adjustable_pulse_repeater": "Répéteur d'impulsions réglable",
"block.create.adjustable_repeater": "Répéteur réglable", "block.create.adjustable_repeater": "Répéteur réglable",
"block.create.analog_lever": "Levier analogique", "block.create.analog_lever": "Levier analogique",
"block.create.andesite_belt_funnel": "Entonnoir en andésite pour tapis roulant",
"block.create.andesite_bricks": "Briques d'andésite", "block.create.andesite_bricks": "Briques d'andésite",
"block.create.andesite_bricks_slab": "Dalle en briques d'andésite", "block.create.andesite_bricks_slab": "Dalle en briques d'andésite",
"block.create.andesite_bricks_stairs": "Escalier en briques d'andésite", "block.create.andesite_bricks_stairs": "Escalier en briques d'andésite",
"block.create.andesite_bricks_wall": "Mur en briques d'andésite", "block.create.andesite_bricks_wall": "Mur en briques d'andésite",
"block.create.andesite_casing": "Boîtier en andésite", "block.create.andesite_casing": "Revêtement en andésite",
"block.create.andesite_cobblestone": "Pierres d'andésite", "block.create.andesite_cobblestone": "Pierres d'andésite",
"block.create.andesite_cobblestone_slab": "Dalles en pierres d'andésite", "block.create.andesite_cobblestone_slab": "Dalles en pierres d'andésite",
"block.create.andesite_cobblestone_stairs": "Escaliers en pierres d'andésite", "block.create.andesite_cobblestone_stairs": "Escaliers en pierres d'andésite",
"block.create.andesite_cobblestone_wall": "Mur en pierres d'andésite", "block.create.andesite_cobblestone_wall": "Mur en pierres d'andésite",
"block.create.andesite_encased_shaft": "Arbre mécanique dans un revêtement en andésite", "block.create.andesite_encased_shaft": "Rotor dans un revêtement en andésite",
"block.create.andesite_funnel": "Entonnoir en andésite", "block.create.andesite_funnel": "Entonnoir en andésite",
"block.create.andesite_pillar": "Pilier en andésite", "block.create.andesite_pillar": "Pilier en andésite",
"block.create.andesite_tunnel": "Tunnel en andésite", "block.create.andesite_tunnel": "Tunnel en andésite",
"block.create.basin": "Bassin", "block.create.basin": "Bassin",
"block.create.belt": "Tapis roulant", "block.create.belt": "Tapis roulant",
"block.create.birch_window": "Fenêtre en bouleau", "block.create.birch_window": "Fenêtre en bouleau",
"block.create.brass_casing": "Boîtier en laiton", "block.create.birch_window_pane": "Vitre en bouleau",
"block.create.black_sail": "Voile noire",
"block.create.black_seat": "Siège noir",
"block.create.black_valve_handle": "Vanne noire",
"block.create.blaze_burner": "Brûleur à blaze",
"block.create.blue_sail": "Voile bleue",
"block.create.blue_seat": "Siège bleu",
"block.create.blue_valve_handle": "Vanne bleue",
"block.create.brass_belt_funnel": "Entonnoir en laiton pour tapis roulant",
"block.create.brass_block": "Bloc de laiton",
"block.create.brass_casing": "Revêtement en laiton",
"block.create.brass_encased_shaft": "Rotor dans un revêtement en laiton",
"block.create.brass_funnel": "Entonnoir en laiton",
"block.create.brass_tunnel": "Tunnel en laiton",
"block.create.brown_sail": "Voile brune",
"block.create.brown_seat": "Siège brun",
"block.create.brown_valve_handle": "Vanne brune",
"block.create.cart_assembler": "Assembleur de wagon", "block.create.cart_assembler": "Assembleur de wagon",
"block.create.chiseled_dark_scoria": "Scoria sombre taillé",
"block.create.chiseled_dolomite": "Dolomite taillée",
"block.create.chiseled_gabbro": "Gabbro taillé",
"block.create.chiseled_limestone": "Calcaire taillé",
"block.create.chiseled_scoria": "Scoria taillé",
"block.create.chiseled_weathered_limestone": "Calcaire altéré taillé",
"block.create.chocolate": "Chocolat",
"block.create.chute": "Glissière",
"block.create.clockwork_bearing": "Roulement mécanique horloger", "block.create.clockwork_bearing": "Roulement mécanique horloger",
"block.create.clutch": "Embrayage", "block.create.clutch": "Embrayage",
"block.create.cogwheel": "Roue dentée", "block.create.cogwheel": "Roue dentée",
"block.create.content_observer": "Observateur de contenu",
"block.create.controller_rail": "Rails controlleurs",
"block.create.copper_block": "Bloc de cuivre", "block.create.copper_block": "Bloc de cuivre",
"block.create.copper_casing": "Boîtier en cuivre", "block.create.copper_casing": "Revêtement en cuivre",
"block.create.copper_ore": "Minerai de cuivre", "block.create.copper_ore": "Minerai de cuivre",
"block.create.copper_shingles": "Bardeaux de cuivre", "block.create.copper_shingles": "Bardeaux de cuivre",
"block.create.copper_tiles": "Tuiles en cuivre",
"block.create.copper_valve_handle": "Vanne en cuivre",
"block.create.creative_crate": "Créateur de schémacanon", "block.create.creative_crate": "Créateur de schémacanon",
"block.create.creative_fluid_tank": "Réservoir créatif",
"block.create.creative_motor": "Moteur", "block.create.creative_motor": "Moteur",
"block.create.crushing_wheel": "Roue de concassage", "block.create.crushing_wheel": "Roue de concassage",
"block.create.crushing_wheel_controller": "Contrôleur de roue de concassage",
"block.create.cuckoo_clock": "Horloge à coucou", "block.create.cuckoo_clock": "Horloge à coucou",
"block.create.cyan_sail": "Voile cyan",
"block.create.cyan_seat": "Siège cyan",
"block.create.cyan_valve_handle": "Vanne cyan",
"block.create.dark_oak_window": "fenêtre en chêne sombre",
"block.create.dark_oak_window_pane": "Vitre en chêne sombre",
"block.create.dark_scoria": "Scorie sombre", "block.create.dark_scoria": "Scorie sombre",
"block.create.dark_scoria_bricks": "Briques de scorie sombre", "block.create.dark_scoria_bricks": "Briques de scorie sombre",
"block.create.dark_scoria_bricks_slab": "Dalles de briques de scorie sombre", "block.create.dark_scoria_bricks_slab": "Dalles de briques de scorie sombre",
"block.create.dark_scoria_bricks_stairs": "Escaliers de briques de scorie sombre", "block.create.dark_scoria_bricks_stairs": "Escaliers de briques de scorie sombre",
"block.create.dark_scoria_bricks_wall": "Muret de briques de scorie sombre", "block.create.dark_scoria_bricks_wall": "Muret de briques de scorie sombre",
"block.create.dark_scoria_cobblestone": "Pierres de scorie sombre",
"block.create.deployer": "Déployeur", "block.create.deployer": "Déployeur",
"block.create.depot": "Dépot",
"block.create.diorite_bricks": "Briques de diorite", "block.create.diorite_bricks": "Briques de diorite",
"block.create.dolomite": "Dolomie", "block.create.dolomite": "Dolomite",
"block.create.dolomite_bricks": "Briques de dolomie", "block.create.dolomite_bricks": "Briques de dolomite",
"block.create.dolomite_bricks_slab": "Dalle de briques de dolomie", "block.create.dolomite_bricks_slab": "Dalle de briques de dolomite",
"block.create.dolomite_bricks_stairs": "Escaliers de briques de dolomie", "block.create.dolomite_bricks_stairs": "Escaliers de briques de dolomite",
"block.create.dolomite_bricks_wall": "Muret de briques de dolomie", "block.create.dolomite_bricks_wall": "Muret de briques de dolomite",
"block.create.dolomite_pillar": "Pillier de dolomie", "block.create.dolomite_pillar": "Pillier de dolomite",
"block.create.encased_fan": "Ventilateur enfermé", "block.create.encased_chain_drive": "Chaine de transmission",
"block.create.encased_fan": "Ventilateur enchâssé",
"block.create.flywheel": "Volant d'inertie", "block.create.flywheel": "Volant d'inertie",
"block.create.framed_glass": "Grande fenêtre en verre", "block.create.framed_glass": "Grande fenêtre en verre",
"block.create.framed_glass_pane": "Grande vitre encadrée", "block.create.framed_glass_pane": "Grande vitre encadrée",
@ -85,23 +123,23 @@
"block.create.mechanical_saw": "Scie mécanique", "block.create.mechanical_saw": "Scie mécanique",
"block.create.natural_scoria": "Scorie naturelle", "block.create.natural_scoria": "Scorie naturelle",
"block.create.nozzle": "Buse", "block.create.nozzle": "Buse",
"block.create.piston_extension_pole": "Pôle d'extension de piston", "block.create.piston_extension_pole": "Barre d'extension de piston",
"block.create.polished_dark_scoria": "Scorie sombre polie", "block.create.polished_dark_scoria": "Scorie sombre polie",
"block.create.polished_dolomite": "Dolomie polie", "block.create.polished_dolomite": "Dolomite polie",
"block.create.polished_gabbro": "Gabbro poli", "block.create.polished_gabbro": "Gabbro poli",
"block.create.polished_limestone": "Calcaire poli", "block.create.polished_limestone": "Calcaire poli",
"block.create.polished_limestone_slab": "Dalle de calcaire polie", "block.create.polished_limestone_slab": "Dalle de calcaire polie",
"block.create.polished_scoria": "Scorie polie", "block.create.polished_scoria": "Scorie polie",
"block.create.polished_scoria_slab": "Dalle de scorie polie", "block.create.polished_scoria_slab": "Dalle de scorie polie",
"block.create.polished_weathered_limestone": "Calcaire patinées polies", "block.create.polished_weathered_limestone": "Calcaire altéré polies",
"block.create.polished_weathered_limestone_slab": "Dalle de calcaire patinées", "block.create.polished_weathered_limestone_slab": "Dalle de calcaire altéré",
"block.create.portable_storage_interface": "Interface de stockage portable", "block.create.portable_storage_interface": "Interface de stockage portable",
"block.create.powered_latch": "Verrou alimenté", "block.create.powered_latch": "Verrou alimenté",
"block.create.powered_toggle_latch": "Verrou alimenté à bascule", "block.create.powered_toggle_latch": "Verrou alimenté à bascule",
"block.create.pulley_magnet": "Aimant de poulie", "block.create.pulley_magnet": "Aimant de poulie",
"block.create.pulse_repeater": "Répéteur d'impulsions", "block.create.pulse_repeater": "Répéteur d'impulsions",
"block.create.radial_chassis": "Châssis radial", "block.create.radial_chassis": "Châssis radial",
"block.create.redstone_contact": "redstone_contact Redstone", "block.create.redstone_contact": "Contact de redstone",
"block.create.redstone_link": "Liaison Redstone", "block.create.redstone_link": "Liaison Redstone",
"block.create.rope": "Corde", "block.create.rope": "Corde",
"block.create.rope_pulley": "Poulie à corde", "block.create.rope_pulley": "Poulie à corde",
@ -112,7 +150,7 @@
"block.create.scoria_bricks": "Briques de scorie", "block.create.scoria_bricks": "Briques de scorie",
"block.create.scoria_pillar": "Pillier de scorie", "block.create.scoria_pillar": "Pillier de scorie",
"block.create.sequenced_gearshift": "Décaleur de rotation séquencé", "block.create.sequenced_gearshift": "Décaleur de rotation séquencé",
"block.create.shaft": "Arbre mécanique", "block.create.shaft": "Rotor",
"block.create.speedometer": "Compteur de vitesse", "block.create.speedometer": "Compteur de vitesse",
"block.create.sticky_mechanical_piston": "Piston mécanique collant", "block.create.sticky_mechanical_piston": "Piston mécanique collant",
"block.create.stockpile_switch": "Détecteur de stockage", "block.create.stockpile_switch": "Détecteur de stockage",
@ -123,12 +161,12 @@
"block.create.vertical_framed_glass": "Fenêtre en verre verticale", "block.create.vertical_framed_glass": "Fenêtre en verre verticale",
"block.create.vertical_framed_glass_pane": "Vitre encadrée verticale", "block.create.vertical_framed_glass_pane": "Vitre encadrée verticale",
"block.create.water_wheel": "Roue à eau", "block.create.water_wheel": "Roue à eau",
"block.create.weathered_limestone": "Calcaire patinées", "block.create.weathered_limestone": "Calcaire altéré",
"block.create.weathered_limestone_bricks": "Briques de calcaire patinées", "block.create.weathered_limestone_bricks": "Briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_slab": "Dalle de briques de calcaire patinées", "block.create.weathered_limestone_bricks_slab": "Dalle de briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_stairs": "Escaliers de briques de calcaire patinées", "block.create.weathered_limestone_bricks_stairs": "Escaliers de briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_wall": "Muret de briques de calcaire patinées", "block.create.weathered_limestone_bricks_wall": "Muret de briques de Calcaire altéré",
"block.create.weathered_limestone_pillar": "Pillier de calcaire patinées", "block.create.weathered_limestone_pillar": "Pillier de Calcaire altéré",
"block.create.zinc_block": "Bloc de zinc", "block.create.zinc_block": "Bloc de zinc",
"block.create.zinc_ore": "Minerai de zinc", "block.create.zinc_ore": "Minerai de zinc",
@ -203,7 +241,7 @@
"item.create.schematic_and_quill": "Schéma et plume", "item.create.schematic_and_quill": "Schéma et plume",
"item.create.shadow_steel": "Acier sombre", "item.create.shadow_steel": "Acier sombre",
"item.create.super_glue": "Colle extra-forte", "item.create.super_glue": "Colle extra-forte",
"item.create.tree_fertilizer": "Engrais pour arbre", "item.create.tree_fertilizer": "Engrais pour arbres",
"item.create.vertical_gearbox": "Boîte de transfert verticale", "item.create.vertical_gearbox": "Boîte de transfert verticale",
"item.create.wand_of_symmetry": "Bâton de symétrie", "item.create.wand_of_symmetry": "Bâton de symétrie",
"item.create.wheat_flour": "Farine", "item.create.wheat_flour": "Farine",
@ -220,7 +258,7 @@
"advancement.create.andesite_alloy.desc": "Certains matériaux de Create ont des noms bizzares; l'alliage d'andésite est l'un d'entre eux.", "advancement.create.andesite_alloy.desc": "Certains matériaux de Create ont des noms bizzares; l'alliage d'andésite est l'un d'entre eux.",
"advancement.create.its_alive": "Ça bouge!", "advancement.create.its_alive": "Ça bouge!",
"advancement.create.its_alive.desc": "Regardez vos bremiers composants tourner.", "advancement.create.its_alive.desc": "Regardez vos bremiers composants tourner.",
"advancement.create.shifting_gears": "Arbre de transmission", "advancement.create.shifting_gears": "rotor de transmission",
"advancement.create.shifting_gears.desc": "Connectez une roue dentée à une grande roue dentée afin de changer la vitesse de votre engin", "advancement.create.shifting_gears.desc": "Connectez une roue dentée à une grande roue dentée afin de changer la vitesse de votre engin",
"advancement.create.overstressed": "Surtension", "advancement.create.overstressed": "Surtension",
"advancement.create.overstressed.desc": "Testez d'abord les limites de la force mécanique", "advancement.create.overstressed.desc": "Testez d'abord les limites de la force mécanique",
@ -237,7 +275,7 @@
"itemGroup.create.base": "Create", "itemGroup.create.base": "Create",
"itemGroup.create.palettes": "Create Palettes", "itemGroup.create.palettes": "Create Palettes",
"death.attack.create.crush": "%1$s nanana a été traitée par une roue de concassage", "death.attack.create.crush": "%1$s a été concassé.e",
"death.attack.create.fan_fire": "%1$s a été brûlé à mort par l'air chaud", "death.attack.create.fan_fire": "%1$s a été brûlé à mort par l'air chaud",
"death.attack.create.fan_lava": "%1$s a été brûlé à mort par un ventilateur de lave", "death.attack.create.fan_lava": "%1$s a été brûlé à mort par un ventilateur de lave",
"death.attack.create.mechanical_drill": "%1$s a été empalé par une perceuse mécanique", "death.attack.create.mechanical_drill": "%1$s a été empalé par une perceuse mécanique",
@ -365,10 +403,10 @@
"create.contraptions.movement_mode": "Mode de mouvement", "create.contraptions.movement_mode": "Mode de mouvement",
"create.contraptions.movement_mode.move_place": "Toujours placer à l'arrêt", "create.contraptions.movement_mode.move_place": "Toujours placer à l'arrêt",
"create.contraptions.movement_mode.move_place_returned": "Placer uniquement en position de départ", "create.contraptions.movement_mode.move_place_returned": "Placer uniquement en position de départ",
"create.contraptions.movement_mode.move_never_place": "Ne placer que lorsque l'ancre est détruite", "create.contraptions.movement_mode.move_never_place": "Ne placer que Quand l'ancre est détruite",
"create.contraptions.movement_mode.rotate_place": "Toujours placer à l'arrêt", "create.contraptions.movement_mode.rotate_place": "Toujours placer à l'arrêt",
"create.contraptions.movement_mode.rotate_place_returned": "Placer uniquement près de l'angle initial", "create.contraptions.movement_mode.rotate_place_returned": "Placer uniquement près de l'angle initial",
"create.contraptions.movement_mode.rotate_never_place": "Ne placer que lorsque l'ancre est détruite", "create.contraptions.movement_mode.rotate_never_place": "Ne placer que Quand l'ancre est détruite",
"create.logistics.filter": "Filtre", "create.logistics.filter": "Filtre",
"create.logistics.recipe_filter": "Filtre de recettes", "create.logistics.recipe_filter": "Filtre de recettes",
@ -607,7 +645,7 @@
"create.command.killTPSCommand.status.usage.1": "[Create]: use /killtps start <tickTime> to artificially slow down the server tick", "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.command.killTPSCommand.argument.tickTime": "tickTime",
"create.subtitle.schematicannon_launch_block": "Tire de schémacanon", "create.subtitle.schematicannon_launch_block": "Tir de schémacanon",
"create.subtitle.schematicannon_finish": "Fin de schémacanon", "create.subtitle.schematicannon_finish": "Fin de schémacanon",
"create.subtitle.slime_added": "Bruit de slime", "create.subtitle.slime_added": "Bruit de slime",
"create.subtitle.mechanical_press_activation": "Activation de la presse mechanique", "create.subtitle.mechanical_press_activation": "Activation de la presse mechanique",
@ -626,12 +664,12 @@
"item.create.example_item.tooltip.behaviour1": "Donc cet objet fait ceci. (les comportements sont affichés avec shift)", "item.create.example_item.tooltip.behaviour1": "Donc cet objet fait ceci. (les comportements sont affichés avec shift)",
"item.create.example_item.tooltip.condition2": "Et quand cela", "item.create.example_item.tooltip.condition2": "Et quand cela",
"item.create.example_item.tooltip.behaviour2": "Vous pouvez ajouter autant de comportements que vous le souhaitez", "item.create.example_item.tooltip.behaviour2": "Vous pouvez ajouter autant de comportements que vous le souhaitez",
"item.create.example_item.tooltip.control1": "Lorsque Ctrl enfoncé", "item.create.example_item.tooltip.control1": "Quand Ctrl enfoncé",
"item.create.example_item.tooltip.action1": "Ces commandes sont affichées.", "item.create.example_item.tooltip.action1": "Ces commandes sont affichées.",
"item.create.wand_of_symmetry.tooltip": "BÂTON DE SYMÉTRIE", "item.create.wand_of_symmetry.tooltip": "BÂTON DE SYMÉTRIE",
"item.create.wand_of_symmetry.tooltip.summary": "Reflète parfaitement le placement des blocs sur les plans configurés.", "item.create.wand_of_symmetry.tooltip.summary": "Reflète parfaitement le placement des blocs sur les plans configurés.",
"item.create.wand_of_symmetry.tooltip.condition1": "Lorsque positionné dans la barre active", "item.create.wand_of_symmetry.tooltip.condition1": "Quand positionné dans la barre active",
"item.create.wand_of_symmetry.tooltip.behaviour1": "Reste actif", "item.create.wand_of_symmetry.tooltip.behaviour1": "Reste actif",
"item.create.wand_of_symmetry.tooltip.control1": "Clic droit au sol", "item.create.wand_of_symmetry.tooltip.control1": "Clic droit au sol",
"item.create.wand_of_symmetry.tooltip.action1": "_Créé_ ou _déplace_ le mirroir", "item.create.wand_of_symmetry.tooltip.action1": "_Créé_ ou _déplace_ le mirroir",
@ -658,25 +696,25 @@
"item.create.handheld_worldshaper.tooltip.control3": "Clic droit en étant accroupi", "item.create.handheld_worldshaper.tooltip.control3": "Clic droit en étant accroupi",
"item.create.handheld_worldshaper.tooltip.action3": "Ouvre l'_interface_ _de_ _configuration_", "item.create.handheld_worldshaper.tooltip.action3": "Ouvre l'_interface_ _de_ _configuration_",
"item.create.tree_fertilizer.tooltip": "ENGRAIS POUR ARBRE", "item.create.tree_fertilizer.tooltip": "ENGRAIS POUR ARBRES",
"item.create.tree_fertilizer.tooltip.summary": "Une puissante combinaison de minéraux adaptée pour accélérer la croissance des types d'arbres communs.", "item.create.tree_fertilizer.tooltip.summary": "Une puissante combinaison de minéraux adaptée pour accélérer la croissance des types d'rotors communs.",
"item.create.tree_fertilizer.tooltip.condition1": "Lorsqu'utilisé sur une pousse d'arbre", "item.create.tree_fertilizer.tooltip.condition1": "Lorsqu'utilisé sur une pousse d'rotor",
"item.create.tree_fertilizer.tooltip.behaviour1": "Fait pousser des arbres _indépendamment_ de leurs _conditions_ _d'emplacement_", "item.create.tree_fertilizer.tooltip.behaviour1": "Fait pousser des rotors _indépendamment_ de leurs _conditions_ _d'emplacement_",
"item.create.deforester.tooltip": "DÉFORESTEUR", "item.create.deforester.tooltip": "DÉFORESTEUR",
"item.create.deforester.tooltip.summary": "Une _hache_ _rayonnante_ capable d'abattre des arbres en une fraction de seconde.", "item.create.deforester.tooltip.summary": "Une _hache_ _rayonnante_ capable d'abattre des rotors en une fraction de seconde.",
"item.create.filter.tooltip": "FILTRE", "item.create.filter.tooltip": "FILTRE",
"item.create.filter.tooltip.summary": "_Contrôle_ les _sorties_ et _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.", "item.create.filter.tooltip.summary": "_Contrôle_ les _sorties_ et _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.",
"item.create.filter.tooltip.condition1": "Lorsque dans l'emplacement de filtre", "item.create.filter.tooltip.condition1": "Quand dans l'emplacement de filtre",
"item.create.filter.tooltip.behaviour1": "_Contrôle_ le flux d'object selon sa _configuration_.", "item.create.filter.tooltip.behaviour1": "_Contrôle_ le flux d'object selon sa _configuration_.",
"item.create.filter.tooltip.condition2": "Clic droit", "item.create.filter.tooltip.condition2": "Clic droit",
"item.create.filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.", "item.create.filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.",
"item.create.attribute_filter.tooltip": "FILTRE D'ATTRIBUTS", "item.create.attribute_filter.tooltip": "FILTRE D'ATTRIBUTS",
"item.create.attribute_filter.tooltip.summary": "_Contrôle_ les _sorties_ et les _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.", "item.create.attribute_filter.tooltip.summary": "_Contrôle_ les _sorties_ et les _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.",
"item.create.attribute_filter.tooltip.condition1": "Lorsque dans l'emplacement de filtre", "item.create.attribute_filter.tooltip.condition1": "Quand dans l'emplacement de filtre",
"item.create.attribute_filter.tooltip.behaviour1": "_Contrôle_ le flux d'object selon sa _configuration_.", "item.create.attribute_filter.tooltip.behaviour1": "_Contrôle_ le flux d'object selon sa _configuration_.",
"item.create.attribute_filter.tooltip.condition2": "Clic droit", "item.create.attribute_filter.tooltip.condition2": "Clic droit",
"item.create.attribute_filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.", "item.create.attribute_filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.",
@ -686,7 +724,7 @@
"item.create.schematic.tooltip": "SCHÉMA", "item.create.schematic.tooltip": "SCHÉMA",
"item.create.schematic.tooltip.summary": "Contient une structure à positionner et à placer dans le monde. Positionnez l'hologramme comme vous le souhaitez et utilisez un _schémacanon_ pour le construire.", "item.create.schematic.tooltip.summary": "Contient une structure à positionner et à placer dans le monde. Positionnez l'hologramme comme vous le souhaitez et utilisez un _schémacanon_ pour le construire.",
"item.create.schematic.tooltip.condition1": "Lorsque tenu en main", "item.create.schematic.tooltip.condition1": "Quand tenu en main",
"item.create.schematic.tooltip.behaviour1": "Peut être positionné à l'aide des outils à l'écran.", "item.create.schematic.tooltip.behaviour1": "Peut être positionné à l'aide des outils à l'écran.",
"item.create.schematic.tooltip.control1": "Clic droit en étant accroupi", "item.create.schematic.tooltip.control1": "Clic droit en étant accroupi",
"item.create.schematic.tooltip.action1": "Ouvre une _interface_ pour rentrer les _coordonées_ correctes.", "item.create.schematic.tooltip.action1": "Ouvre une _interface_ pour rentrer les _coordonées_ correctes.",
@ -711,54 +749,54 @@
"block.create.schematic_table.tooltip": "TABLE À SCHÉMA", "block.create.schematic_table.tooltip": "TABLE À SCHÉMA",
"block.create.schematic_table.tooltip.summary": "Écrit les schémas enregistrés dans un _schéma_ _vide_.", "block.create.schematic_table.tooltip.summary": "Écrit les schémas enregistrés dans un _schéma_ _vide_.",
"block.create.schematic_table.tooltip.condition1": "Lorsque donné un schéma vide", "block.create.schematic_table.tooltip.condition1": "Quand donné un schéma vide",
"block.create.schematic_table.tooltip.behaviour1": "Télécharge un fichier choisi à partir de votre dossier de schémas.", "block.create.schematic_table.tooltip.behaviour1": "Télécharge un fichier choisi à partir de votre dossier de schémas.",
"block.create.shaft.tooltip": "ARBRE MÉCANIQUE", "block.create.shaft.tooltip": "ROTOR",
"block.create.shaft.tooltip.summary": "_Relais_ la _rotation_ en ligne droite.", "block.create.shaft.tooltip.summary": "_Relaie_ la _rotation_ en ligne droite.",
"block.create.cogwheel.tooltip": "ROUE DENTÉE", "block.create.cogwheel.tooltip": "ROUE DENTÉE",
"block.create.cogwheel.tooltip.summary": "_Relais_ la _rotation_ en ligne droite, et aux _roues_ _dentées_ adjacentes.", "block.create.cogwheel.tooltip.summary": "_Relaie_ la _rotation_ en ligne droite, et aux _roues_ _dentées_ adjacentes.",
"block.create.large_cogwheel.tooltip": "GRANDE ROUE DENTÉE", "block.create.large_cogwheel.tooltip": "GRANDE ROUE DENTÉE",
"block.create.large_cogwheel.tooltip.summary": "Une version plus grande de la _roue_ _dentée_, permettant des _changements_ dans la _vitesse_ _de_ _rotation_ lorsqu'il est connecté à son homologue plus petit.", "block.create.large_cogwheel.tooltip.summary": "Une version plus grande de la _roue_ _dentée_, permettant des _changements_ dans la _vitesse_ _de_ _rotation_ lorsqu'il est connecté à son homologue plus petit.",
"block.create.encased_shaft.tooltip": "ARBRE MÉCANIQUE ENBOÎTÉ", "block.create.encased_shaft.tooltip": "ROTOR ENCASTRÉ",
"block.create.encased_shaft.tooltip.summary": "_Relais_ la _rotation_ en ligne droite. Convient pour propager la rotation à travers les murs.", "block.create.encased_shaft.tooltip.summary": "_Relaie_ la _rotation_ en ligne droite. Convient pour propager la rotation à travers les murs.",
"block.create.gearbox.tooltip": "BOÎTE DE VITESSES", "block.create.gearbox.tooltip": "BOÎTE DE VITESSES",
"block.create.gearbox.tooltip.summary": "_Relais_ la _rotation_ dans _quatre_ _directions_. Inverse les connexions directes.", "block.create.gearbox.tooltip.summary": "_Relaie_ la _rotation_ dans _quatre_ _directions_. Inverse les connexions directes.",
"block.create.gearshift.tooltip": "DÉCALEUR DE ROTATION", "block.create.gearshift.tooltip": "BOÎTE DE VITESSES",
"block.create.gearshift.tooltip.summary": "Une commande pour basculer le sens de rotation des arbres connectés.", "block.create.gearshift.tooltip.summary": "Une commande pour basculer le sens de rotation des rotors connectés.",
"block.create.gearshift.tooltip.condition1": "Lorsqu'alimenté", "block.create.gearshift.tooltip.condition1": "Lorsqu'alimenté",
"block.create.gearshift.tooltip.behaviour1": "_Inverse_ la rotation sortante.", "block.create.gearshift.tooltip.behaviour1": "_Inverse_ la rotation sortante.",
"block.create.clutch.tooltip": "EMBRAYAGE", "block.create.clutch.tooltip": "EMBRAYAGE",
"block.create.clutch.tooltip.summary": "Une commande pour engager / désengager la rotation des arbres connectés.", "block.create.clutch.tooltip.summary": "Une commande pour engager / désengager la rotation des rotors connectés.",
"block.create.clutch.tooltip.condition1": "Lorsqu'alimenté", "block.create.clutch.tooltip.condition1": "Lorsqu'alimenté",
"block.create.clutch.tooltip.behaviour1": "_Arrête_ de transmettre la rotation de l'autre côté.", "block.create.clutch.tooltip.behaviour1": "_Arrête_ de transmettre la rotation de l'autre côté.",
"item.create.belt_connector.tooltip": "CONNECTEUR DE TAPIS ROULANTS", "item.create.belt_connector.tooltip": "CONNECTEUR DE TAPIS ROULANTS",
"item.create.belt_connector.tooltip.summary": "Connecte deux _arbres_ ou plus à un _tapis_ _roulant_ _mécanique_. Les arbres connectés auront exactement la même vitesse et le même sens de rotation. La ceinture peut agir comme un _convoyeur_ pour _objets_ et _entités_.", "item.create.belt_connector.tooltip.summary": "Connecte deux _rotors_ ou plus à un _tapis_ _roulant_ _mécanique_. Les rotors connectés auront exactement la même vitesse et le même sens de rotation. La ceinture peut agir comme un _convoyeur_ pour _objets_ et _entités_.",
"item.create.belt_connector.tooltip.control1": "Clic droit sur arbre", "item.create.belt_connector.tooltip.control1": "Clic droit sur rotor",
"item.create.belt_connector.tooltip.action1": "Sélectionne l'arbre comme une poulie de la courroie. Les deux arbres sélectionnés doivent être _alignés_ soit _verticalement_, _horizontalement_, ou _diagonalement_ en direction de la courroie.", "item.create.belt_connector.tooltip.action1": "Sélectionne le rotor comme une poulie de la courroie. Les deux rotors sélectionnés doivent être _alignés_ soit _verticalement_, _horizontalement_, ou _diagonalement_ en direction de la courroie.",
"item.create.belt_connector.tooltip.control2": "Clic droit en étant accroupi", "item.create.belt_connector.tooltip.control2": "Clic droit en étant accroupi",
"item.create.belt_connector.tooltip.action2": "_Réinitialise_ la première position sélectionnée pour le tapis roulant.", "item.create.belt_connector.tooltip.action2": "_Réinitialise_ la première position sélectionnée pour le tapis roulant.",
"item.create.goggles.tooltip": "LUNETTES", "item.create.goggles.tooltip": "LUNETTES",
"item.create.goggles.tooltip.summary": "Une paire de lunettes pour augmenter votre vision avec des _informations_ _kinétiques_ utiles.", "item.create.goggles.tooltip.summary": "Une paire de lunettes pour augmenter votre vision avec des _informations_ _kinétiques_ utiles.",
"item.create.goggles.tooltip.condition1": "Lorsque portées", "item.create.goggles.tooltip.condition1": "Quand portées",
"item.create.goggles.tooltip.behaviour1": "Affiche des _indicateurs_ _colorés_ correspondants au _niveau_ _de_ _vitesse_ d'un composant cinétique placé ainsi que _l'impact_ du _stress_ et la _capacité_ des composants individuels.", "item.create.goggles.tooltip.behaviour1": "Affiche des _indicateurs_ _colorés_ correspondants au _niveau_ _de_ _vitesse_ d'un composant cinétique placé ainsi que _l'impact_ du _stress_ et la _capacité_ des composants individuels.",
"item.create.goggles.tooltip.condition2": "Lorsque vision portée sur une jauge", "item.create.goggles.tooltip.condition2": "Quand vision portée sur une jauge",
"item.create.goggles.tooltip.behaviour2": "Affiche des informations détaillées sur la _vitesse_ ou le _stress_ du réseau auquel la jauge est connectée.", "item.create.goggles.tooltip.behaviour2": "Affiche des informations détaillées sur la _vitesse_ ou le _stress_ du réseau auquel la jauge est connectée.",
"item.create.wrench.tooltip": "CLÉ", "item.create.wrench.tooltip": "CLÉ",
"item.create.wrench.tooltip.summary": "Un outil utile pour travailler sur les engins cinétiques. Peut être utilisé pour _tourner_, _démonter_ et _configurer_ les composants.", "item.create.wrench.tooltip.summary": "Un outil utile pour travailler sur les engins cinétiques. Peut être utilisé pour _tourner_, _démonter_ et _configurer_ les composants.",
"item.create.wrench.tooltip.control1": "Clic droit a kinetic block", "item.create.wrench.tooltip.control1": "Clic droit sur un bloc de Create",
"item.create.wrench.tooltip.action1": "_Tourne_ les _composents_ proche ou loin de la face avec lequel vous avez interagi.", "item.create.wrench.tooltip.action1": "_Tourne_ le _composant_ le long de l'axe dépendant de la face avec lequel vous avez interagi.",
"item.create.wrench.tooltip.control2": "Clic droit en étant accroupi", "item.create.wrench.tooltip.control2": "Clic droit en étant accroupi",
"item.create.wrench.tooltip.action2": "_Démonte_ les _composants_ _cinétiques_ et les replace dans _votre_ _inventaire_.", "item.create.wrench.tooltip.action2": "_Démonte_ les _composants_ _cinétiques_ et les replace dans _votre_ _inventaire_.",
@ -768,17 +806,17 @@
"block.create.water_wheel.tooltip": "ROUE À EAU", "block.create.water_wheel.tooltip": "ROUE À EAU",
"block.create.water_wheel.tooltip.summary": "Fournit une _force_ _de_ _rotation_ provenant de _courants_ _d'eau_ adjacents.", "block.create.water_wheel.tooltip.summary": "Fournit une _force_ _de_ _rotation_ provenant de _courants_ _d'eau_ adjacents.",
"block.create.encased_fan.tooltip": "VENTILATEUR ENFERMÉ", "block.create.encased_fan.tooltip": "VENTILATEUR ENCHÂSSÉ",
"block.create.encased_fan.tooltip.summary": "Convertit _force_ _de_ _rotation_ en _courants_ _d'air_ et inversement. A une variété d'utilisations.", "block.create.encased_fan.tooltip.summary": "Convertit _force_ _de_ _rotation_ en _courants_ _d'air_ et inversement. A une variété d'utilisations.",
"block.create.encased_fan.tooltip.condition1": "Lorsqu'alimenté par de la redstone", "block.create.encased_fan.tooltip.condition1": "Lorsqu'alimenté par de la redstone",
"block.create.encased_fan.tooltip.behaviour1": "Fournit _force_ _de_ _rotation_ à partir de toute _source_ _de_ _chaleur_ immédiatement en dessous de lui. Le ventilateur doit être tourné vers le bas.", "block.create.encased_fan.tooltip.behaviour1": "Fournit _force_ _de_ _rotation_ à partir de toute _source_ _de_ _chaleur_ immédiatement en dessous de lui. Le ventilateur doit être tourné vers le bas.",
"block.create.encased_fan.tooltip.condition2": "Lorsque tourné", "block.create.encased_fan.tooltip.condition2": "Quand tourné",
"block.create.encased_fan.tooltip.behaviour2": "_Pousse_ ou _tire_ les entités, selon la vitesse de rotation entrante.", "block.create.encased_fan.tooltip.behaviour2": "_Pousse_ ou _tire_ les entités, selon la vitesse de rotation entrante.",
"block.create.encased_fan.tooltip.condition3": "Lorsque souffle à travers des blocs spéciaux", "block.create.encased_fan.tooltip.condition3": "Quand souffle à travers des blocs spéciaux",
"block.create.encased_fan.tooltip.behaviour3": "Des particules de _liquides_ et de _feu_ sont émises dans le flux d'air. Cela peut être utilisé pour _traiter_ des _objets_.", "block.create.encased_fan.tooltip.behaviour3": "Des particules de _liquides_ et de _feu_ sont émises dans le flux d'air. Cela peut être utilisé pour _traiter_ des _objets_.",
"block.create.nozzle.tooltip": "BUSE", "block.create.nozzle.tooltip": "BUSE",
"block.create.nozzle.tooltip.summary": "Attachez-le à l'avant d'un _ventilateur_ _enfermé_ pour répartir son effet sur les entités dans _toutes_ les _directions_.", "block.create.nozzle.tooltip.summary": "Attachez-le à l'avant d'un _ventilateur_ enchâssé_ pour répartir son effet sur les entités dans _toutes_ les _directions_.",
"block.create.hand_crank.tooltip": "MANIVELLE", "block.create.hand_crank.tooltip": "MANIVELLE",
"block.create.hand_crank.tooltip.summary": "Une simple _source_ de _force_ _de_ _rotation_ qui nécessite l'interaction des joueurs.", "block.create.hand_crank.tooltip.summary": "Une simple _source_ de _force_ _de_ _rotation_ qui nécessite l'interaction des joueurs.",
@ -787,16 +825,16 @@
"block.create.cuckoo_clock.tooltip": "COUCOU", "block.create.cuckoo_clock.tooltip": "COUCOU",
"block.create.cuckoo_clock.tooltip.summary": "Un bel artisanat pour _décorer_ un espace et _garder_ la _notion_ _du_ _temps_.", "block.create.cuckoo_clock.tooltip.summary": "Un bel artisanat pour _décorer_ un espace et _garder_ la _notion_ _du_ _temps_.",
"block.create.cuckoo_clock.tooltip.condition1": "Lorsque tourné", "block.create.cuckoo_clock.tooltip.condition1": "Quand tourné",
"block.create.cuckoo_clock.tooltip.behaviour1": "Affiche le _temps_ _présent_ et joue une mélodie deux fois par jour. _S'active_ une fois le _midi_ et une fois au crépuscule, dès que les _joueurs_ _peuvent_ _dormir_.", "block.create.cuckoo_clock.tooltip.behaviour1": "Affiche le _temps_ _présent_ et joue une mélodie deux fois par jour. _S'active_ une fois le _midi_ et une fois au crépuscule, dès que les _joueurs_ _peuvent_ _dormir_.",
"block.create.turntable.tooltip": "PLAQUE TOURNANTE", "block.create.turntable.tooltip": "PLAQUE TOURNANTE",
"block.create.turntable.tooltip.summary": "Transforme la _force_ _de_ _rotation_ en une nausée.", "block.create.turntable.tooltip.summary": "Transforme la _force_ _de_ _rotation_ en énergie cinétique.",
"block.create.crushing_wheel.tooltip": "ROUE DE CONCASSAGE", "block.create.crushing_wheel.tooltip": "ROUE DE CONCASSAGE",
"block.create.crushing_wheel.tooltip.summary": "Grandes roues rotatives qui _cassent_ n'importe quoi.", "block.create.crushing_wheel.tooltip.summary": "Grandes roues rotatives qui _cassent_ n'importe quoi.",
"block.create.crushing_wheel.tooltip.condition1": "Lorsque fixé à une autre roue de concassage", "block.create.crushing_wheel.tooltip.condition1": "Quand fixé à une autre roue de concassage",
"block.create.crushing_wheel.tooltip.behaviour1": "Forme une machine de concassage pour traiter une variété de choses. Les dents des roues doivent se connecter et se déplacer avec la _même_ _vitesse_ dans des _directions_ _opposées_.", "block.create.crushing_wheel.tooltip.behaviour1": "Forme une machine de concassage pour traiter une variété de choses. Les dents des roues doivent se connecter et se déplacer avec la _même_ _vitesse_ dans des _directions_ _opposées_.",
"block.create.mechanical_press.tooltip": "PRESSE MÉCANIQUE", "block.create.mechanical_press.tooltip": "PRESSE MÉCANIQUE",
@ -814,11 +852,11 @@
"block.create.mechanical_mixer.tooltip": "MIXEUR MÉCANIQUE", "block.create.mechanical_mixer.tooltip": "MIXEUR MÉCANIQUE",
"block.create.mechanical_mixer.tooltip.summary": "Un fouet cinétique pour appliquer toutes les recettes d'artisanat informes aux objets en dessous. Nécessite une _force_ _de_ _rotation_ constant et un _bassin_ placé en dessous (avec un espace entre les deux).", "block.create.mechanical_mixer.tooltip.summary": "Un fouet cinétique pour appliquer toutes les recettes d'artisanat informes aux objets en dessous. Nécessite une _force_ _de_ _rotation_ constant et un _bassin_ placé en dessous (avec un espace entre les deux).",
"block.create.mechanical_mixer.tooltip.condition1": "Lorsqu'au-dessus d'un bassin", "block.create.mechanical_mixer.tooltip.condition1": "Lorsqu'au-dessus d'un bassin",
"block.create.mechanical_mixer.tooltip.behaviour1": "Commence à mélanger les objets dans le bassin lorsque tous les ingrédients nécessaires sont présents.", "block.create.mechanical_mixer.tooltip.behaviour1": "Commence à mélanger les objets dans le bassin Quand tous les ingrédients nécessaires sont présents.",
"block.create.mechanical_crafter.tooltip": "ÉTABLI MÉCANIQUE", "block.create.mechanical_crafter.tooltip": "ÉTABLI MÉCANIQUE",
"block.create.mechanical_crafter.tooltip.summary": "Un assembleur cinétique pour _automatiser_ n'importe quelle recette _en_ _forme_. Placez-en _plusieurs_ _dans_ _une_ _grille_ correspondant à votre recette, et _arrangez_ _leurs_ _tapis_ _roulant_ pour créer un _flux_ qui sort de la grille sur l'un des établis.", "block.create.mechanical_crafter.tooltip.summary": "Un assembleur cinétique pour _automatiser_ n'importe quelle recette _en_ _forme_. Placez-en _plusieurs_ _dans_ _une_ _grille_ correspondant à votre recette, et _arrangez_ _leurs_ _tapis_ _roulant_ pour créer un _flux_ qui sort de la grille sur l'un des établis.",
"block.create.mechanical_crafter.tooltip.condition1": "Lorsque tourné", "block.create.mechanical_crafter.tooltip.condition1": "Quand tourné",
"block.create.mechanical_crafter.tooltip.behaviour1": "_Démarre_ _le_ _processus_ _d'artisanat_ dès que _tous_ les _établis_ dans la grille ont _reçu_ _un_ _objet_.", "block.create.mechanical_crafter.tooltip.behaviour1": "_Démarre_ _le_ _processus_ _d'artisanat_ dès que _tous_ les _établis_ dans la grille ont _reçu_ _un_ _objet_.",
"block.create.mechanical_crafter.tooltip.control1": "Lorsqu'utilisation de la clé à l'avant", "block.create.mechanical_crafter.tooltip.control1": "Lorsqu'utilisation de la clé à l'avant",
"block.create.mechanical_crafter.tooltip.action1": "_Fait_ _défiler_ _la_ _direction_ dans laquelle un établi individuel _déplace_ _ses_ _objets_. Pour former une grille de travail, disposer les _tapis_ _roulants_ _dans_ _un_ _flux_ qui déplace tous les articles vers un établi final. Le dernier artisan doit _pointer_ _autrepart_ de la grille.", "block.create.mechanical_crafter.tooltip.action1": "_Fait_ _défiler_ _la_ _direction_ dans laquelle un établi individuel _déplace_ _ses_ _objets_. Pour former une grille de travail, disposer les _tapis_ _roulants_ _dans_ _un_ _flux_ qui déplace tous les articles vers un établi final. Le dernier artisan doit _pointer_ _autrepart_ de la grille.",
@ -838,7 +876,7 @@
"block.create.portable_storage_interface.tooltip": "INTERFACE DE STOCKAGE PORTABLE", "block.create.portable_storage_interface.tooltip": "INTERFACE DE STOCKAGE PORTABLE",
"block.create.portable_storage_interface.tooltip.summary": "Un point d'échange portable pour _déplacer_ des _objets_ vers et depuis une _structure_ déplacée par un piston, un roulement, un chariot ou une poulie.", "block.create.portable_storage_interface.tooltip.summary": "Un point d'échange portable pour _déplacer_ des _objets_ vers et depuis une _structure_ déplacée par un piston, un roulement, un chariot ou une poulie.",
"block.create.portable_storage_interface.tooltip.condition1": "Lorsqu'en mouvement", "block.create.portable_storage_interface.tooltip.condition1": "Lorsqu'en mouvement",
"block.create.portable_storage_interface.tooltip.behaviour1": "Interagit avec les _transposeurs_ stationnaires de sorte que les transposeurs faisant _face_ _autrepart_ de l'interface tirent les objets, et les transposeurs ciblant l'interface y _insereront_ les _objets_ de l'inventaire joint. L'engin se bloquera brièvement lorsque les objets seront échangés.", "block.create.portable_storage_interface.tooltip.behaviour1": "Interagit avec les _transposeurs_ stationnaires de sorte que les transposeurs faisant _face_ _autrepart_ de l'interface tirent les objets, et les transposeurs ciblant l'interface y _insereront_ les _objets_ de l'inventaire joint. L'engin se bloquera brièvement Quand les objets seront échangés.",
"block.create.rotation_speed_controller.tooltip": "CONTRÔLEUR DE VITESSE DE ROTATION", "block.create.rotation_speed_controller.tooltip": "CONTRÔLEUR DE VITESSE DE ROTATION",
@ -848,17 +886,17 @@
"block.create.mechanical_piston.tooltip": "PISTON MÉCANIQUE", "block.create.mechanical_piston.tooltip": "PISTON MÉCANIQUE",
"block.create.mechanical_piston.tooltip.summary": "Une version plus avancée du _piston_. Il utilise une _force_ _de_ rotation_ pour déplacer précisément les structures attachées. Les _pôles_ _d'extension_ _de_ _piston_ à l'arrière définissent la _portée_ de cet appareil. Sans extensions, le piston ne bougera pas. Utilisez un _châssis_ ou un _bloc_ _de_ slime_ pour déplacer plus d'une seule ligne de blocs.", "block.create.mechanical_piston.tooltip.summary": "Une version plus avancée du _piston_. Il utilise une _force_ _de_ rotation_ pour déplacer précisément les structures attachées. Les _pôles_ _d'extension_ _de_ _piston_ à l'arrière définissent la _portée_ de cet appareil. Sans extensions, le piston ne bougera pas. Utilisez un _châssis_ ou un _bloc_ _de_ slime_ pour déplacer plus d'une seule ligne de blocs.",
"block.create.mechanical_piston.tooltip.condition1": "Lorsque tourné", "block.create.mechanical_piston.tooltip.condition1": "Quand tourné",
"block.create.mechanical_piston.tooltip.behaviour1": "Commence à déplacer la structure attachée. La vitesse et la direction sont corrélées à la vitesse de rotation entrante.", "block.create.mechanical_piston.tooltip.behaviour1": "Commence à déplacer la structure attachée. La vitesse et la direction sont corrélées à la vitesse de rotation entrante.",
"block.create.piston_extension_pole.tooltip": "PÔLE DE PISTON", "block.create.piston_extension_pole.tooltip": "BARRE DE PISTON",
"block.create.piston_extension_pole.tooltip.summary": "Étend la portée des _pistons_ _mécaniques.", "block.create.piston_extension_pole.tooltip.summary": "Étend la portée des _pistons_ _mécaniques.",
"block.create.piston_extension_pole.tooltip.condition1": "Lorsqu'attaché à un piston mécanique", "block.create.piston_extension_pole.tooltip.condition1": "Lorsqu'attaché à un piston mécanique",
"block.create.piston_extension_pole.tooltip.behaviour1": "Étend la portée du _piston_ d'un bloc", "block.create.piston_extension_pole.tooltip.behaviour1": "Étend la portée du _piston_ d'un bloc",
"block.create.mechanical_bearing.tooltip": "ROULEMENT MÉCANIQUE", "block.create.mechanical_bearing.tooltip": "ROULEMENT MÉCANIQUE",
"block.create.mechanical_bearing.tooltip.summary": "Utilisé pour faire tourner de _plus_ _grande_ _structures_ ou pour exploiter une _force_ _de_ rotation_ contre le vent.", "block.create.mechanical_bearing.tooltip.summary": "Utilisé pour faire tourner de _plus_ _grande_ _structures_ ou pour exploiter une _force_ _de_ rotation_ contre le vent.",
"block.create.mechanical_bearing.tooltip.condition1": "Lorsque tourné", "block.create.mechanical_bearing.tooltip.condition1": "Quand tourné",
"block.create.mechanical_bearing.tooltip.behaviour1": "Démarre les blocs attachés en rotation. Utilisez un _châssis_ ou _bloc_ _de_ _slime_ pour déplacer plus d'un seul bloc.", "block.create.mechanical_bearing.tooltip.behaviour1": "Démarre les blocs attachés en rotation. Utilisez un _châssis_ ou _bloc_ _de_ _slime_ pour déplacer plus d'un seul bloc.",
@ -866,48 +904,50 @@
"block.create.clockwork_bearing.tooltip": "ROULEMENT MÉCANIQUE HORLOGER", "block.create.clockwork_bearing.tooltip": "ROULEMENT MÉCANIQUE HORLOGER",
"block.create.clockwork_bearing.tooltip.summary": "Une version avancée du _roulement_ _mécanique_ pour faire tourner jusqu'à deux _aiguilles_ _d'horloge_ en fonction du _temps_ _en-jeu_ actuel.", "block.create.clockwork_bearing.tooltip.summary": "Une version avancée du _roulement_ _mécanique_ pour faire tourner jusqu'à deux _aiguilles_ _d'horloge_ en fonction du _temps_ _en-jeu_ actuel.",
"block.create.clockwork_bearing.tooltip.condition1": "Lorsque tourné", "block.create.clockwork_bearing.tooltip.condition1": "Quand tourné",
"block.create.clockwork_bearing.tooltip.behaviour1": "Commence la rotation de la structure attachée vers l'_heure_ _actuelle_. Si une seconde structure est présente, elle servira _d'aiguille_ _des_ _minutes_.", "block.create.clockwork_bearing.tooltip.behaviour1": "Commence la rotation de la structure attachée vers l'_heure_ _actuelle_. Si une seconde structure est présente, elle servira _d'aiguille_ _des_ _minutes_.",
"block.create.sequenced_gearshift.tooltip": "DÉCALEUR DE ROTATION SÉQUENCÉ", "block.create.sequenced_gearshift.tooltip": "BOÎITE À VITESSES SÉQUENCÉE",
"block.create.sequenced_gearshift.tooltip.summary": "Un _composant_ _utilitaire_ _programmable_, qui peut changer son _débit_ _de_ _rotation_ suivant jusqu'à _5_ _instructions_ _consécutives_. Utilisez-le pour alimenter des roulements mécaniques, des pistons ou des poulies avec plus de contrôle sur le timing et la vitesse. Peut devenir moins précis à des vitesses plus élevées.", "block.create.sequenced_gearshift.tooltip.summary": "Un _composant_ _utilitaire_ _programmable_, qui peut changer son _débit_ _de_ _rotation_ suivant jusqu'à _5_ _instructions_ _consécutives_. Utilisez-le pour alimenter des roulements mécaniques, des pistons ou des poulies avec plus de contrôle sur le timing et la vitesse. Peut devenir moins précis à des vitesses plus élevées.",
"block.create.sequenced_gearshift.tooltip.condition1": "Lorsqu'alimenté par de la redstone", "block.create.sequenced_gearshift.tooltip.condition1": "Lorsqu'alimenté par de la redstone",
"block.create.sequenced_gearshift.tooltip.behaviour1": "_Commence_ _à_ _exécuter_ les instructions programmées en fonction de la vitesse d'entrée.", "block.create.sequenced_gearshift.tooltip.behaviour1": "_Commence_ _à_ _exécuter_ les instructions programmées en fonction de la vitesse d'entrée.",
"block.create.sequenced_gearshift.tooltip.condition2": "Clic droit", "block.create.sequenced_gearshift.tooltip.condition2": "Clic droit",
"block.create.sequenced_gearshift.tooltip.behaviour2": "Ouvre _l'interface_ _de_ _configuration_", "block.create.sequenced_gearshift.tooltip.behaviour2": "Ouvre _l'interface_ _de_ _configuration_",
"block.create.cart_assembler.tooltip": "ASSEMBLEUR DE CHARIOT", "block.create.cart_assembler.tooltip": "ASSEMBLEUR DE WAGON",
"block.create.cart_assembler.tooltip.summary": "Monte une structure connectée sur un _chariot_ _passant_.", "block.create.cart_assembler.tooltip.summary": "Monte une structure connectée sur un _wagon_ _passant_.",
"block.create.cart_assembler.tooltip.condition1": "Lorsqu'alimenté par de la redstone", "block.create.cart_assembler.tooltip.condition1": "Lorsqu'alimenté par de la redstone",
"block.create.cart_assembler.tooltip.behaviour1": "_Démonte_ les structures montées un _chariot_ _passant_ et les remet dans le monde.", "block.create.cart_assembler.tooltip.behaviour1": "_Démonte_ les structures montées un _wagon passant_ et les remet dans le monde.",
"block.create.rope_pulley.tooltip": "POULIE DE CORDE", "block.create.rope_pulley.tooltip": "POULIE",
"block.create.rope_pulley.tooltip.summary": "Déplace les _blocs_ et _structures_ attachés _verticalement_. Utilisez un _châssis_ ou _bloc_ _de_ _slime_ pour déplacer plus d'un seul bloc.", "block.create.rope_pulley.tooltip.summary": "Déplace les _blocs_ et _structures_ attachés _verticalement_. Utilisez un _châssis_ ou _bloc_ _de_ _slime_ pour déplacer plus d'un seul bloc.",
"block.create.rope_pulley.tooltip.condition1": "Lorsque tourné", "block.create.rope_pulley.tooltip.condition1": "Quand tourné",
"block.create.rope_pulley.tooltip.behaviour1": "Commence à déplacer la structure attachée. La vitesse et la direction sont corrélées à la vitesse de rotation entrante.", "block.create.rope_pulley.tooltip.behaviour1": "Commence à déplacer la structure attachée. La vitesse et la direction sont corrélées à la vitesse de rotation entrante.",
"block.create.linear_chassis.tooltip": "CHÂSSIS DE TRADUCTION", "block.create.linear_chassis.tooltip": "CHÂSSIS LINÉAIRE",
"block.create.linear_chassis.tooltip.summary": "Un bloc de base configurable reliant les structures pour le mouvement.", "block.create.linear_chassis.tooltip.summary": "Un bloc de base configurable reliant les structures pour le mouvement.",
"block.create.linear_chassis.tooltip.condition1": "Lorsque déplacé", "block.create.linear_chassis.tooltip.condition1": "Quand déplacé",
"block.create.linear_chassis.tooltip.behaviour1": "_Déplace_ tous les _châssis_ _attachés_ avec la même orientation, et une colonne de blocs dans sa portée. Les blocs ne seront tirés que si la face du châssis est _collante_ (Voir [Ctrl]).", "block.create.linear_chassis.tooltip.behaviour1": "_Déplace_ tous les _châssis_ _attachés_ avec la même orientation, et une colonne de blocs dans sa portée. Les blocs ne seront tirés que si la face du châssis est _collante_ (Voir [Ctrl]).",
"block.create.linear_chassis.tooltip.condition2": "Lorsqu'utilisé avec une clé", "block.create.linear_chassis.tooltip.condition2": "Lorsqu'utilisé avec une clé",
"block.create.linear_chassis.tooltip.behaviour2": "Configurez la _portée_ pour ce bloc de châssis. Maintenez CTRL pour modifier également la plage de tous les blocs de châssis connectés.", "block.create.linear_chassis.tooltip.behaviour2": "Configurez la _portée_ pour ce bloc de châssis. Maintenez CTRL pour modifier également la plage de tous les blocs de châssis connectés.",
"block.create.linear_chassis.tooltip.control1": "Clic droit avec une boule de slime", "block.create.linear_chassis.tooltip.control1": "Clic droit avec une boule de slime",
"block.create.linear_chassis.tooltip.action1": "Rends la face _collante_. Lorsque déplace, le châssis va _tirer_ les blocs attachés, quelle que soit la direction du mouvement.", "block.create.linear_chassis.tooltip.action1": "Rend la face _collante_. Quand déplacé, le châssis va _tirer_ les blocs attachés, quelle que soit la direction du mouvement.",
"block.create.secondary_linear_chassis.tooltip": "CHÂSSIS LINÉAIRE SECONDAIRE",
"block.create.secondary_linear_chassis.tooltip.summary": "Un deuxième type de _châssis linéaire_ qui ne se connecte pas au premier.",
"block.create.radial_chassis.tooltip": "CHÂSSIS DE ROTATION", "block.create.radial_chassis.tooltip": "CHÂSSIS DE ROTATION",
"block.create.radial_chassis.tooltip.summary": "Un bloc de base configurable reliant les structures pour le mouvement.", "block.create.radial_chassis.tooltip.summary": "Un bloc de base configurable reliant les structures pour le mouvement.",
"block.create.radial_chassis.tooltip.condition1": "Lorsque déplacé", "block.create.radial_chassis.tooltip.condition1": "Quand déplacé",
"block.create.radial_chassis.tooltip.behaviour1": "_Déplace_ tous les _châssis_ _attachés_ en colonne, et un cylindre de blocs autour de lui. Les blocs qui l'entourent ne sont déplacés que lorsqu'ils sont à portée et attachés à un côté collant (voir [Ctrl]).", "block.create.radial_chassis.tooltip.behaviour1": "_Déplace_ tous les _châssis_ _attachés_ en colonne, et un cylindre de blocs autour de lui. Les blocs qui l'entourent ne sont déplacés que lorsqu'ils sont à portée et attachés à un côté collant (voir [Ctrl]).",
"block.create.radial_chassis.tooltip.condition2": "Lorsqu'utilisé avec une clé", "block.create.radial_chassis.tooltip.condition2": "Lorsqu'utilisé avec une clé",
"block.create.radial_chassis.tooltip.behaviour2": "Configure la _portée_ pour ce bloc de châssis. Maintenez CTRL pour modifier également la portée de tous les blocs de châssis connectés.", "block.create.radial_chassis.tooltip.behaviour2": "Configure la _portée_ pour ce bloc de châssis. Maintenez CTRL pour modifier également la portée de tous les blocs de châssis connectés.",
"block.create.radial_chassis.tooltip.control1": "Clic droit avec une boule de slime", "block.create.radial_chassis.tooltip.control1": "Clic droit avec une boule de slime",
"block.create.radial_chassis.tooltip.action1": "Rend la face _collante_. Lorsque le châssis se déplace, tous les blocs désignés attachés au côté collant sont déplacés avec lui.", "block.create.radial_chassis.tooltip.action1": "Rend la face _collante_. Quand le châssis se déplace, tous les blocs désignés attachés au côté collant sont déplacés avec lui.",
"block.create.mechanical_drill.tooltip": "PERCEUSE MÉCANIQUE", "block.create.mechanical_drill.tooltip": "PERCEUSE MÉCANIQUE",
"block.create.mechanical_drill.tooltip.summary": "Un dispositif mécanique adapté pour _casser_ les _blocs_. Il est déplaceable avec _pistons_ _mécaniques_ ou _roulements_.", "block.create.mechanical_drill.tooltip.summary": "Un dispositif mécanique adapté pour _casser_ les _blocs_. Il est déplaceable avec _pistons_ _mécaniques_ ou _roulements_.",
"block.create.mechanical_drill.tooltip.condition1": "Lorsque tourné", "block.create.mechanical_drill.tooltip.condition1": "Quand tourné",
"block.create.mechanical_drill.tooltip.behaviour1": "Agit comme un casseur de bloc _stationnaire_. Inflige aussi des _dégats_ aux _entités_ se situant dans sa zone effective.", "block.create.mechanical_drill.tooltip.behaviour1": "Agit comme un casseur de bloc _stationnaire_. Inflige aussi des _dégats_ aux _entités_ se situant dans sa zone effective.",
"block.create.mechanical_drill.tooltip.condition2": "Lorsqu'en mouvement", "block.create.mechanical_drill.tooltip.condition2": "Lorsqu'en mouvement",
"block.create.mechanical_drill.tooltip.behaviour2": "Casse les blocs avec lesquels la perceuse entre en collision.", "block.create.mechanical_drill.tooltip.behaviour2": "Casse les blocs avec lesquels la perceuse entre en collision.",
@ -917,38 +957,44 @@
"block.create.mechanical_harvester.tooltip.condition1": "Lorsqu'en mouvement", "block.create.mechanical_harvester.tooltip.condition1": "Lorsqu'en mouvement",
"block.create.mechanical_harvester.tooltip.behaviour1": "_Récolte_ toutes les _cultures_ _matures_ que la lame entre en touche et les remet à leur état de croissance initial.", "block.create.mechanical_harvester.tooltip.behaviour1": "_Récolte_ toutes les _cultures_ _matures_ que la lame entre en touche et les remet à leur état de croissance initial.",
"block.create.mechanical_plough.tooltip": "CHARRUE MÉCANIQUE",
"block.create.mechanical_plough.tooltip.summary": "Une charrue mécanique a divers usages. Elle peut être déplacée à l'aide de _pistons mécaniques_, de _roulements_ ou d'autres dispositifs de commande.",
"block.create.mechanical_plough.tooltip.condition1": "Lorsquen mouvement",
"block.create.mechanical_plough.tooltip.behaviour1": "_Casse les blocs_ avec lesquels _on ne peut pas entrer en collision_, tels que les torches, les sentiers ou les couches de neige. _Applique_ son _mouvement_ aux _entités_ sans les blesser. _Bêche les blocs de terre_ comme si une houe était utilisée sur ceux-ci.",
"block.create.mechanical_saw.tooltip": "SCIE MÉCANIQUE", "block.create.mechanical_saw.tooltip": "SCIE MÉCANIQUE",
"block.create.mechanical_saw.tooltip.summary": "Convient pour _couper_ des _arbres_ efficacement et pour _tailler_ des _blocs_ dans leurs homologues menuisés. Il est déplaceable à l'aide de _pistons_ _mécaniques_ ou _roulements_.", "block.create.mechanical_saw.tooltip.summary": "Convient pour _couper_ des _rotors_ efficacement et pour _tailler_ des _blocs_ dans leurs homologues menuisés. Il est déplaceable à l'aide de _pistons_ _mécaniques_ ou _roulements_.",
"block.create.mechanical_saw.tooltip.condition1": "Lorsque tourné vers le haut", "block.create.mechanical_saw.tooltip.condition1": "Quand tourné vers le haut",
"block.create.mechanical_saw.tooltip.behaviour1": "Applique les _recettes_ de _sciage_ et de _taillerie_ aux éléments jetés ou insérés dedans. Lorsque plusieurs sorties sont possibles, il les parcourt à moins qu'un _filtre_ ne soit affecté.", "block.create.mechanical_saw.tooltip.behaviour1": "Applique les _recettes_ de _sciage_ et de _taillerie_ aux éléments jetés ou insérés dedans. Quand plusieurs sorties sont possibles, il les parcourt à moins qu'un _filtre_ ne soit affecté.",
"block.create.mechanical_saw.tooltip.condition2": "Lorsqu'à l'horizontal", "block.create.mechanical_saw.tooltip.condition2": "Lorsqu'à l'horizontal",
"block.create.mechanical_saw.tooltip.behaviour2": "_Casse_ les _troncs_ devant elle. Si le tronc a supportait un arbre, _l'arbre_ _tombera_ loin de la scie.", "block.create.mechanical_saw.tooltip.behaviour2": "_Casse_ les _troncs_ devant elle. Si le tronc a supportait un rotor, _le rotor_ _tombera_ loin de la scie.",
"block.create.mechanical_saw.tooltip.condition3": "Lorsqu'en mouvement", "block.create.mechanical_saw.tooltip.condition3": "Lorsqu'en mouvement",
"block.create.mechanical_saw.tooltip.behaviour3": "_Coupe_ tous les _arbres_ avec lesquels la scie entre en collision.", "block.create.mechanical_saw.tooltip.behaviour3": "_Coupe_ tous les _rotors_ avec lesquels la scie entre en collision.",
"block.create.stockpile_switch.tooltip": "DÉTÉCTEUR DE STOCKAGE", "block.create.stockpile_switch.tooltip": "DÉTÉCTEUR DE STOCKAGE",
"block.create.stockpile_switch.tooltip.summary": "Bascule un signal Redstone basé sur _l'espace_ _de_ _stockage_ dans le conteneur attaché.", "block.create.stockpile_switch.tooltip.summary": "Bascule un signal Redstone basé sur _l'espace_ _de_ _stockage_ dans le conteneur attaché.",
"block.create.stockpile_switch.tooltip.condition1": "Lorsqu'en dessous de la limite de stockage minimum", "block.create.stockpile_switch.tooltip.condition1": "Lorsqu'en dessous de la limite de stockage minimum",
"block.create.stockpile_switch.tooltip.behaviour1": "Arrête de fournir de _l'énergie_", "block.create.stockpile_switch.tooltip.behaviour1": "Arrête de fournir de _l'énergie_",
"block.create.content_observer.tooltip": "OBSERVATEUR DE CONTENU",
"block.create.content_observer.tooltip.summary": "_Détecte les objets_ à l'intérieur des _conteneurs_ et des _transporteurs_ correspondant à un _filtre_ configuré. Tant que l'_inventaire_, le _tapis roulant_ ou la _glissière_ observé _contient_ un objet correspondant, ce composant émet un _signal de redstone_. Quand un _entonnoir_ observé _transfère_ un objet correspondant, ce composant émet une _impulsion de redstone_.",
"block.create.redstone_link.tooltip": "LIAISON REDSTONE", "block.create.redstone_link.tooltip": "LIEN DE REDSTONE",
"block.create.redstone_link.tooltip.summary": "Points de terminaison pour les connexions de _redstone_ _sans-fil_. Peut être attribué des _fréquences_ en utilisant n'importe quel objet. La portée du signal est limitée, quoique raisonnablement loin.", "block.create.redstone_link.tooltip.summary": "Terminaux pour les connexions de _redstone_ _sans-fil_. Peut être attribué des _fréquences_ en utilisant n'importe quel objet. La portée du signal est limitée, nonobstant raisonnablement loin.",
"block.create.redstone_link.tooltip.condition1": "Lorsqu'alimenté", "block.create.redstone_link.tooltip.condition1": "Quand alimenté",
"block.create.redstone_link.tooltip.behaviour1": "La réception de liens de la même _fréquence_ produira un signal redstone.", "block.create.redstone_link.tooltip.behaviour1": "Les liens de la même _fréquence_ configurés en réception produira un signal redstone.",
"block.create.redstone_link.tooltip.control1": "Clic droit avec un objet", "block.create.redstone_link.tooltip.control1": "Clic droit avec un objet",
"block.create.redstone_link.tooltip.action1": "Définit la _fréquence_ sur cet élément. Un total de _deux_ _différents_ _objets_ peuvent être utilisés en combinaison pour définir une fréquence.", "block.create.redstone_link.tooltip.action1": "Définit la _fréquence_ sur cet élément. Un total de _deux_ _différents_ _objets_ peuvent être utilisés en combinaison pour définir une fréquence.",
"block.create.redstone_link.tooltip.control2": "Clic droit en étant accroupi", "block.create.redstone_link.tooltip.control2": "Clic droit en étant accroupi",
"block.create.redstone_link.tooltip.action2": "TBascule entre le mode _receveur_ et _transmetteur_.", "block.create.redstone_link.tooltip.action2": "Bascule entre le mode _récepteur_ et _transmetteur_.",
"block.create.redstone_contact.tooltip": "redstone_contact REDSTONE", "block.create.redstone_contact.tooltip": "CONTACT DE REDSTONE",
"block.create.redstone_contact.tooltip.summary": "N'émet de l'énergie que par paires. Il est mobile avec _pistons_ _mécaniques_ ou _roulements_.", "block.create.redstone_contact.tooltip.summary": "N'émet de l'énergie que par paires. Il est mobile avec des _pistons_ _mécaniques_ ou _roulements_.",
"block.create.redstone_contact.tooltip.condition1": "Lorsque tourné vers un autre redstone_contact", "block.create.redstone_contact.tooltip.condition1": "Quand tourné vers un autre contact de redstone",
"block.create.redstone_contact.tooltip.behaviour1": "Fournit un _signal_ _redstone_.", "block.create.redstone_contact.tooltip.behaviour1": "Fournit un _signal_ de _redstone_.",
"block.create.redstone_contact.tooltip.condition2": "Lorsqu'en mouvement", "block.create.redstone_contact.tooltip.condition2": "Quand en mouvement",
"block.create.redstone_contact.tooltip.behaviour2": "Déclenche tous les redstone_contacts fixes qu'il passe.", "block.create.redstone_contact.tooltip.behaviour2": "Déclenche tous les contacts de redstone fixes qu'il passe.",
"block.create.adjustable_crate.tooltip": "CAISSE AJUSTABLE", "block.create.adjustable_crate.tooltip": "CAISSE AJUSTABLE",
"block.create.adjustable_crate.tooltip.summary": "Ce _conteneur_ _de_ _stockage_ permet un contrôle manuel de sa capacité. Il peut contenir jusqu'à _16_ _piles_ de n'importe quel objet. Prend en charge les _comparateurs_ _de_ _redstone_.", "block.create.adjustable_crate.tooltip.summary": "Ce _conteneur_ _de_ _stockage_ permet un contrôle manuel de sa capacité. Il peut contenir jusqu'à _16_ _piles_ de n'importe quel objet. Prend en charge les _comparateurs_ _de_ _redstone_.",
@ -957,16 +1003,20 @@
"block.create.creative_crate.tooltip": "CAISSE CRÉATIVE", "block.create.creative_crate.tooltip": "CAISSE CRÉATIVE",
"block.create.creative_crate.tooltip.summary": "Fournit une réserve infinie de blocs aux _Schémacanons_ adjacents.", "block.create.creative_crate.tooltip.summary": "Fournit une réserve infinie de blocs aux _Schémacanons_ adjacents.",
"block.create.creative_crate.tooltip.condition1": "Quand un objet se trouve dans l'emplacement de filtrage",
"block.create.creative_crate.tooltip.behaviour1": "Tout ce qui _extrait_ de ce conteneur aura une _alimentation illimitée_ de l'objet spécifié. Les objets _insérés_ dans cette caisse seront _éliminés_.",
"block.create.deployer.tooltip": "DÉPLOYEUR", "block.create.deployer.tooltip": "DÉPLOYEUR",
"block.create.deployer.tooltip.summary": "_Frappe_, _utilise_ et _active_. Cette machine essaiera _d'imiter_ un _joueur_ autant que possible. Peut _prendre_ et _déposer_ des _objets_ dans _l'inventaire_ adjacent. Peut être affecté à une pile d'éléments en tant que _filtre_.", "block.create.deployer.tooltip.summary": "_Frappe_, _utilise_ et _active_. Cette machine essaiera _d'imiter_ un _joueur_ autant que possible. Peut _prendre_ et _déposer_ des _objets_ dans _l'inventaire_ adjacent. Peut être affecté à une pile d'éléments en tant que _filtre_.",
"block.create.deployer.tooltip.condition1": "Lorsque tourné", "block.create.deployer.tooltip.condition1": "Quand tourné",
"block.create.deployer.tooltip.behaviour1": "Étend son bras et _active_ dans l'espace de bloc _2m_ _devant_ de lui-même.", "block.create.deployer.tooltip.behaviour1": "Étend son bras et _active_ dans l'espace de bloc _2m_ _devant_ de lui-même.",
"block.create.deployer.tooltip.condition2": "Clic droit avec une clé", "block.create.deployer.tooltip.condition2": "Clic droit avec une clé",
"block.create.deployer.tooltip.behaviour2": "Bascule le mode frappe. Dans le _mode_ _frappe_, le déployeur tentera d'utiliser son élément pour _casser_ les _blocs_ ou infliger des _dégats_ aux _entités_.", "block.create.deployer.tooltip.behaviour2": "Bascule le mode frappe. Dans le _mode_ _frappe_, le déployeur tentera d'utiliser son élément pour _casser_ les _blocs_ ou infliger des _dégats_ aux _entités_.",
"block.create.deployer.tooltip.condition3": "Quand un filtre est attribué",
"block.create.deployer.tooltip.behaviour3": "Le déploiement n'est activé que si l'élément tenu _correspond_ au _filtre._ Les éléments ne correspondant pas ne peuvent pas être insérés ; les éléments tenus correspondant au filtre ne peuvent pas être extraits.",
"block.create.brass_casing.tooltip": "BOÎTIER EN LAITON", "block.create.brass_casing.tooltip": "REVÊTEMENT EN LAITON",
"block.create.brass_casing.tooltip.summary": "Boîtier de machine robuste avec une variété d'utilisations. Sans danger pour la décoration.", "block.create.brass_casing.tooltip.summary": "Revêtement de machine robuste avec une variété d'utilisations. Sans danger pour la décoration.",
"block.create.pulse_repeater.tooltip": "RÉPÉTEUR D'IMPULSIONS", "block.create.pulse_repeater.tooltip": "RÉPÉTEUR D'IMPULSIONS",
"block.create.pulse_repeater.tooltip.summary": "Un circuit simple pour couper les signaux de redstone passant à une longueur de _1_ _tick_.", "block.create.pulse_repeater.tooltip.summary": "Un circuit simple pour couper les signaux de redstone passant à une longueur de _1_ _tick_.",
@ -989,20 +1039,36 @@
"block.create.speedometer.tooltip": "COMPTEUR DE VITESSE", "block.create.speedometer.tooltip": "COMPTEUR DE VITESSE",
"block.create.speedometer.tooltip.summary": "Mesure et affiche la _ vitesse de rotation _ des composants cinétiques attachés. Prend en charge les _comparateurs_ _de_ _redstone_.", "block.create.speedometer.tooltip.summary": "Mesure et affiche la _ vitesse de rotation _ des composants cinétiques attachés. Prend en charge les _comparateurs_ _de_ _redstone_.",
"block.create.speedometer.tooltip.condition1": "Lorsque tourné", "block.create.speedometer.tooltip.condition1": "Quand tourné",
"block.create.speedometer.tooltip.behaviour1": "Indique une couleur correspondant au niveau de vitesse. _Vert_ indique une rotation lente, _Bleu_ modérée et _violet_ rapide. Certains composants mécaniques nécessitent une vitesse suffisante pour fonctionner correctement.", "block.create.speedometer.tooltip.behaviour1": "Indique une couleur correspondant au niveau de vitesse. _Vert_ indique une rotation lente, _Bleu_ modérée et _violet_ rapide. Certains composants mécaniques nécessitent une vitesse suffisante pour fonctionner correctement.",
"block.create.stressometer.tooltip": "STRESSOMÈTRE", "block.create.stressometer.tooltip": "STRESSOMÈTRE",
"block.create.stressometer.tooltip.summary": "Mesure et affiche la _stress__ globale du réseau cinétique attaché. Prend en charge les _comparateurs_ _de_ _redstone_.", "block.create.stressometer.tooltip.summary": "Mesure et affiche la _stress__ globale du réseau cinétique attaché. Prend en charge les _comparateurs_ _de_ _redstone_.",
"block.create.stressometer.tooltip.condition1": "Lorsque tourné", "block.create.stressometer.tooltip.condition1": "Quand tourné",
"block.create.stressometer.tooltip.behaviour1": "Indique une couleur correspondant au niveau de contrainte. Les _réseaux_ _surchargés_ cesseront de bouger. Le stress peut être soulagé en ajoutant plus de _sources_ _rotationnelles_ au réseau.", "block.create.stressometer.tooltip.behaviour1": "Indique une couleur correspondant au niveau de contrainte. Les _réseaux_ _surchargés_ cesseront de bouger. Le stress peut être soulagé en ajoutant plus de _sources_ _rotationnelles_ au réseau.",
"item.create.sand_paper.tooltip": "PAPIER DE VERRE",
"item.create.sand_paper.tooltip.summary": "Un papier rugueux qui peut être utilisé pour _polir des matériaux_. Peut être appliqué automatiquement à l'aide du déployeur.",
"item.create.sand_paper.tooltip.condition1": "Quand utilisé",
"item.create.sand_paper.tooltip.behaviour1": "Polit les objets qui se tenus dans la _main secondaire_ ou par terre quand on les _regarde_.",
"item.create.super_glue.tooltip": "COLLE EXTRA-FORTE",
"item.create.super_glue.tooltip.summary": "Collez un bloc à un autre, et ils seront à jamais inséparables.",
"item.create.super_glue.tooltip.condition1": "Quand utilisé",
"item.create.super_glue.tooltip.behaviour1": "Rend la face _cliquée_ d'un bloc _collante_. Les blocs attachés aux faces collantes seront entraînés par des _pistons mécaniques_, _des roulements_ et d'autres contrôleurs.",
"item.create.super_glue.tooltip.condition2": "Quand tenu en main secondaire",
"item.create.super_glue.tooltip.behaviour2": "Attache automatiquement les blocs placés de la main principale à la _face_ contre laquelle ils ont été _placés_.",
"item.create.builders_tea.tooltip": "THÉ DU CONSTRUCTEUR",
"item.create.builders_tea.tooltip.summary": "La boisson parfaite pour commencer la journée - _motivante_ et _rasasiante_.",
"item.create.refined_radiance.tooltip": "ÉCLAT RAFFINÉ", "item.create.refined_radiance.tooltip": "ÉCLAT RAFFINÉ",
"item.create.refined_radiance.tooltip.summary": "Un matériau chromatique forgé à partir de _lumière_ _absorbée_.", "item.create.refined_radiance.tooltip.summary": "Un matériau chromatique forgé à partir de _lumière_ _absorbée_.",
"item.create.shadow_steel.tooltip": "ACIER SOMBRE", "item.create.shadow_steel.tooltip": "ACIER SOMBRE",
"item.create.shadow_steel.tooltip.summary": "Un matériau chromatique forgé _dans_ _le_ _néant_.", "item.create.shadow_steel.tooltip.summary": "Un matériau chromatique forgé _dans_ _le_ _néant_.",
"item.create.minecart_coupling.tooltip": "LIEN POUR WAGONS",
"item.create.crafter_slot_cover.tooltip": "COUVERCLE D'EMPLACEMENT", "item.create.crafter_slot_cover.tooltip": "COUVERCLE D'EMPLACEMENT",
"item.create.crafter_slot_cover.tooltip.summary": "Utilisé pour marquer un _établi_ _mécanique_ comme un emplacement vide dans une recette. Les établis ne doivent pas nécessairement former une grille carrée complète. C'est utile quand il y a des recettes où les _ingredients_ _sont_ _en_ _diagonale_ les uns aux autres.", "item.create.crafter_slot_cover.tooltip.summary": "Utilisé pour marquer un _établi_ _mécanique_ comme un emplacement vide dans une recette. Les établis ne doivent pas nécessairement former une grille carrée complète. C'est utile quand il y a des recettes où les _ingredients_ _sont_ _en_ _diagonale_ les uns aux autres.",
@ -1012,7 +1078,7 @@
"create.tooltip.randomWipDescription0": "Veuillez garder cet objet hors de portée des enfants.", "create.tooltip.randomWipDescription0": "Veuillez garder cet objet hors de portée des enfants.",
"create.tooltip.randomWipDescription1": "Un bébé panda meurt chaque fois que vous utilisez cet objet. Chaque. Fois.", "create.tooltip.randomWipDescription1": "Un bébé panda meurt chaque fois que vous utilisez cet objet. Chaque. Fois.",
"create.tooltip.randomWipDescription2": "À utiliser à vos risques et périls.", "create.tooltip.randomWipDescription2": "À utiliser à vos risques et périls.",
"create.tooltip.randomWipDescription3": "Ce n'est pas l'objet que vous recherchez, *agites les doigts* veuillez vous disperser.", "create.tooltip.randomWipDescription3": "Ce n'est pas l'objet que vous recherchez, *agite les doigts* circulez.",
"create.tooltip.randomWipDescription4": "Cet objet s'autodétruit en 10 secondes. 10, 9, 8...", "create.tooltip.randomWipDescription4": "Cet objet s'autodétruit en 10 secondes. 10, 9, 8...",
"create.tooltip.randomWipDescription5": "Croyez-moi, c'est inutile.", "create.tooltip.randomWipDescription5": "Croyez-moi, c'est inutile.",
"create.tooltip.randomWipDescription6": "En utilisant cet article, vous êtes responsables et acceptez ses conditions.", "create.tooltip.randomWipDescription6": "En utilisant cet article, vous êtes responsables et acceptez ses conditions.",